You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by am...@apache.org on 2019/06/05 11:08:03 UTC

[ignite] branch gg-19225 created (now ba764c6)

This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a change to branch gg-19225
in repository https://gitbox.apache.org/repos/asf/ignite.git.


      at ba764c6  GG-19225: MVCC: Fix incorrect exception thrown.

This branch includes the following new commits:

     new 9e4cdbc  GG-19132 Add licence to Tests.DotNetCore
     new 9d9c21a  GG-19066 [IGNITE-10983] Check that persistenceEnabled is consistent on all nodes.
     new 4cc49e4  GG-18877 additional heartbeat to prevent FailureProcessor from treating tcp-comm-worker as blocked
     new 374db46  GG-18749 Web console: Fixed template for "Eviction mode". Fixes #71.
     new 629c37a  GG-12665 Use UTC timezone in build date.
     new c4e0f96  GG-18939 Web Console: Fixed dependency generation for Ignite CE libraries. #57
     new f79a2d6  GG-18896 Web Console: Added support for configuration of "Hive storage" and "Hive data source". Fixes #54.
     new 61fc6a5  IGNITE-1903 Missed part
     new 5b47baa  IGNITE-10623 More graceful error handling when node is stopping - Fixes #5623.
     new 0acb359  IGNITE-10178 change tests that fail(Ignite JIRA) to @Ignore(Ignite JIRA). - Fixes #5824.
     new 4af7b7d  GG-18670 [IGNITE-11749] Implement automatic pages history dump on CorruptedTreeException. Contributors: Anton Kalashnikov <ka...@yandex.ru> Ivan Bessonov <be...@gmail.com>
     new 25e91d74 GG-18622 [IGNITE-11780] Split command handler on hierarchy of commands -CE licenses
     new 7bb8f94  GG-19159 GridVersionSelfTest#testVersions hangs
     new 2a32a34  GG-19160 GridDeploymentSelfTest#testRedeploy fails
     new bf3a702  IGNITE-1090 Fixed GridCachePartitionedOptimisticTxNodeRestartTest - Fixes #6140.
     new e545d54  IGNITE-1741 Fixed hanging CacheAffinityCallSelfTest.testAffinityCallNoServerNode - Fixes #5729.
     new b75a023  IGNITE-11702 Awaiting PME in test. - Fixes #6425.
     new 034681f  ignoring tests
     new 3d75874  GG-19180 [GG-19116] Backport: Fix CacheContinuousQueryAsyncFailoverAtomicSelfTest.testFailoverStartStopBackup (#73)
     new 11ff0f6  GG-19181 Web Console: Added exclusions of "jetty" artifacts for "hive" dependency. Fixes #79.
     new 6f01765  GG-19181 Web Console: Add exclusions of org.eclipse.jetty.aggregate artifacts for "hive".
     new 04564b8  GG-19187 Web Console: Fixed selection time units on "Refresh rate" popover.
     new 81b8d85  GG-18917 [IGNITE-11821] Deprecate rebalance properties at CacheConfiguration and move them to IgniteConfiguration level (#6534)
     new 7de25e5  GG-18670 [IGNITE-11749] Implement automatic pages history dump on CorruptedTreeException.
     new b1f748b  GG-13964 control.sh should log actions performed
     new 536d397  GG-19147 Resharper inspections got broken after update
     new 3cb1c9a  GG-17467: Log finish rebuilding all indexes
     new 5dcff9f  GG-18656 attempt to restore connection to failed client may lead to firing SYSTEM_WORKER_BLOCKED failure in exchange-worker
     new 76289ae  GG-19221 [GG-18667]-[IGNITE-11750] Implement locked pages info dump for long-running B+Tree operations
     new b1a49be  GG-19169: Fix wrong mvcc tx detection. This closes #78.
     new ba764c6  GG-19225: MVCC: Fix incorrect exception thrown.

The 31 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[ignite] 16/31: IGNITE-1741 Fixed hanging CacheAffinityCallSelfTest.testAffinityCallNoServerNode - Fixes #5729.

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch gg-19225
in repository https://gitbox.apache.org/repos/asf/ignite.git

commit e545d547d5ce883766ee2c50f499e208fa3193c5
Author: Semyon Boikov <sb...@apache.org>
AuthorDate: Tue Dec 25 11:10:17 2018 +0300

    IGNITE-1741 Fixed hanging CacheAffinityCallSelfTest.testAffinityCallNoServerNode - Fixes #5729.
    
    Signed-off-by: Alexey Goncharuk <al...@gmail.com>
    (cherry picked from commit 175c1d815d848918eab79960910a8a3002143aa0)
---
 .../managers/discovery/GridDiscoveryManager.java   |   6 +-
 .../processors/affinity/GridAffinityProcessor.java | 195 ++++++++++++---------
 .../internal/processors/task/GridTaskWorker.java   |  14 +-
 .../cache/CacheAffinityCallSelfTest.java           |  70 +++++++-
 4 files changed, 193 insertions(+), 92 deletions(-)

diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java
index 42dabdd..552fc2e 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java
@@ -1939,7 +1939,7 @@ public class GridDiscoveryManager extends GridManagerAdapter<DiscoverySpi> {
      * @param topVer Topology version.
      * @return Collection of cache nodes.
      */
-    public Collection<ClusterNode> cacheNodes(@Nullable String cacheName, AffinityTopologyVersion topVer) {
+    public List<ClusterNode> cacheNodes(@Nullable String cacheName, AffinityTopologyVersion topVer) {
         return resolveDiscoCache(CU.cacheId(cacheName), topVer).cacheNodes(cacheName);
     }
 
@@ -2483,7 +2483,7 @@ public class GridDiscoveryManager extends GridManagerAdapter<DiscoverySpi> {
      * @param cacheName Cache name.
      * @param node Node to add
      */
-    private void addToMap(Map<Integer, List<ClusterNode>> cacheMap, String cacheName, ClusterNode rich) {
+    private void addToMap(Map<Integer, List<ClusterNode>> cacheMap, String cacheName, ClusterNode node) {
         List<ClusterNode> cacheNodes = cacheMap.get(CU.cacheId(cacheName));
 
         if (cacheNodes == null) {
@@ -2492,7 +2492,7 @@ public class GridDiscoveryManager extends GridManagerAdapter<DiscoverySpi> {
             cacheMap.put(CU.cacheId(cacheName), cacheNodes);
         }
 
-        cacheNodes.add(rich);
+        cacheNodes.add(node);
     }
 
     /**
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/affinity/GridAffinityProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/affinity/GridAffinityProcessor.java
index 61886b6..67b511c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/affinity/GridAffinityProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/affinity/GridAffinityProcessor.java
@@ -30,21 +30,24 @@ import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.IgniteException;
 import org.apache.ignite.IgniteLogger;
 import org.apache.ignite.binary.BinaryObject;
-import org.apache.ignite.cache.CacheMode;
 import org.apache.ignite.cache.affinity.Affinity;
 import org.apache.ignite.cache.affinity.AffinityFunction;
 import org.apache.ignite.cache.affinity.AffinityKeyMapper;
 import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.cluster.ClusterTopologyException;
 import org.apache.ignite.configuration.CacheConfiguration;
 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.IgniteInternalFuture;
+import org.apache.ignite.internal.cluster.ClusterGroupEmptyCheckedException;
+import org.apache.ignite.internal.cluster.ClusterTopologyCheckedException;
 import org.apache.ignite.internal.managers.eventstorage.GridLocalEventListener;
 import org.apache.ignite.internal.processors.GridProcessorAdapter;
 import org.apache.ignite.internal.processors.cache.CacheObject;
 import org.apache.ignite.internal.processors.cache.CacheObjectContext;
+import org.apache.ignite.internal.processors.cache.DynamicCacheDescriptor;
 import org.apache.ignite.internal.processors.cache.GridCacheAdapter;
 import org.apache.ignite.internal.processors.cache.GridCacheContext;
 import org.apache.ignite.internal.processors.cache.KeyCacheObject;
@@ -53,6 +56,8 @@ import org.apache.ignite.internal.util.GridLeanMap;
 import org.apache.ignite.internal.util.future.GridFinishedFuture;
 import org.apache.ignite.internal.util.future.GridFutureAdapter;
 import org.apache.ignite.internal.util.lang.GridTuple3;
+import org.apache.ignite.internal.util.typedef.CI1;
+import org.apache.ignite.internal.util.typedef.CX1;
 import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.X;
 import org.apache.ignite.internal.util.typedef.internal.A;
@@ -79,12 +84,6 @@ public class GridAffinityProcessor extends GridProcessorAdapter {
     /** Affinity map cleanup delay (ms). */
     private static final long AFFINITY_MAP_CLEAN_UP_DELAY = 3000;
 
-    /** Retries to get affinity in case of error. */
-    private static final int ERROR_RETRIES = 3;
-
-    /** Time to wait between errors (in milliseconds). */
-    private static final long ERROR_WAIT = 500;
-
     /** Log. */
     private final IgniteLogger log;
 
@@ -390,10 +389,19 @@ public class GridAffinityProcessor extends GridProcessorAdapter {
      * @return Affinity cache.
      * @throws IgniteCheckedException In case of error.
      */
-    @SuppressWarnings("ErrorNotRethrown")
     @Nullable private AffinityInfo affinityCache(final String cacheName, AffinityTopologyVersion topVer)
         throws IgniteCheckedException {
+        return affinityCacheFuture(cacheName, topVer).get();
+    }
 
+    /**
+     * @param cacheName Cache name.
+     * @param topVer Topology version.
+     * @return Affinity cache.
+     * @throws IgniteCheckedException In case of error.
+     */
+    public IgniteInternalFuture<AffinityInfo> affinityCacheFuture(final String cacheName, AffinityTopologyVersion topVer)
+        throws IgniteCheckedException {
         assert cacheName != null;
 
         AffinityAssignmentKey key = new AffinityAssignmentKey(cacheName, topVer);
@@ -401,7 +409,7 @@ public class GridAffinityProcessor extends GridProcessorAdapter {
         IgniteInternalFuture<AffinityInfo> fut = affMap.get(key);
 
         if (fut != null)
-            return fut.get();
+            return fut;
 
         GridCacheAdapter<Object, Object> cache = ctx.cache().internalCache(cacheName);
 
@@ -416,7 +424,7 @@ public class GridAffinityProcessor extends GridProcessorAdapter {
                 cctx.gate().enter();
             }
             catch (IllegalStateException ignored) {
-                return null;
+                return new GridFinishedFuture<>((AffinityInfo)null);
             }
 
             try {
@@ -428,99 +436,116 @@ public class GridAffinityProcessor extends GridProcessorAdapter {
                     cctx.cacheObjectContext()
                 );
 
-                IgniteInternalFuture<AffinityInfo> old = affMap.putIfAbsent(key, new GridFinishedFuture<>(info));
+                GridFinishedFuture<AffinityInfo> fut0 = new GridFinishedFuture<>(info);
+
+                IgniteInternalFuture<AffinityInfo> old = affMap.putIfAbsent(key, fut0);
 
                 if (old != null)
-                    info = old.get();
+                    return old;
 
-                return info;
+                return fut0;
             }
             finally {
                 cctx.gate().leave();
             }
         }
 
-        Collection<ClusterNode> cacheNodes = ctx.discovery().cacheNodes(cacheName, topVer);
+        List<ClusterNode> cacheNodes = ctx.discovery().cacheNodes(cacheName, topVer);
 
-        if (F.isEmpty(cacheNodes))
-            return null;
+        DynamicCacheDescriptor desc = ctx.cache().cacheDescriptor(cacheName);
 
-        GridFutureAdapter<AffinityInfo> fut0 = new GridFutureAdapter<>();
+        if (desc == null || F.isEmpty(cacheNodes)) {
+            if (ctx.clientDisconnected())
+                return new GridFinishedFuture<>(new IgniteClientDisconnectedCheckedException(ctx.cluster().clientReconnectFuture(),
+                        "Failed to get affinity mapping, client disconnected."));
 
-        IgniteInternalFuture<AffinityInfo> old = affMap.putIfAbsent(key, fut0);
+            return new GridFinishedFuture<>((AffinityInfo)null);
+        }
 
-        if (old != null)
-            return old.get();
+        if (desc.cacheConfiguration().getCacheMode() == LOCAL)
+            return new GridFinishedFuture<>(new IgniteCheckedException("Failed to map keys for LOCAL cache: " + cacheName));
 
-        int max = ERROR_RETRIES;
-        int cnt = 0;
+        AffinityFuture fut0 = new AffinityFuture(cacheName, topVer, cacheNodes);
 
-        Iterator<ClusterNode> it = cacheNodes.iterator();
+        IgniteInternalFuture<AffinityInfo> old = affMap.putIfAbsent(key, fut0);
 
-        // We are here because affinity has not been fetched yet, or cache mode is LOCAL.
-        while (true) {
-            cnt++;
+        if (old != null)
+            return old;
 
-            if (!it.hasNext())
-                it = cacheNodes.iterator();
+        fut0.getAffinityFromNextNode();
 
-            // Double check since we deal with dynamic view.
-            if (!it.hasNext())
-                // Exception will be caught in this method.
-                throw new IgniteCheckedException("No cache nodes in topology for cache name: " + cacheName);
+        return fut0;
+    }
 
-            ClusterNode n = it.next();
+    /**
+     *
+     */
+    private class AffinityFuture extends GridFutureAdapter<AffinityInfo> {
+        /** */
+        private final String cacheName;
 
-            CacheMode mode = ctx.cache().cacheMode(cacheName);
+        /** */
+        private final AffinityTopologyVersion topVer;
 
-            if (mode == null) {
-                if (ctx.clientDisconnected())
-                    throw new IgniteClientDisconnectedCheckedException(ctx.cluster().clientReconnectFuture(),
-                            "Failed to get affinity mapping, client disconnected.");
+        /** */
+        private final List<ClusterNode> cacheNodes;
 
-                throw new IgniteCheckedException("No cache nodes in topology for cache name: " + cacheName);
-            }
+        /** */
+        private int nodeIdx;
 
-            // Map all keys to a single node, if the cache mode is LOCAL.
-            if (mode == LOCAL) {
-                fut0.onDone(new IgniteCheckedException("Failed to map keys for LOCAL cache."));
+        /**
+         * @param cacheName Cache name.
+         * @param topVer Topology version.
+         * @param cacheNodes Cache nodes.
+         */
+        AffinityFuture(String cacheName, AffinityTopologyVersion topVer, List<ClusterNode> cacheNodes) {
+            this.cacheName = cacheName;
+            this.topVer = topVer;
+            this.cacheNodes = cacheNodes;
+        }
 
-                // Will throw exception.
-                fut0.get();
-            }
+        /**
+         *
+         */
+        void getAffinityFromNextNode() {
+            while (nodeIdx < cacheNodes.size()) {
+                final ClusterNode node = cacheNodes.get(nodeIdx);
 
-            try {
-                // Resolve cache context for remote node.
-                // Set affinity function before counting down on latch.
-                fut0.onDone(affinityInfoFromNode(cacheName, topVer, n));
+                nodeIdx++;
 
-                break;
-            }
-            catch (IgniteCheckedException e) {
-                if (log.isDebugEnabled())
-                    log.debug("Failed to get affinity from node (will retry) [cache=" + cacheName +
-                        ", node=" + U.toShortString(n) + ", msg=" + e.getMessage() + ']');
+                if (!ctx.discovery().alive(node.id()))
+                    continue;
 
-                if (cnt < max) {
-                    U.sleep(ERROR_WAIT);
+                affinityInfoFromNode(cacheName, topVer, node).listen(new CI1<IgniteInternalFuture<AffinityInfo>>() {
+                    @Override public void apply(IgniteInternalFuture<AffinityInfo> fut) {
+                        try {
+                            onDone(fut.get());
+                        }
+                        catch (IgniteCheckedException e) {
+                            if (e instanceof ClusterTopologyCheckedException || X.hasCause(e, ClusterTopologyException.class)) {
+                                if (log.isDebugEnabled())
+                                    log.debug("Failed to get affinity from node, node failed [cache=" + cacheName +
+                                            ", node=" + node.id() + ", msg=" + e.getMessage() + ']');
 
-                    continue;
-                }
+                                getAffinityFromNextNode();
+
+                                return;
+                            }
 
-                affMap.remove(key, fut0);
+                            if (log.isDebugEnabled())
+                                log.debug("Failed to get affinity from node [cache=" + cacheName +
+                                        ", node=" + node.id() + ", msg=" + e.getMessage() + ']');
 
-                fut0.onDone(new IgniteCheckedException("Failed to get affinity mapping from node: " + n, e));
+                            onDone(new IgniteCheckedException("Failed to get affinity mapping from node: " + node.id(), e));
+                        }
+                    }
+                });
 
-                break;
+                return;
             }
-            catch (RuntimeException | Error e) {
-                fut0.onDone(new IgniteCheckedException("Failed to get affinity mapping from node: " + n, e));
 
-                break;
-            }
+            onDone(new ClusterGroupEmptyCheckedException("Failed to get cache affinity, all cache nodes failed: " + cacheName));
         }
-
-        return fut0.get();
     }
 
     /**
@@ -529,26 +554,30 @@ public class GridAffinityProcessor extends GridProcessorAdapter {
      * @param cacheName Name of cache on which affinity is requested.
      * @param topVer Topology version.
      * @param n Node from which affinity is requested.
-     * @return Affinity cached function.
-     * @throws IgniteCheckedException If either local or remote node cannot get deployment for affinity objects.
+     * @return Affinity future.
      */
-    private AffinityInfo affinityInfoFromNode(String cacheName, AffinityTopologyVersion topVer, ClusterNode n)
-        throws IgniteCheckedException {
-        GridTuple3<GridAffinityMessage, GridAffinityMessage, GridAffinityAssignment> t = ctx.closure()
-            .callAsyncNoFailover(BROADCAST, affinityJob(cacheName, topVer), F.asList(n), true/*system pool*/, 0, false).get();
+    private IgniteInternalFuture<AffinityInfo> affinityInfoFromNode(String cacheName, AffinityTopologyVersion topVer, ClusterNode n) {
+        IgniteInternalFuture<GridTuple3<GridAffinityMessage, GridAffinityMessage, GridAffinityAssignment>> fut = ctx.closure()
+            .callAsyncNoFailover(BROADCAST, affinityJob(cacheName, topVer), F.asList(n), true/*system pool*/, 0, false);
+
+        return fut.chain(new CX1<IgniteInternalFuture<GridTuple3<GridAffinityMessage, GridAffinityMessage, GridAffinityAssignment>>, AffinityInfo>() {
+            @Override public AffinityInfo applyx(IgniteInternalFuture<GridTuple3<GridAffinityMessage, GridAffinityMessage, GridAffinityAssignment>> fut) throws IgniteCheckedException {
+                GridTuple3<GridAffinityMessage, GridAffinityMessage, GridAffinityAssignment> t = fut.get();
 
-        AffinityFunction f = (AffinityFunction)unmarshall(ctx, n.id(), t.get1());
-        AffinityKeyMapper m = (AffinityKeyMapper)unmarshall(ctx, n.id(), t.get2());
+                AffinityFunction f = (AffinityFunction)unmarshall(ctx, n.id(), t.get1());
+                AffinityKeyMapper m = (AffinityKeyMapper)unmarshall(ctx, n.id(), t.get2());
 
-        assert m != null;
+                assert m != null;
 
-        // Bring to initial state.
-        f.reset();
-        m.reset();
+                // Bring to initial state.
+                f.reset();
+                m.reset();
 
-        CacheConfiguration ccfg = ctx.cache().cacheConfiguration(cacheName);
+                CacheConfiguration ccfg = ctx.cache().cacheConfiguration(cacheName);
 
-        return new AffinityInfo(f, m, t.get3(), ctx.cacheObjects().contextForCache(ccfg));
+                return new AffinityInfo(f, m, t.get3(), ctx.cacheObjects().contextForCache(ccfg));
+            }
+        });
     }
 
     /**
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/task/GridTaskWorker.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/task/GridTaskWorker.java
index 02e8736..78d1554 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/task/GridTaskWorker.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/task/GridTaskWorker.java
@@ -928,9 +928,21 @@ class GridTaskWorker<T, R> extends GridWorker implements GridTimeoutObject {
                                     mapTopVer = ctx.cache().context().exchange().readyAffinityVersion();
 
                                     affFut = ctx.cache().context().exchange().lastTopologyFuture();
+
+                                    if (affFut == null || affFut.isDone()) {
+                                        affFut = null;
+
+                                        // Need asynchronosly fetch affinity if cache is not started on node .
+                                        if (affCacheName != null && ctx.cache().internalCache(affCacheName) == null) {
+                                            affFut = ctx.affinity().affinityCacheFuture(affCacheName, mapTopVer);
+
+                                            if (affFut.isDone())
+                                                affFut = null;
+                                        }
+                                    }
                                 }
 
-                                if (affFut != null && !affFut.isDone()) {
+                                if (affFut != null) {
                                     waitForAffTop = true;
 
                                     jobRes.resetResponse();
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheAffinityCallSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheAffinityCallSelfTest.java
index 2c5472e..3eb6974 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheAffinityCallSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheAffinityCallSelfTest.java
@@ -17,13 +17,18 @@
 package org.apache.ignite.internal.processors.cache;
 
 import java.util.concurrent.Callable;
+import java.util.concurrent.CyclicBarrier;
+import java.util.concurrent.ThreadLocalRandom;
+
 import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.IgniteCompute;
+import org.apache.ignite.cache.affinity.Affinity;
 import org.apache.ignite.cluster.ClusterNode;
 import org.apache.ignite.cluster.ClusterTopologyException;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.IgniteEx;
 import org.apache.ignite.internal.IgniteInternalFuture;
 import org.apache.ignite.internal.IgniteKernal;
 import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
@@ -142,18 +147,23 @@ public class CacheAffinityCallSelfTest extends GridCommonAbstractTest {
      */
     @Test
     public void testAffinityCallNoServerNode() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-1741");
-
         startGridsMultiThreaded(SRVS + 1);
 
         final Integer key = 1;
 
-        final Ignite client = grid(SRVS);
+        final IgniteEx client = grid(SRVS);
 
         assertTrue(client.configuration().isClientMode());
+        assertNull(client.context().cache().cache(CACHE_NAME));
+
+        final int THREADS = 5;
+
+        CyclicBarrier b = new CyclicBarrier(THREADS + 1);
 
         final IgniteInternalFuture<Object> fut = GridTestUtils.runAsync(new Callable<Object>() {
             @Override public Object call() throws Exception {
+                b.await();
+
                 for (int i = 0; i < SRVS; ++i)
                     stopGrid(i, false);
 
@@ -162,8 +172,16 @@ public class CacheAffinityCallSelfTest extends GridCommonAbstractTest {
         });
 
         try {
-            while (!fut.isDone())
-                client.compute().affinityCall(CACHE_NAME, key, new CheckCallable(key, null));
+            GridTestUtils.runMultiThreaded(new Callable<Object>() {
+                @Override public Void call() throws Exception {
+                    b.await();
+
+                    while (!fut.isDone())
+                        client.compute().affinityCall(CACHE_NAME, key, new CheckCallable(key, null));
+
+                    return null;
+                }
+            }, THREADS, "test-thread");
         }
         catch (ClusterTopologyException e) {
             log.info("Expected error: " + e);
@@ -174,6 +192,48 @@ public class CacheAffinityCallSelfTest extends GridCommonAbstractTest {
     }
 
     /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testAffinityFailoverNoCacheOnClient() throws Exception {
+        startGridsMultiThreaded(SRVS + 1);
+
+        final Integer key = 1;
+
+        final IgniteEx client = grid(SRVS);
+
+        assertTrue(client.configuration().isClientMode());
+
+        final IgniteInternalFuture<Object> fut = GridTestUtils.runAsync(new Callable<Object>() {
+            @Override public Object call() throws Exception {
+                for (int i = 0; i < SRVS - 1; ++i) {
+                    U.sleep(ThreadLocalRandom.current().nextLong(100) + 50);
+
+                    stopGrid(i, false);
+                }
+
+                return null;
+            }
+        });
+
+        try {
+            final Affinity<Integer> aff = client.affinity(CACHE_NAME);
+
+            assertNull(client.context().cache().cache(CACHE_NAME));
+
+            GridTestUtils.runMultiThreaded(new Runnable() {
+                @Override public void run() {
+                    while (!fut.isDone())
+                        assertNotNull(aff.mapKeyToNode(key));
+                }
+            }, 5, "test-thread");
+        }
+        finally {
+            stopAllGrids();
+        }
+    }
+
+    /**
      * Test callable.
      */
     public static class CheckCallable implements IgniteCallable<Object> {


[ignite] 20/31: GG-19181 Web Console: Added exclusions of "jetty" artifacts for "hive" dependency. Fixes #79.

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch gg-19225
in repository https://gitbox.apache.org/repos/asf/ignite.git

commit 11ff0f65a307f86de5788b85cf76ded55d95bb90
Author: Vasiliy Sisko <vs...@gridgain.com>
AuthorDate: Fri May 31 20:49:23 2019 +0700

    GG-19181 Web Console: Added exclusions of "jetty" artifacts for "hive" dependency. Fixes #79.
    
    (cherry picked from commit 0e7bf29443178ac85747e97af2a837e308c37516)
---
 .../generator/generator/Maven.service.js              | 19 +++++++++++++++----
 .../frontend/app/data/pom-dependencies.json           |  2 +-
 2 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/modules/web-console/frontend/app/configuration/generator/generator/Maven.service.js b/modules/web-console/frontend/app/configuration/generator/generator/Maven.service.js
index 9e4e301..b472272 100644
--- a/modules/web-console/frontend/app/configuration/generator/generator/Maven.service.js
+++ b/modules/web-console/frontend/app/configuration/generator/generator/Maven.service.js
@@ -44,8 +44,8 @@ export default class IgniteMavenGenerator {
         sb.append(`<!-- ${comment} -->`);
     }
 
-    addDependency(deps, groupId, artifactId, version, jar, link) {
-        deps.push({groupId, artifactId, version, jar, link});
+    addDependency(deps, groupId, artifactId, version, jar, link, exclude) {
+        deps.push({groupId, artifactId, version, jar, link, exclude});
     }
 
     _extractVersion(igniteVer, version) {
@@ -58,8 +58,8 @@ export default class IgniteMavenGenerator {
         if (_.isNil(deps))
             return;
 
-        _.forEach(_.castArray(deps), ({groupId, artifactId, version, jar, link}) => {
-            this.addDependency(acc, groupId || artifactGrp, artifactId, storedVer || this._extractVersion(igniteVer, version) || dfltVer, jar, link);
+        _.forEach(_.castArray(deps), ({groupId, artifactId, version, jar, link, exclude}) => {
+            this.addDependency(acc, groupId || artifactGrp, artifactId, storedVer || this._extractVersion(igniteVer, version) || dfltVer, jar, link, exclude);
         });
     }
 
@@ -101,6 +101,17 @@ export default class IgniteMavenGenerator {
             if (dep.link)
                 this.addComment(sb, `You may download JDBC driver from: ${dep.link}`);
 
+            if (dep.exclude) {
+                sb.startBlock('<exclusions>');
+                _.forEach(dep.exclude, (e) => {
+                    sb.startBlock('<exclusion>');
+                    this.addProperty(sb, 'groupId', e.groupId);
+                    this.addProperty(sb, 'artifactId', e.artifactId);
+                    sb.endBlock('</exclusion>');
+                });
+                sb.endBlock('</exclusions>');
+            }
+
             sb.endBlock('</dependency>');
         });
 
diff --git a/modules/web-console/frontend/app/data/pom-dependencies.json b/modules/web-console/frontend/app/data/pom-dependencies.json
index e7bc106..b597e6a 100644
--- a/modules/web-console/frontend/app/data/pom-dependencies.json
+++ b/modules/web-console/frontend/app/data/pom-dependencies.json
@@ -16,7 +16,7 @@
         {"groupId": "com.mchange", "artifactId": "mchange-commons-java", "version": "0.2.11"}
     ],
     "Hive": [
-        {"groupId": "org.apache.hive", "artifactId": "hive-jdbc", "version": "3.1.1"},
+        {"groupId": "org.apache.hive", "artifactId": "hive-jdbc", "version": "3.1.1", "exclude": [{ "groupId": "org.eclipse.jetty", "artifactId": "*" }]},
         {"groupId": "com.mchange", "artifactId": "c3p0", "version": "0.9.5.2"},
         {"groupId": "com.mchange", "artifactId": "mchange-commons-java", "version": "0.2.11"}
     ],


[ignite] 24/31: GG-18670 [IGNITE-11749] Implement automatic pages history dump on CorruptedTreeException.

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch gg-19225
in repository https://gitbox.apache.org/repos/asf/ignite.git

commit 7de25e5256e9026c12d051c5f06cff7d91e56c35
Author: Anton Kalashnikov <ka...@yandex.ru>
AuthorDate: Mon Jun 3 17:24:48 2019 +0300

    GG-18670 [IGNITE-11749] Implement automatic pages history dump on CorruptedTreeException.
    
    (cherry picked from commit 1f746e8)
---
 .../wal/scanner/PrintToFileHandler.java            |  5 +-
 .../persistence/wal/scanner/PrintToLogHandler.java |  6 ++-
 .../persistence/wal/scanner/ScannerHandler.java    | 18 +++++++
 .../cache/persistence/wal/scanner/WalScanner.java  | 63 +++++++++++++---------
 .../diagnostic/PageHistoryDiagnoster.java          | 47 ++--------------
 5 files changed, 70 insertions(+), 69 deletions(-)

diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/scanner/PrintToFileHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/scanner/PrintToFileHandler.java
index 4693700..5c72bf0 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/scanner/PrintToFileHandler.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/scanner/PrintToFileHandler.java
@@ -18,7 +18,6 @@ package org.apache.ignite.internal.processors.cache.persistence.wal.scanner;
 
 import java.io.File;
 import java.io.IOException;
-import java.nio.charset.StandardCharsets;
 import java.nio.file.StandardOpenOption;
 import org.apache.ignite.IgniteException;
 import org.apache.ignite.configuration.DataStorageConfiguration;
@@ -29,6 +28,8 @@ import org.apache.ignite.internal.processors.cache.persistence.file.FileIOFactor
 import org.apache.ignite.lang.IgniteBiTuple;
 import org.jetbrains.annotations.Nullable;
 
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.apache.ignite.internal.processors.cache.persistence.wal.scanner.ScannerHandler.toStringRecord;
 import static org.apache.ignite.internal.processors.cache.persistence.wal.scanner.ScannerHandlers.DEFAULT_WAL_RECORD_PREFIX;
 
 /**
@@ -67,7 +68,7 @@ class PrintToFileHandler implements ScannerHandler {
      * @return Bytes repersentation of data to be written in dump file.
      */
     protected byte[] getBytes(IgniteBiTuple<WALPointer, WALRecord> record) {
-        return (DEFAULT_WAL_RECORD_PREFIX + record.get2() + "\n").getBytes(StandardCharsets.UTF_8);
+        return (DEFAULT_WAL_RECORD_PREFIX + toStringRecord(record.get2()) + System.lineSeparator()).getBytes(UTF_8);
     }
 
     /**
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/scanner/PrintToLogHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/scanner/PrintToLogHandler.java
index 2d1af63..2061a44 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/scanner/PrintToLogHandler.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/scanner/PrintToLogHandler.java
@@ -22,6 +22,7 @@ import org.apache.ignite.internal.pagemem.wal.WALPointer;
 import org.apache.ignite.internal.pagemem.wal.record.WALRecord;
 import org.apache.ignite.lang.IgniteBiTuple;
 
+import static org.apache.ignite.internal.processors.cache.persistence.wal.scanner.ScannerHandler.toStringRecord;
 import static org.apache.ignite.internal.processors.cache.persistence.wal.scanner.ScannerHandlers.DEFAULT_WAL_RECORD_PREFIX;
 
 /**
@@ -47,7 +48,10 @@ class PrintToLogHandler implements ScannerHandler {
     @Override public void handle(IgniteBiTuple<WALPointer, WALRecord> record) {
         ensureNotFinished();
 
-        resultString.append(DEFAULT_WAL_RECORD_PREFIX).append(record.get2()).append("\n");
+        resultString
+            .append(DEFAULT_WAL_RECORD_PREFIX)
+            .append(toStringRecord(record.get2()))
+            .append(System.lineSeparator());
     }
 
     /** {@inheritDoc} */
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/scanner/ScannerHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/scanner/ScannerHandler.java
index f88815c..adbfae8 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/scanner/ScannerHandler.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/scanner/ScannerHandler.java
@@ -66,4 +66,22 @@ public interface ScannerHandler {
             }
         };
     }
+
+    /**
+     * Make string from given wal record.
+     *
+     * @param walRecord Source WAL record.
+     * @return Representation of WAL record.
+     */
+    public static String toStringRecord(WALRecord walRecord) {
+        String walRecordStr;
+
+        try {
+            walRecordStr = walRecord != null ? walRecord.toString() : "Record is null";
+        }
+        catch (RuntimeException e) {
+            walRecordStr = "Record : " + walRecord.type() + " - Unable to convert to string representation.";
+        }
+        return walRecordStr;
+    }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/scanner/WalScanner.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/scanner/WalScanner.java
index fe133a0..c475b91 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/scanner/WalScanner.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/scanner/WalScanner.java
@@ -45,21 +45,45 @@ import static org.apache.ignite.internal.processors.cache.persistence.wal.reader
  * Scanning WAL by specific condition.
  */
 public class WalScanner {
-    /** Parameters for iterator. */
-    private final IteratorParametersBuilder parametersBuilder;
-    /** Wal iterator factory. */
-    private final IgniteWalIteratorFactory iteratorFactory;
+    /** Low level WAL iterator. */
+    private final IgniteThrowableSupplier<WALIterator> walIteratorSupplier;
 
     /**
+     * @param preconfiguredIter Preconfgured iterator.
      * @param parametersBuilder Parameters for iterator.
      * @param factory Factory of iterator.
      */
     WalScanner(
+        WALIterator preconfiguredIter,
         IteratorParametersBuilder parametersBuilder,
         IgniteWalIteratorFactory factory
     ) {
-        this.parametersBuilder = parametersBuilder;
-        iteratorFactory = factory == null ? new IgniteWalIteratorFactory() : factory;
+        if (preconfiguredIter != null)
+            walIteratorSupplier = () -> preconfiguredIter;
+        else
+            walIteratorSupplier = () -> standaloneWalIterator(
+                factory == null ? new IgniteWalIteratorFactory() : factory,
+                parametersBuilder
+            );
+    }
+
+    /**
+     * @param iteratorFactory Factory of iterator.
+     * @param parametersBuilder Parameters for iterator.
+     * @return Standalone WAL iterator created by given parameters.
+     * @throws IgniteCheckedException If failed.
+     */
+    private static WALIterator standaloneWalIterator(
+        IgniteWalIteratorFactory iteratorFactory,
+        IteratorParametersBuilder parametersBuilder
+    ) throws IgniteCheckedException {
+        return iteratorFactory.iterator(
+            parametersBuilder.copy().addFilter((type, pointer) ->
+                // PHYSICAL need fo page shanpshot or delta record.
+                // MIXED need for partiton meta state update.
+                type.purpose() == PHYSICAL || type.purpose() == MIXED
+            )
+        );
     }
 
     /**
@@ -85,26 +109,17 @@ public class WalScanner {
             .or(pageOwner(groupAndPageIds0))
             .or(partitionMetaStateUpdate(groupAndParts));
 
-        return new ScanTerminateStep(() -> iterator(filter,
-            parametersBuilder.copy().addFilter((type, pointer) ->
-                // PHYSICAL need fo page shanpshot or delta record.
-                // MIXED need for partiton meta state update.
-                type.purpose() == PHYSICAL || type.purpose() == MIXED
-            )
-        ));
+        return new ScanTerminateStep(() -> new FilteredWalIterator(walIteratorSupplier.get(), filter));
     }
 
     /**
-     * @param filter Record filter.
-     * @param parametersBuilder Iterator parameters for customization.
-     * @return Instance of {@link FilteredWalIterator}.
-     * @throws IgniteCheckedException If initialization of iterator will be failed.
+     * Factory method of {@link WalScanner}.
+     *
+     * @param walIterator Preconfigured WAL iterator.
+     * @return Instance of {@link WalScanner}.
      */
-    @NotNull private FilteredWalIterator iterator(
-        Predicate<IgniteBiTuple<WALPointer, WALRecord>> filter,
-        IteratorParametersBuilder parametersBuilder
-    ) throws IgniteCheckedException {
-        return new FilteredWalIterator(iteratorFactory.iterator(parametersBuilder), filter);
+    public static WalScanner buildWalScanner(WALIterator walIterator) {
+        return new WalScanner(walIterator, null, null);
     }
 
     /**
@@ -114,7 +129,7 @@ public class WalScanner {
      * @return Instance of {@link WalScanner}.
      */
     public static WalScanner buildWalScanner(IteratorParametersBuilder parametersBuilder) {
-        return new WalScanner(parametersBuilder, null);
+        return buildWalScanner(parametersBuilder, null);
     }
 
     /**
@@ -128,7 +143,7 @@ public class WalScanner {
         IteratorParametersBuilder parametersBuilder,
         IgniteWalIteratorFactory factory
     ) {
-        return new WalScanner(parametersBuilder, factory);
+        return new WalScanner(null, parametersBuilder, factory);
     }
 
     /**
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/diagnostic/PageHistoryDiagnoster.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/diagnostic/PageHistoryDiagnoster.java
index 3572fc8..9d1b2fc 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/diagnostic/PageHistoryDiagnoster.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/diagnostic/PageHistoryDiagnoster.java
@@ -21,21 +21,14 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.EnumSet;
-import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
 import java.util.function.BiFunction;
-import java.util.function.Predicate;
-import java.util.stream.Collectors;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.IgniteException;
 import org.apache.ignite.IgniteLogger;
 import org.apache.ignite.internal.GridKernalContext;
-import org.apache.ignite.internal.pagemem.PageIdUtils;
-import org.apache.ignite.internal.pagemem.wal.WALIterator;
-import org.apache.ignite.internal.pagemem.wal.WALPointer;
-import org.apache.ignite.internal.pagemem.wal.record.WALRecord;
 import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
 import org.apache.ignite.internal.processors.cache.persistence.wal.FileDescriptor;
 import org.apache.ignite.internal.processors.cache.persistence.wal.FileWALPointer;
@@ -50,17 +43,13 @@ import org.apache.ignite.internal.processors.cache.persistence.wal.serializer.Re
 import org.apache.ignite.internal.processors.diagnostic.DiagnosticProcessor.DiagnosticFileWriteMode;
 import org.apache.ignite.internal.util.tostring.GridToStringExclude;
 import org.apache.ignite.internal.util.typedef.T2;
-import org.apache.ignite.lang.IgniteBiTuple;
 import org.jetbrains.annotations.NotNull;
 
 import static java.util.Objects.requireNonNull;
 import static org.apache.ignite.internal.processors.cache.persistence.wal.reader.IgniteWalIteratorFactory.IteratorParametersBuilder.withIteratorParameters;
-import static org.apache.ignite.internal.processors.cache.persistence.wal.reader.WalFilters.checkpoint;
-import static org.apache.ignite.internal.processors.cache.persistence.wal.reader.WalFilters.pageOwner;
-import static org.apache.ignite.internal.processors.cache.persistence.wal.reader.WalFilters.partitionMetaStateUpdate;
+import static org.apache.ignite.internal.processors.cache.persistence.wal.scanner.ScannerHandlers.printRawToFile;
 import static org.apache.ignite.internal.processors.cache.persistence.wal.scanner.ScannerHandlers.printToFile;
 import static org.apache.ignite.internal.processors.cache.persistence.wal.scanner.ScannerHandlers.printToLog;
-import static org.apache.ignite.internal.processors.cache.persistence.wal.scanner.ScannerHandlers.printRawToFile;
 import static org.apache.ignite.internal.processors.cache.persistence.wal.scanner.WalScanner.buildWalScanner;
 
 /**
@@ -199,43 +188,17 @@ public class PageHistoryDiagnoster {
         ScannerHandler action,
         FileWALPointer from
     ) throws IgniteCheckedException {
-        IgniteBiTuple<WALPointer, WALRecord> lastReadRec = null;
         // Try scan via WAL manager. More safety way on working node.
         try {
-            Set<T2<Integer, Long>> groupAndPageIds0 = new HashSet<>(builder.pageIds);
-
-            // Collect all (group, partition) partition pairs.
-            Set<T2<Integer, Integer>> groupAndParts = groupAndPageIds0.stream()
-                .map((tup) -> new T2<>(tup.get1(), PageIdUtils.partId(tup.get2())))
-                .collect(Collectors.toSet());
-
-            // Build WAL filter. (Checkoint, Page, Partition meta)
-            Predicate<IgniteBiTuple<WALPointer, WALRecord>> filter = checkpoint()
-                .or(pageOwner(groupAndPageIds0))
-                .or(partitionMetaStateUpdate(groupAndParts));
-
-            try (WALIterator it = wal.replay(from)) {
-                while (it.hasNext()) {
-                    IgniteBiTuple<WALPointer, WALRecord> recTup = lastReadRec = it.next();
-
-                    if (filter.test(recTup))
-                        action.handle(recTup);
-                }
-            }
-            finally {
-                action.finish();
-            }
+            buildWalScanner(wal.replay(from))
+                .findAllRecordsFor(builder.pageIds)
+                .forEach(action);
 
             return;
 
         }
         catch (IgniteCheckedException e) {
-            if (lastReadRec != null) {
-                log.warning("Failed to diagnosric scan via WAL manager, lastReadRec:["
-                    + lastReadRec.get1() + ", " + lastReadRec.get2() + "]",e);
-            }
-            else
-                log.warning("Failed to diagnosric scan via WAL manager", e);
+            log.warning("Failed to diagnosric scan via WAL manager", e);
         }
 
         // Try scan via stand alone iterator is not safety if wal still generated and moving to archive.


[ignite] 28/31: GG-18656 attempt to restore connection to failed client may lead to firing SYSTEM_WORKER_BLOCKED failure in exchange-worker

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch gg-19225
in repository https://gitbox.apache.org/repos/asf/ignite.git

commit 5dcff9f6d73483e28aee4da53e293ac5518d713f
Author: Sergey Chugunov <se...@gmail.com>
AuthorDate: Tue Jun 4 18:19:53 2019 +0300

    GG-18656 attempt to restore connection to failed client may lead to firing SYSTEM_WORKER_BLOCKED failure in exchange-worker
    
    (cherry-picked from commit #c15ef97)
---
 .../cache/GridCachePartitionExchangeManager.java   |  7 ++-
 .../spi/communication/tcp/TcpCommunicationSpi.java | 30 +++++++++-
 .../ignite/internal/IgniteClientFailuresTest.java  | 69 ++++++++++++++++++----
 3 files changed, 91 insertions(+), 15 deletions(-)

diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCachePartitionExchangeManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCachePartitionExchangeManager.java
index 4f5d2fc..46dade4 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCachePartitionExchangeManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCachePartitionExchangeManager.java
@@ -178,6 +178,9 @@ public class GridCachePartitionExchangeManager<K, V> extends GridCacheSharedMana
     /** Stripe id for cluster activation event. */
     private static final int CLUSTER_ACTIVATION_EVT_STRIPE_ID = Integer.MAX_VALUE;
 
+    /** */
+    private static final String EXCHANGE_WORKER_THREAD_NAME = "exchange-worker";
+
     /** Atomic reference for pending partition resend timeout object. */
     private AtomicReference<ResendTimeoutObject> pendingResend = new AtomicReference<>();
 
@@ -719,7 +722,7 @@ public class GridCachePartitionExchangeManager<K, V> extends GridCacheSharedMana
         else if (reconnect)
             reconnectExchangeFut.onDone();
 
-        new IgniteThread(cctx.igniteInstanceName(), "exchange-worker", exchWorker).start();
+        new IgniteThread(cctx.igniteInstanceName(), exchWorker.name(), exchWorker).start();
 
         if (reconnect) {
             if (fut != null) {
@@ -2753,7 +2756,7 @@ public class GridCachePartitionExchangeManager<K, V> extends GridCacheSharedMana
          * Constructor.
          */
         private ExchangeWorker() {
-            super(cctx.igniteInstanceName(), "partition-exchanger", GridCachePartitionExchangeManager.this.log,
+            super(cctx.igniteInstanceName(), EXCHANGE_WORKER_THREAD_NAME, GridCachePartitionExchangeManager.this.log,
                 cctx.kernalContext().workersRegistry());
         }
 
diff --git a/modules/core/src/main/java/org/apache/ignite/spi/communication/tcp/TcpCommunicationSpi.java b/modules/core/src/main/java/org/apache/ignite/spi/communication/tcp/TcpCommunicationSpi.java
index 2a9fb9a..16b7983 100755
--- a/modules/core/src/main/java/org/apache/ignite/spi/communication/tcp/TcpCommunicationSpi.java
+++ b/modules/core/src/main/java/org/apache/ignite/spi/communication/tcp/TcpCommunicationSpi.java
@@ -66,6 +66,7 @@ import org.apache.ignite.failure.FailureType;
 import org.apache.ignite.internal.IgniteClientDisconnectedCheckedException;
 import org.apache.ignite.internal.IgniteEx;
 import org.apache.ignite.internal.IgniteFeatures;
+import org.apache.ignite.internal.IgniteFutureTimeoutCheckedException;
 import org.apache.ignite.internal.IgniteInternalFuture;
 import org.apache.ignite.internal.IgniteInterruptedCheckedException;
 import org.apache.ignite.internal.IgniteKernal;
@@ -2954,7 +2955,34 @@ public class TcpCommunicationSpi extends IgniteSpiAdapter implements Communicati
                 else
                     fut = oldFut;
 
-                client = fut.get();
+                WorkersRegistry registry = getWorkersRegistry(ignite);
+
+                long clientReserveWaitTimeout = registry != null ? registry.getSystemWorkerBlockedTimeout() / 3
+                    : connTimeout / 3;
+
+                long currTimeout = System.currentTimeMillis();
+
+                // This cycle will eventually quit when future is completed by concurrent thread reserving client.
+                while (true) {
+                    try {
+                        client = fut.get(clientReserveWaitTimeout, TimeUnit.MILLISECONDS);
+
+                        break;
+                    }
+                    catch (IgniteFutureTimeoutCheckedException ignored) {
+                        currTimeout += clientReserveWaitTimeout;
+
+                        if (log.isDebugEnabled())
+                            log.debug("Still waiting for reestablishing connection to node [nodeId=" + node.id() + ", waitingTime=" + currTimeout + "ms]");
+
+                        if (registry != null) {
+                            GridWorker wrkr = registry.worker(Thread.currentThread().getName());
+
+                            if (wrkr != null)
+                                wrkr.updateHeartbeat();
+                        }
+                    }
+                }
 
                 if (client == null) {
                     if (isLocalNodeDisconnected())
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/IgniteClientFailuresTest.java b/modules/core/src/test/java/org/apache/ignite/internal/IgniteClientFailuresTest.java
index 82522ae..f1d12f2 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/IgniteClientFailuresTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/IgniteClientFailuresTest.java
@@ -18,6 +18,7 @@ package org.apache.ignite.internal;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.failure.FailureType;
 import org.apache.ignite.internal.cluster.IgniteClusterEx;
 import org.apache.ignite.internal.managers.GridManagerAdapter;
 import org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi;
@@ -35,7 +36,7 @@ import org.junit.Test;
  */
 public class IgniteClientFailuresTest extends GridCommonAbstractTest {
     /** */
-    private boolean clientMode;
+    private static final String EXCHANGE_WORKER_BLOCKED_MSG = "threadName=exchange-worker, blockedFor=";
 
     /** */
     private GridStringLogger inMemoryLog;
@@ -44,13 +45,15 @@ public class IgniteClientFailuresTest extends GridCommonAbstractTest {
     @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
         IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
 
-        cfg.setClientMode(clientMode);
-
-        if (!clientMode) {
+        if (igniteInstanceName.contains("client"))
+            cfg.setClientMode(true);
+        else {
             cfg.setClientFailureDetectionTimeout(10_000);
 
             cfg.setSystemWorkerBlockedTimeout(5_000);
 
+            cfg.setNetworkTimeout(5_000);
+
             cfg.setGridLogger(inMemoryLog);
         }
 
@@ -77,13 +80,15 @@ public class IgniteClientFailuresTest extends GridCommonAbstractTest {
      */
     @Test
     public void testNoMessagesFromFailureProcessor() throws Exception {
-        inMemoryLog = new GridStringLogger(false, new GridTestLog4jLogger());
+        GridStringLogger strLog = new GridStringLogger(false, new GridTestLog4jLogger());
+
+        strLog.logLength(1024 * 1024);
 
-        inMemoryLog.logLength(1024 * 1024);
+        inMemoryLog = strLog;
 
         IgniteEx srv = startGrid(0);
 
-        clientMode = true;
+        inMemoryLog = null;
 
         IgniteEx client00 = startGrid("client00");
 
@@ -99,7 +104,7 @@ public class IgniteClientFailuresTest extends GridCommonAbstractTest {
 
         assertTrue(waitRes);
 
-        assertFalse(inMemoryLog.toString().contains("name=tcp-comm-worker"));
+        assertFalse(strLog.toString().contains("name=tcp-comm-worker"));
     }
 
     /**
@@ -112,12 +117,8 @@ public class IgniteClientFailuresTest extends GridCommonAbstractTest {
     public void testFailedClientLeavesTopologyAfterTimeout() throws Exception {
         IgniteEx srv0 = startGrid(0);
 
-        clientMode = true;
-
         IgniteEx client00 = startGrid("client00");
 
-        Thread.sleep(5_000);
-
         client00.getOrCreateCache(new CacheConfiguration<>("cache0"));
 
         breakClient(client00);
@@ -138,6 +139,50 @@ public class IgniteClientFailuresTest extends GridCommonAbstractTest {
         assertTrue(waitRes);
     }
 
+    /**
+     * Test verifies that when some sys thread (on server node) tries to re-establish connection to failed client
+     * and exchange-worker gets blocked waiting for it (e.g. to send partitions full map)
+     * it is not treated as {@link FailureType#SYSTEM_WORKER_BLOCKED}
+     * because this waiting is finite and part of normal operations.
+     *
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testExchangeWorkerIsNotTreatedAsBlockedWhenClientNodeFails() throws Exception {
+        GridStringLogger strLog = new GridStringLogger(false, new GridTestLog4jLogger());
+
+        strLog.logLength(1024 * 1024);
+
+        inMemoryLog = strLog;
+
+        IgniteEx srv0 = startGrid(0);
+
+        inMemoryLog = null;
+
+        IgniteEx client00 = startGrid("client00");
+
+        client00.getOrCreateCache(new CacheConfiguration<>("cache0"));
+
+        startGrid(1);
+
+        breakClient(client00);
+
+        final IgniteClusterEx cl = srv0.cluster();
+
+        assertEquals(3, cl.topology(cl.topologyVersion()).size());
+
+        startGrid("client01");
+
+        boolean waitRes = GridTestUtils.waitForCondition(() -> (cl.topology(cl.topologyVersion()).size() == 3),
+            20_000);
+
+        assertTrue(waitRes);
+
+        String logRes = strLog.toString();
+
+        assertFalse(logRes.contains(EXCHANGE_WORKER_BLOCKED_MSG));
+    }
+
     /** */
     private void checkCacheOperations(IgniteCache cache) {
         for (int i = 0; i < 100; i++)


[ignite] 07/31: GG-18896 Web Console: Added support for configuration of "Hive storage" and "Hive data source". Fixes #54.

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch gg-19225
in repository https://gitbox.apache.org/repos/asf/ignite.git

commit f79a2d6cc4aaa6f99e751a9ee84a35f355418cf4
Author: Vasiliy Sisko <vs...@gridgain.com>
AuthorDate: Thu May 30 16:25:22 2019 +0700

    GG-18896 Web Console: Added support for configuration of "Hive storage" and "Hive data source". Fixes #54.
    
    (cherry picked from commit 465689cdc323b2af3cc29d1311808990d15b2c97)
---
 modules/web-console/backend/app/schemas.js         |  26 ++++-
 .../components/modal-import-models/component.js    |  29 +++--
 .../components/cache-edit-form/controller.ts       |   4 +
 .../components/cache-edit-form/templates/store.pug | 130 ++++++++++++++++++++-
 .../generator/generator/ConfigurationGenerator.js  | 108 ++++++++++-------
 .../generator/generator/JavaTransformer.service.js |   6 +-
 .../generator/generator/Readme.service.js          |   4 +-
 .../generator/generator/defaults/Cache.service.js  |   7 ++
 .../frontend/app/configuration/mixins.pug          |   4 +-
 .../frontend/app/configuration/services/Caches.ts  |   7 ++
 .../web-console/frontend/app/data/dialects.json    |   3 +-
 .../frontend/app/data/pom-dependencies.json        |   5 +
 .../frontend/app/services/LegacyUtils.service.js   |   3 +-
 13 files changed, 272 insertions(+), 64 deletions(-)

diff --git a/modules/web-console/backend/app/schemas.js b/modules/web-console/backend/app/schemas.js
index 0191f4f..6cacf78 100644
--- a/modules/web-console/backend/app/schemas.js
+++ b/modules/web-console/backend/app/schemas.js
@@ -243,13 +243,29 @@ module.exports.factory = function() {
         cacheStoreFactory: {
             kind: {
                 type: String,
-                enum: ['CacheJdbcPojoStoreFactory', 'CacheJdbcBlobStoreFactory', 'CacheHibernateBlobStoreFactory']
+                enum: ['HiveCacheJdbcPojoStoreFactory', 'CacheJdbcPojoStoreFactory', 'CacheJdbcBlobStoreFactory', 'CacheHibernateBlobStoreFactory']
+            },
+            HiveCacheJdbcPojoStoreFactory: {
+                dataSourceBean: String,
+                dialect: {
+                    type: String,
+                    enum: ['Generic', 'Oracle', 'DB2', 'SQLServer', 'MySQL', 'PostgreSQL', 'H2', 'Hive']
+                },
+                implementationVersion: String,
+                batchSize: Number,
+                maximumPoolSize: Number,
+                maximumWriteAttempts: Number,
+                parallelLoadCacheMinimumThreshold: Number,
+                hasher: String,
+                transformer: String,
+                sqlEscapeAll: Boolean,
+                streamerEnabled: {type: Boolean, default: true}
             },
             CacheJdbcPojoStoreFactory: {
                 dataSourceBean: String,
                 dialect: {
                     type: String,
-                    enum: ['Generic', 'Oracle', 'DB2', 'SQLServer', 'MySQL', 'PostgreSQL', 'H2']
+                    enum: ['Generic', 'Oracle', 'DB2', 'SQLServer', 'MySQL', 'PostgreSQL', 'H2', 'Hive']
                 },
                 implementationVersion: String,
                 batchSize: Number,
@@ -267,7 +283,7 @@ module.exports.factory = function() {
                 dataSourceBean: String,
                 dialect: {
                     type: String,
-                    enum: ['Generic', 'Oracle', 'DB2', 'SQLServer', 'MySQL', 'PostgreSQL', 'H2']
+                    enum: ['Generic', 'Oracle', 'DB2', 'SQLServer', 'MySQL', 'PostgreSQL', 'H2', 'Hive']
                 },
                 initSchema: Boolean,
                 createTableQuery: String,
@@ -589,7 +605,7 @@ module.exports.factory = function() {
                 dataSourceBean: String,
                 dialect: {
                     type: String,
-                    enum: ['Generic', 'Oracle', 'DB2', 'SQLServer', 'MySQL', 'PostgreSQL', 'H2']
+                    enum: ['Generic', 'Oracle', 'DB2', 'SQLServer', 'MySQL', 'PostgreSQL', 'H2', 'Hive']
                 }
             },
             SharedFs: {
@@ -951,7 +967,7 @@ module.exports.factory = function() {
                 dataSourceBean: String,
                 dialect: {
                     type: String,
-                    enum: ['Generic', 'Oracle', 'DB2', 'SQLServer', 'MySQL', 'PostgreSQL', 'H2']
+                    enum: ['Generic', 'Oracle', 'DB2', 'SQLServer', 'MySQL', 'PostgreSQL', 'H2', 'Hive']
                 },
                 user: String,
                 checkpointTableName: String,
diff --git a/modules/web-console/frontend/app/configuration/components/modal-import-models/component.js b/modules/web-console/frontend/app/configuration/components/modal-import-models/component.js
index 722c6b7..ee00805 100644
--- a/modules/web-console/frontend/app/configuration/components/modal-import-models/component.js
+++ b/modules/web-console/frontend/app/configuration/components/modal-import-models/component.js
@@ -93,7 +93,7 @@ export class ModalImportModels {
     /** @type {ng.ICompiledExpression} */
     onHide;
 
-    static $inject = ['$uiRouter', 'ConfigSelectors', 'ConfigEffects', 'ConfigureState', 'IgniteConfirm', 'IgniteConfirmBatch', 'IgniteFocus', 'SqlTypes', 'JavaTypes', 'IgniteMessages', '$scope', '$rootScope', 'AgentManager', 'IgniteActivitiesData', 'IgniteLoading', 'IgniteFormUtils', 'IgniteLegacyUtils'];
+    static $inject = ['$uiRouter', 'ConfigSelectors', 'ConfigEffects', 'ConfigureState', 'IgniteConfirm', 'IgniteConfirmBatch', 'IgniteFocus', 'SqlTypes', 'JavaTypes', 'IgniteMessages', '$scope', '$rootScope', 'AgentManager', 'IgniteActivitiesData', 'IgniteLoading', 'IgniteFormUtils', 'IgniteLegacyUtils', 'IgniteVersion'];
 
     /**
      * @param {UIRouter} $uiRouter
@@ -108,7 +108,7 @@ export class ModalImportModels {
      * @param {AgentManager} agentMgr
      * @param {ActivitiesData} ActivitiesData
      */
-    constructor($uiRouter, ConfigSelectors, ConfigEffects, ConfigureState, Confirm, ConfirmBatch, Focus, SqlTypes, JavaTypes, Messages, $scope, $root, agentMgr, ActivitiesData, Loading, FormUtils, LegacyUtils) {
+    constructor($uiRouter, ConfigSelectors, ConfigEffects, ConfigureState, Confirm, ConfirmBatch, Focus, SqlTypes, JavaTypes, Messages, $scope, $root, agentMgr, ActivitiesData, Loading, FormUtils, LegacyUtils, IgniteVersion) {
         this.$uiRouter = $uiRouter;
         this.ConfirmBatch = ConfirmBatch;
         this.ConfigSelectors = ConfigSelectors;
@@ -120,7 +120,7 @@ export class ModalImportModels {
         this.JavaTypes = JavaTypes;
         this.SqlTypes = SqlTypes;
         this.ActivitiesData = ActivitiesData;
-        Object.assign(this, {Confirm, Focus, Messages, Loading, FormUtils, LegacyUtils});
+        Object.assign(this, {Confirm, Focus, Messages, Loading, FormUtils, LegacyUtils, IgniteVersion});
     }
 
     loadData() {
@@ -389,6 +389,12 @@ export class ModalImportModels {
                 jdbcDriverClass: 'org.h2.Driver',
                 jdbcUrl: 'jdbc:h2:tcp://[host]/[database]',
                 user: 'sa'
+            },
+            {
+                db: 'Hive',
+                jdbcDriverClass: 'org.apache.hive.jdbc.HiveDriver',
+                jdbcUrl: 'jdbc:hive2://[host]:[port]/[database]',
+                user: 'hiveuser'
             }
         ];
 
@@ -820,13 +826,18 @@ export class ModalImportModels {
 
                         const catalog = $scope.importDomain.catalog;
 
+                        const dsFactoryBean = {
+                            dataSourceBean: 'ds' + dialect + '_' + catalog,
+                            dialect,
+                            implementationVersion: $scope.selectedPreset.jdbcDriverImplementationVersion
+                        };
+
                         newCache.cacheStoreFactory = {
-                            kind: 'CacheJdbcPojoStoreFactory',
-                            CacheJdbcPojoStoreFactory: {
-                                dataSourceBean: 'ds' + dialect + '_' + catalog,
-                                dialect,
-                                implementationVersion: $scope.selectedPreset.jdbcDriverImplementationVersion
-                            },
+                            kind: dialect === 'Hive' && this.IgniteVersion.currentSbj.getValue().hiveVersion
+                                ? 'HiveCacheJdbcPojoStoreFactory'
+                                : 'CacheJdbcPojoStoreFactory',
+                            HiveCacheJdbcPojoStoreFactory: dsFactoryBean,
+                            CacheJdbcPojoStoreFactory: dsFactoryBean,
                             CacheJdbcBlobStoreFactory: { connectVia: 'DataSource' }
                         };
                     }
diff --git a/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/controller.ts b/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/controller.ts
index 7101d95..b9cdd70 100644
--- a/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/controller.ts
+++ b/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/controller.ts
@@ -56,6 +56,10 @@ export default class CacheEditFormController {
 
             if (this.available(['1.0.0', '2.0.0']))
                 this.$scope.affinityFunction.splice(1, 0, {value: 'Fair', label: 'Fair'});
+
+            if (!this.IgniteVersion.currentSbj.getValue().hiveVersion
+                && _.get(this.clonedCache, 'cacheStoreFactory.kind') === 'HiveCacheJdbcPojoStoreFactory')
+                this.clonedCache.cacheStoreFactory.kind = null;
         };
 
         rebuildDropdowns();
diff --git a/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/store.pug b/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/store.pug
index 5f1559b..c87ff61 100644
--- a/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/store.pug
+++ b/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cache-edit-form/templates/store.pug
@@ -29,7 +29,32 @@ panel-collapsible(ng-form=form on-open=`ui.loadPanel('${form}')`)
         .pca-form-column-6.pc-form-grid-row
             -var storeFactory = `${model}.cacheStoreFactory`;
             -var storeFactoryKind = `${storeFactory}.kind`;
-            .pc-form-grid-col-60
+            .pc-form-grid-col-60(ng-if='$ctrl.IgniteVersion.currentSbj.getValue().hiveVersion')
+                +form-field__dropdown({
+                    label: 'Store factory:',
+                    model: storeFactoryKind,
+                    name: '"cacheStoreFactory_2_7"',
+                    placeholder: '{{ ::$ctrl.Caches.cacheStoreFactory.kind.default }}',
+                    options: '::$ctrl.Caches.cacheStoreFactory.values_2_7',
+                    tip: `Factory for persistent storage for cache data
+                    <ul>
+                        <li>JDBC POJO store factory - Objects are stored in underlying database by using java beans mapping description via reflection backed by JDBC</li>
+                        <li>JDBC BLOB store factory - Objects are stored in underlying database in BLOB format backed by JDBC</li>
+                        <li>Hibernate BLOB store factory - Objects are stored in underlying database in BLOB format backed by Hibernate</li>
+                    </ul>`
+                })(
+                ui-validate=`{
+                        writeThroughOn: '$ctrl.Caches.cacheStoreFactory.storeDisabledValueOff(${model}, ${model}.writeThrough)',
+                        readThroughOn: '$ctrl.Caches.cacheStoreFactory.storeDisabledValueOff(${model}, ${model}.readThrough)',
+                        writeBehindOn: '$ctrl.Caches.cacheStoreFactory.storeDisabledValueOff(${model}, ${model}.writeBehindEnabled)'
+                    }`
+                ui-validate-watch-collection=`"[${model}.readThrough, ${model}.writeThrough, ${model}.writeBehindEnabled]"`
+                ng-model-options='{allowInvalid: true}'
+                )
+                    +form-field__error({ error: 'writeThroughOn', message: 'Write through is enabled but store is not set' })
+                    +form-field__error({ error: 'readThroughOn', message: 'Read through is enabled but store is not set' })
+                    +form-field__error({ error: 'writeBehindOn', message: 'Write-behind is enabled but store is not set' })
+            .pc-form-grid-col-60(ng-if='!$ctrl.IgniteVersion.currentSbj.getValue().hiveVersion')
                 +form-field__dropdown({
                     label: 'Store factory:',
                     model: storeFactoryKind,
@@ -55,6 +80,109 @@ panel-collapsible(ng-form=form on-open=`ui.loadPanel('${form}')`)
                     +form-field__error({ error: 'readThroughOn', message: 'Read through is enabled but store is not set' })
                     +form-field__error({ error: 'writeBehindOn', message: 'Write-behind is enabled but store is not set' })
             .pc-form-group(ng-if=storeFactoryKind)
+                .pc-form-grid-row(ng-if=`$ctrl.available("2.7.0") && ${storeFactoryKind} === 'HiveCacheJdbcPojoStoreFactory'`)
+                    -var pojoStoreFactory = `${storeFactory}.HiveCacheJdbcPojoStoreFactory`
+                    -var required = `${storeFactoryKind} === 'HiveCacheJdbcPojoStoreFactory'`
+
+                    .pc-form-grid-col-30
+                        +form-field__text({
+                            label: 'Data source bean name:',
+                            model: `${pojoStoreFactory}.dataSourceBean`,
+                            name: '"pojoDataSourceBean"',
+                            required: required,
+                            placeholder: 'Input bean name',
+                            tip: 'Name of the data source bean in Spring context'
+                        })(
+                            is-valid-java-identifier
+                            not-java-reserved-word
+                        )
+                            +form-field__error({ error: 'required', message: 'Data source bean name is required' })
+                            +form-field__error({ error: 'isValidJavaIdentifier', message: 'Data source bean name is not a valid Java identifier' })
+                            +form-field__error({ error: 'notJavaReservedWord', message: 'Data source bean name should not be a Java reserved word' })
+                    .pc-form-grid-col-30
+                        +form-field__dialect({
+                            label: 'Dialect:',
+                            model: `${pojoStoreFactory}.dialect`,
+                            name: '"pojoDialect"',
+                            required,
+                            tip: 'Dialect of SQL implemented by a particular RDBMS:',
+                            genericDialectName: 'Generic JDBC dialect',
+                            placeholder: 'Choose JDBC dialect',
+                            change:`$ctrl.clearImplementationVersion(${pojoStoreFactory})`
+                        })
+                    .pc-form-grid-col-60(ng-if=`$ctrl.Caches.requiresProprietaryDrivers(${pojoStoreFactory})`)
+                        a.link-success(ng-href=`{{ $ctrl.Caches.jdbcDriverURL(${pojoStoreFactory}) }}` target='_blank')
+                            | Download JDBC drivers?
+                    .pc-form-grid-col-30
+                        +form-field__number({
+                            label:'Batch size:',
+                            model: `${pojoStoreFactory}.batchSize`,
+                            name: '"pojoBatchSize"',
+                            placeholder: '512',
+                            min: '1',
+                            tip: 'Maximum batch size for writeAll and deleteAll operations'
+                        })
+                    .pc-form-grid-col-30
+                        +form-field__number({
+                            label: 'Thread count:',
+                            model: `${pojoStoreFactory}.maximumPoolSize`,
+                            name: '"pojoMaximumPoolSize"',
+                            placeholder: 'availableProcessors',
+                            min: '1',
+                            tip: 'Maximum workers thread count.<br/>\
+                                 These threads are responsible for load cache.'
+                        })
+                    .pc-form-grid-col-30
+                        +form-field__number({
+                            label: 'Maximum write attempts:',
+                            model: `${pojoStoreFactory}.maximumWriteAttempts`,
+                            name: '"pojoMaximumWriteAttempts"',
+                            placeholder: '2',
+                            min: '0',
+                            tip: 'Maximum write attempts in case of database error'
+                        })
+                    .pc-form-grid-col-30
+                        +form-field__number({
+                            label: 'Parallel load threshold:',
+                            model: `${pojoStoreFactory}.parallelLoadCacheMinimumThreshold`,
+                            name: '"pojoParallelLoadCacheMinimumThreshold"',
+                            placeholder: '512',
+                            min: '0',
+                            tip: 'Parallel load cache minimum threshold.<br/>\
+                                 If <b>0</b> then load sequentially.'
+                        })
+                    .pc-form-grid-col-60
+                        +form-field__java-class({
+                            label: 'Hasher:',
+                            model: `${pojoStoreFactory}.hasher`,
+                            name: '"pojoHasher"',
+                            tip: 'Hash calculator',
+                            validationActive: required
+                        })
+                    .pc-form-grid-col-60
+                        +form-field__java-class({
+                            label: 'Transformer:',
+                            model: `${pojoStoreFactory}.transformer`,
+                            name: '"pojoTransformer"',
+                            tip: 'Types transformer',
+                            validationActive: required
+                        })
+                    .pc-form-grid-col-60
+                        +form-field__checkbox({
+                            label: 'Escape table and filed names',
+                            model:`${pojoStoreFactory}.sqlEscapeAll`,
+                            name: '"sqlEscapeAll"',
+                            tip: 'If enabled than all schema, table and field names will be escaped with double quotes (for example: "tableName"."fieldName").<br/>\
+                                  This enforces case sensitivity for field names and also allows having special characters in table and field names.<br/>\
+                                  Escaped names will be used for CacheJdbcPojoStore internal SQL queries.'
+                        })
+                    .pc-form-grid-col-60
+                        +form-field__checkbox({
+                            label: 'Data streamer',
+                            model:`${pojoStoreFactory}.streamerEnabled`,
+                            name: '"streamerEnabled"',
+                            tip: 'Indicating whether job data streamer is used during load cache.'
+                        })
                 .pc-form-grid-row(ng-if=`${storeFactoryKind} === 'CacheJdbcPojoStoreFactory'`)
                     -var pojoStoreFactory = `${storeFactory}.CacheJdbcPojoStoreFactory`
                     -var required = `${storeFactoryKind} === 'CacheJdbcPojoStoreFactory'`
diff --git a/modules/web-console/frontend/app/configuration/generator/generator/ConfigurationGenerator.js b/modules/web-console/frontend/app/configuration/generator/generator/ConfigurationGenerator.js
index b4fb34f..25e5017 100644
--- a/modules/web-console/frontend/app/configuration/generator/generator/ConfigurationGenerator.js
+++ b/modules/web-console/frontend/app/configuration/generator/generator/ConfigurationGenerator.js
@@ -134,7 +134,7 @@ export default class IgniteConfigurationGenerator {
         this.clusterTransactions(cluster.transactionConfiguration, available, cfg);
         this.clusterUserAttributes(cluster, cfg);
 
-        this.clusterCaches(cluster, cluster.caches, cluster.igfss, available, client, cfg);
+        this.clusterCaches(cluster, cluster.caches, cluster.igfss, available, targetVer, client, cfg);
 
         if (!client)
             this.clusterIgfss(cluster.igfss, available, cfg);
@@ -151,15 +151,18 @@ export default class IgniteConfigurationGenerator {
 
         switch (dialect) {
             case 'Generic':
+            case 'Hive':
                 dsBean = new Bean('com.mchange.v2.c3p0.ComboPooledDataSource', id, {})
                     .property('jdbcUrl', `${id}.jdbc.url`, 'jdbc:your_database');
 
                 break;
+
             case 'Oracle':
                 dsBean = new Bean('oracle.jdbc.pool.OracleDataSource', id, {})
                     .property('URL', `${id}.jdbc.url`, 'jdbc:oracle:thin:@[host]:[port]:[database]');
 
                 break;
+
             case 'DB2':
                 dsBean = new Bean('com.ibm.db2.jcc.DB2DataSource', id, {})
                     .property('serverName', `${id}.jdbc.server_name`, 'YOUR_DATABASE_SERVER_NAME')
@@ -168,11 +171,13 @@ export default class IgniteConfigurationGenerator {
                     .propertyInt('driverType', `${id}.jdbc.driver_type`, 'YOUR_JDBC_DRIVER_TYPE');
 
                 break;
+
             case 'SQLServer':
                 dsBean = new Bean('com.microsoft.sqlserver.jdbc.SQLServerDataSource', id, {})
                     .property('URL', `${id}.jdbc.url`, 'jdbc:sqlserver://[host]:[port][;databaseName=database]');
 
                 break;
+
             case 'MySQL':
                 const dep = storeDeps
                     ? _.find(storeDeps, (d) => d.name === dialect)
@@ -184,11 +189,13 @@ export default class IgniteConfigurationGenerator {
                     .property('URL', `${id}.jdbc.url`, 'jdbc:mysql://[host]:[port]/[database]');
 
                 break;
+
             case 'PostgreSQL':
                 dsBean = new Bean('org.postgresql.ds.PGPoolingDataSource', id, {})
                     .property('url', `${id}.jdbc.url`, 'jdbc:postgresql://[host]:[port]/[database]');
 
                 break;
+
             case 'H2':
                 dsBean = new Bean('org.h2.jdbcx.JdbcDataSource', id, {})
                     .property('URL', `${id}.jdbc.url`, 'jdbc:h2:tcp://[host]/[database]');
@@ -448,7 +455,7 @@ export default class IgniteConfigurationGenerator {
         });
     }
 
-    static clusterCaches(cluster, caches, igfss, available, client, cfg = this.igniteConfigurationBean(cluster)) {
+    static clusterCaches(cluster, caches, igfss, available, targetVer, client, cfg = this.igniteConfigurationBean(cluster)) {
         const usedDataSourceVersions = [];
 
         if (cluster.discovery.kind === 'Jdbc')
@@ -466,7 +473,7 @@ export default class IgniteConfigurationGenerator {
 
         const useDeps = _.uniqWith(ArtifactVersionChecker.latestVersions(usedDataSourceVersions), _.isEqual);
 
-        const ccfgs = _.map(caches, (cache) => this.cacheConfiguration(cache, available, useDeps));
+        const ccfgs = _.map(caches, (cache) => this.cacheConfiguration(cache, available, targetVer, useDeps));
 
         if (!client) {
             _.forEach(igfss, (igfs) => {
@@ -2496,58 +2503,73 @@ export default class IgniteConfigurationGenerator {
         return ccfg;
     }
 
-    // Generate cache store group.
-    static cacheStore(cache, domains, available, deps, ccfg = this.cacheConfigurationBean(cache)) {
-        const kind = _.get(cache, 'cacheStoreFactory.kind');
+    static _baseJdbcPojoStoreFactory(storeFactory, bean, cacheName, domains, available, deps) {
+        const jdbcId = bean.valueOf('dataSourceBean');
 
-        if (kind && cache.cacheStoreFactory[kind]) {
-            let bean = null;
+        bean.dataSource(jdbcId, 'dataSourceBean', this.dataSourceBean(jdbcId, storeFactory.dialect, available, deps, storeFactory.implementationVersion))
+            .beanProperty('dialect', new EmptyBean(this.dialectClsName(storeFactory.dialect)));
 
-            const storeFactory = cache.cacheStoreFactory[kind];
+        bean.intProperty('batchSize')
+            .intProperty('maximumPoolSize')
+            .intProperty('maximumWriteAttempts')
+            .intProperty('parallelLoadCacheMinimumThreshold')
+            .emptyBeanProperty('hasher')
+            .emptyBeanProperty('transformer')
+            .boolProperty('sqlEscapeAll');
+
+        const setType = (typeBean, propName) => {
+            if (javaTypes.nonBuiltInClass(typeBean.valueOf(propName)))
+                typeBean.stringProperty(propName);
+            else
+                typeBean.classProperty(propName);
+        };
 
-            switch (kind) {
-                case 'CacheJdbcPojoStoreFactory':
-                    bean = new Bean('org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStoreFactory', 'cacheStoreFactory',
-                        storeFactory, cacheDflts.cacheStoreFactory.CacheJdbcPojoStoreFactory);
+        const types = _.reduce(domains, (acc, domain) => {
+            if (isNil(domain.databaseTable))
+                return acc;
 
-                    const jdbcId = bean.valueOf('dataSourceBean');
+            const typeBean = this.domainJdbcTypeBean(_.merge({}, domain, {cacheName}))
+                .stringProperty('cacheName');
 
-                    bean.dataSource(jdbcId, 'dataSourceBean', this.dataSourceBean(jdbcId, storeFactory.dialect, available, deps, storeFactory.implementationVersion))
-                        .beanProperty('dialect', new EmptyBean(this.dialectClsName(storeFactory.dialect)));
+            setType(typeBean, 'keyType');
+            setType(typeBean, 'valueType');
 
-                    bean.intProperty('batchSize')
-                        .intProperty('maximumPoolSize')
-                        .intProperty('maximumWriteAttempts')
-                        .intProperty('parallelLoadCacheMinimumThreshold')
-                        .emptyBeanProperty('hasher')
-                        .emptyBeanProperty('transformer')
-                        .boolProperty('sqlEscapeAll');
+            this.domainStore(domain, typeBean);
 
-                    const setType = (typeBean, propName) => {
-                        if (javaTypes.nonBuiltInClass(typeBean.valueOf(propName)))
-                            typeBean.stringProperty(propName);
-                        else
-                            typeBean.classProperty(propName);
-                    };
+            acc.push(typeBean);
 
-                    const types = _.reduce(domains, (acc, domain) => {
-                        if (isNil(domain.databaseTable))
-                            return acc;
+            return acc;
+        }, []);
 
-                        const typeBean = this.domainJdbcTypeBean(_.merge({}, domain, {cacheName: cache.name}))
-                            .stringProperty('cacheName');
+        bean.varArgProperty('types', 'types', types, 'org.apache.ignite.cache.store.jdbc.JdbcType');
+    }
 
-                        setType(typeBean, 'keyType');
-                        setType(typeBean, 'valueType');
+    // Generate cache store group.
+    static cacheStore(cache, domains, available, targetVer, deps, ccfg = this.cacheConfigurationBean(cache)) {
+        const kind = _.get(cache, 'cacheStoreFactory.kind');
 
-                        this.domainStore(domain, typeBean);
+        if (kind && cache.cacheStoreFactory[kind]) {
+            let bean = null;
 
-                        acc.push(typeBean);
+            const storeFactory = cache.cacheStoreFactory[kind];
 
-                        return acc;
-                    }, []);
+            switch (kind) {
+                case 'HiveCacheJdbcPojoStoreFactory':
+                    if (targetVer.hiveVersion) {
+                        bean = new Bean('org.gridgain.cachestore.HiveCacheJdbcPojoStoreFactory', 'cacheStoreFactory',
+                            storeFactory, cacheDflts.cacheStoreFactory.HiveCacheJdbcPojoStoreFactory);
+
+                        this._baseJdbcPojoStoreFactory(storeFactory, bean, cache.name, domains, available, deps);
+
+                        bean.boolProperty('streamerEnabled');
+                    }
+
+                    break;
+                case 'CacheJdbcPojoStoreFactory':
+                    bean = new Bean('org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStoreFactory', 'cacheStoreFactory',
+                        storeFactory, cacheDflts.cacheStoreFactory.CacheJdbcPojoStoreFactory);
 
-                    bean.varArgProperty('types', 'types', types, 'org.apache.ignite.cache.store.jdbc.JdbcType');
+                    this._baseJdbcPojoStoreFactory(storeFactory, bean, cache.name, domains, available, deps);
 
                     break;
                 case 'CacheJdbcBlobStoreFactory':
@@ -2768,12 +2790,12 @@ export default class IgniteConfigurationGenerator {
         ccfg.collectionProperty('qryEntities', 'queryEntities', qryEntities, 'org.apache.ignite.cache.QueryEntity');
     }
 
-    static cacheConfiguration(cache, available, deps = [], ccfg = this.cacheConfigurationBean(cache)) {
+    static cacheConfiguration(cache, available, targetVer, deps = [], ccfg = this.cacheConfigurationBean(cache)) {
         this.cacheGeneral(cache, available, ccfg);
         this.cacheAffinity(cache, available, ccfg);
         this.cacheMemory(cache, available, ccfg);
         this.cacheQuery(cache, cache.domains, available, ccfg);
-        this.cacheStore(cache, cache.domains, available, deps, ccfg);
+        this.cacheStore(cache, cache.domains, available, targetVer, deps, ccfg);
         this.cacheKeyConfiguration(cache.keyConfiguration, available, ccfg);
 
         const igfs = _.get(cache, 'nodeFilter.IGFS.instance');
diff --git a/modules/web-console/frontend/app/configuration/generator/generator/JavaTransformer.service.js b/modules/web-console/frontend/app/configuration/generator/generator/JavaTransformer.service.js
index 9ea0fe3..3b4f0d2 100644
--- a/modules/web-console/frontend/app/configuration/generator/generator/JavaTransformer.service.js
+++ b/modules/web-console/frontend/app/configuration/generator/generator/JavaTransformer.service.js
@@ -23,7 +23,11 @@ import StringBuilder from './StringBuilder';
 import VersionService from 'app/services/Version.service';
 
 const versionService = new VersionService();
-const STORE_FACTORY = ['org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStoreFactory'];
+
+const STORE_FACTORY = [
+    'org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStoreFactory',
+    'org.gridgain.cachestore.HiveCacheJdbcPojoStoreFactory'
+];
 
 // Descriptors for generation of demo data.
 const PREDEFINED_QUERIES = [
diff --git a/modules/web-console/frontend/app/configuration/generator/generator/Readme.service.js b/modules/web-console/frontend/app/configuration/generator/generator/Readme.service.js
index 6b631ee..66e8683 100644
--- a/modules/web-console/frontend/app/configuration/generator/generator/Readme.service.js
+++ b/modules/web-console/frontend/app/configuration/generator/generator/Readme.service.js
@@ -32,7 +32,7 @@ export default class IgniteReadmeGenerator {
      * @returns {string} Generated content.
      */
     generateJDBC(sb = new StringBuilder()) {
-        sb.append('Proprietary JDBC drivers for databases like Oracle, IBM DB2, Microsoft SQL Server are not available on Maven Central repository.');
+        sb.append('Proprietary JDBC drivers for databases like Oracle, IBM DB2 Server are not available on Maven Central repository.');
         sb.append('Drivers should be downloaded manually and copied to this folder.');
 
         return sb.asString();
@@ -69,7 +69,7 @@ export default class IgniteReadmeGenerator {
 
         sb.emptyLine();
 
-        sb.append('Note, in case of using proprietary JDBC drivers (Oracle, IBM DB2, Microsoft SQL Server)');
+        sb.append('Note, in case of using proprietary JDBC drivers (Oracle, IBM DB2)');
         sb.append('you should download them manually and copy into ./jdbc-drivers folder.');
 
         return sb.asString();
diff --git a/modules/web-console/frontend/app/configuration/generator/generator/defaults/Cache.service.js b/modules/web-console/frontend/app/configuration/generator/generator/defaults/Cache.service.js
index ab731d6..d44992c 100644
--- a/modules/web-console/frontend/app/configuration/generator/generator/defaults/Cache.service.js
+++ b/modules/web-console/frontend/app/configuration/generator/generator/defaults/Cache.service.js
@@ -40,6 +40,13 @@ const DFLT_CACHE = {
     storeKeepBinary: false,
     loadPreviousValue: false,
     cacheStoreFactory: {
+        HiveCacheJdbcPojoStoreFactory: {
+            batchSize: 512,
+            maximumWriteAttempts: 2,
+            parallelLoadCacheMinimumThreshold: 512,
+            sqlEscapeAll: false,
+            streamerEnabled: true
+        },
         CacheJdbcPojoStoreFactory: {
             batchSize: 512,
             maximumWriteAttempts: 2,
diff --git a/modules/web-console/frontend/app/configuration/mixins.pug b/modules/web-console/frontend/app/configuration/mixins.pug
index 9794662..b6e47b7 100644
--- a/modules/web-console/frontend/app/configuration/mixins.pug
+++ b/modules/web-console/frontend/app/configuration/mixins.pug
@@ -404,7 +404,8 @@ mixin form-field__dialect({ label, model, name, required, tip, genericDialectNam
                 {value: "SQLServer", label: "Microsoft SQL Server"},\
                 {value: "MySQL", label: "MySQL"},\
                 {value: "PostgreSQL", label: "PostgreSQL"},\
-                {value: "H2", label: "H2 database"}\
+                {value: "H2", label: "H2 database"},\
+                {value: "Hive", label: "Apache Hive"}\
         ]',
         tip: `${ tip }
             <ul>
@@ -415,5 +416,6 @@ mixin form-field__dialect({ label, model, name, required, tip, genericDialectNam
                 <li>MySQL</li>
                 <li>PostgreSQL</li>
                 <li>H2 database</li>
+                <li>Apache Hive</li>
             </ul>`
     })
diff --git a/modules/web-console/frontend/app/configuration/services/Caches.ts b/modules/web-console/frontend/app/configuration/services/Caches.ts
index 4649b1a..1279a2d 100644
--- a/modules/web-console/frontend/app/configuration/services/Caches.ts
+++ b/modules/web-console/frontend/app/configuration/services/Caches.ts
@@ -191,6 +191,13 @@ export default class Caches {
             {value: 'CacheHibernateBlobStoreFactory', label: 'Hibernate BLOB store factory'},
             {value: null, label: 'Not set'}
         ],
+        values_2_7: [
+            {value: 'HiveCacheJdbcPojoStoreFactory', label: 'GridGain Hive JDBC POJO store factory'},
+            {value: 'CacheJdbcPojoStoreFactory', label: 'JDBC POJO store factory'},
+            {value: 'CacheJdbcBlobStoreFactory', label: 'JDBC BLOB store factory'},
+            {value: 'CacheHibernateBlobStoreFactory', label: 'Hibernate BLOB store factory'},
+            {value: null, label: 'Not set'}
+        ],
         storeDisabledValueOff: (cache, value) => {
             return cache && cache.cacheStoreFactory.kind ? true : !value;
         },
diff --git a/modules/web-console/frontend/app/data/dialects.json b/modules/web-console/frontend/app/data/dialects.json
index 007fbc6..87dccfc 100644
--- a/modules/web-console/frontend/app/data/dialects.json
+++ b/modules/web-console/frontend/app/data/dialects.json
@@ -5,5 +5,6 @@
   "SQLServer": "org.apache.ignite.cache.store.jdbc.dialect.SQLServerDialect",
   "MySQL": "org.apache.ignite.cache.store.jdbc.dialect.MySQLDialect",
   "PostgreSQL": "org.apache.ignite.cache.store.jdbc.dialect.BasicJdbcDialect",
-  "H2": "org.apache.ignite.cache.store.jdbc.dialect.H2Dialect"
+  "H2": "org.apache.ignite.cache.store.jdbc.dialect.H2Dialect",
+  "Hive": "org.apache.ignite.cache.store.jdbc.dialect.BasicJdbcDialect"
 }
\ No newline at end of file
diff --git a/modules/web-console/frontend/app/data/pom-dependencies.json b/modules/web-console/frontend/app/data/pom-dependencies.json
index 428455f..e7bc106 100644
--- a/modules/web-console/frontend/app/data/pom-dependencies.json
+++ b/modules/web-console/frontend/app/data/pom-dependencies.json
@@ -15,6 +15,11 @@
         {"groupId": "com.mchange", "artifactId": "c3p0", "version": "0.9.5.2"},
         {"groupId": "com.mchange", "artifactId": "mchange-commons-java", "version": "0.2.11"}
     ],
+    "Hive": [
+        {"groupId": "org.apache.hive", "artifactId": "hive-jdbc", "version": "3.1.1"},
+        {"groupId": "com.mchange", "artifactId": "c3p0", "version": "0.9.5.2"},
+        {"groupId": "com.mchange", "artifactId": "mchange-commons-java", "version": "0.2.11"}
+    ],
     "MySQL": {"groupId": "mysql", "artifactId": "mysql-connector-java", "version": "8.0.15"},
     "PostgreSQL": {"groupId": "org.postgresql", "artifactId": "postgresql", "version": "42.2.5"},
     "H2": {"groupId": "com.h2database", "artifactId": "h2", "version": [
diff --git a/modules/web-console/frontend/app/services/LegacyUtils.service.js b/modules/web-console/frontend/app/services/LegacyUtils.service.js
index 27ed502..2ddbc63 100644
--- a/modules/web-console/frontend/app/services/LegacyUtils.service.js
+++ b/modules/web-console/frontend/app/services/LegacyUtils.service.js
@@ -242,7 +242,8 @@ export default function service(ErrorPopover) {
         {value: 'SQLServer', label: 'Microsoft SQL Server'},
         {value: 'MySQL', label: 'MySQL'},
         {value: 'PostgreSQL', label: 'PostgreSQL'},
-        {value: 'H2', label: 'H2 database'}
+        {value: 'H2', label: 'H2 database'},
+        {value: 'Hive', label: 'Apache Hive'}
     ];
 
     function domainForStoreConfigured(domain) {


[ignite] 25/31: GG-13964 control.sh should log actions performed

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch gg-19225
in repository https://gitbox.apache.org/repos/asf/ignite.git

commit b1f748b68cebc4fd8571c2e7115e28ada30fd81c
Author: vmalin <vm...@gridgain.com>
AuthorDate: Tue Jun 4 11:37:30 2019 +0300

    GG-13964 control.sh should log actions performed
---
 .../internal/commandline/ActivateCommand.java      |  16 ++-
 .../internal/commandline/BaselineCommand.java      |  57 +++++----
 .../ignite/internal/commandline/Command.java       |  19 ++-
 .../internal/commandline/CommandHandler.java       | 141 ++++++++++++++-------
 .../ignite/internal/commandline/CommandList.java   |   7 +
 .../ignite/internal/commandline/CommandLogger.java |  61 ++++++---
 .../internal/commandline/DeactivateCommand.java    |  16 ++-
 .../ignite/internal/commandline/StateCommand.java  |  16 ++-
 .../ignite/internal/commandline/TxCommands.java    | 103 ++++++++-------
 .../ignite/internal/commandline/WalCommands.java   |  55 ++++----
 .../internal/commandline/cache/CacheCommands.java  |  65 +++++-----
 .../commandline/cache/CacheContention.java         |  14 +-
 .../commandline/cache/CacheDistribution.java       |  14 +-
 .../commandline/cache/CacheValidateIndexes.java    |  33 +++--
 .../internal/commandline/cache/CacheViewer.java    |  29 +++--
 .../commandline/cache/FindAndDeleteGarbage.java    |  23 ++--
 .../internal/commandline/cache/IdleVerify.java     |  31 +++--
 .../commandline/cache/ResetLostPartitions.java     |  13 +-
 .../ignite/logger/java/JavaLoggerFileHandler.java  |   2 +-
 .../util/GridCommandHandlerAbstractTest.java       |  13 +-
 .../apache/ignite/util/GridCommandHandlerTest.java |  32 +++--
 21 files changed, 471 insertions(+), 289 deletions(-)

diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/ActivateCommand.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/ActivateCommand.java
index 2bdac5f..998360a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/ActivateCommand.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/ActivateCommand.java
@@ -16,6 +16,7 @@
 
 package org.apache.ignite.internal.commandline;
 
+import java.util.logging.Logger;
 import org.apache.ignite.internal.client.GridClient;
 import org.apache.ignite.internal.client.GridClientClusterState;
 import org.apache.ignite.internal.client.GridClientConfiguration;
@@ -28,8 +29,8 @@ import static org.apache.ignite.internal.commandline.CommandList.ACTIVATE;
  */
 public class ActivateCommand implements Command<Void> {
     /** {@inheritDoc} */
-    @Override public void printUsage(CommandLogger logger) {
-        Command.usage(logger, "Activate cluster:", ACTIVATE);
+    @Override public void printUsage() {
+        Command.usage("Activate cluster:", ACTIVATE);
     }
 
     /**
@@ -38,16 +39,16 @@ public class ActivateCommand implements Command<Void> {
      * @param cfg Client configuration.
      * @throws GridClientException If failed to activate.
      */
-    @Override public Object execute(GridClientConfiguration cfg, CommandLogger logger) throws Exception {
+    @Override public Object execute(GridClientConfiguration cfg, Logger logger) throws Exception {
         try (GridClient client = Command.startClient(cfg)) {
             GridClientClusterState state = client.state();
 
             state.active(true);
 
-            logger.log("Cluster activated");
+            logger.info("Cluster activated");
         }
         catch (Throwable e) {
-            logger.log("Failed to activate cluster.");
+            logger.severe("Failed to activate cluster.");
 
             throw e;
         }
@@ -59,4 +60,9 @@ public class ActivateCommand implements Command<Void> {
     @Override public Void arg() {
         return null;
     }
+
+    /** {@inheritDoc} */
+    @Override public String name() {
+        return ACTIVATE.toCommandName();
+    }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/BaselineCommand.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/BaselineCommand.java
index e5940cb..3ba6e2c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/BaselineCommand.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/BaselineCommand.java
@@ -22,6 +22,7 @@ import java.util.Comparator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.logging.Logger;
 import org.apache.ignite.internal.client.GridClient;
 import org.apache.ignite.internal.client.GridClientConfiguration;
 import org.apache.ignite.internal.commandline.baseline.BaselineArguments;
@@ -47,17 +48,17 @@ public class BaselineCommand implements Command<BaselineArguments> {
     private BaselineArguments baselineArgs;
 
     /** {@inheritDoc} */
-    @Override public void printUsage(CommandLogger logger) {
+    @Override public void printUsage() {
         final String constistIds = "consistentId1[,consistentId2,....,consistentIdN]";
 
-        Command.usage(logger, "Print cluster baseline topology:", BASELINE);
-        Command.usage(logger, "Add nodes into baseline topology:", BASELINE, BaselineSubcommands.ADD.text(),
+        Command.usage("Print cluster baseline topology:", BASELINE);
+        Command.usage("Add nodes into baseline topology:", BASELINE, BaselineSubcommands.ADD.text(),
             constistIds, optional(CMD_AUTO_CONFIRMATION));
-        Command.usage(logger, "Remove nodes from baseline topology:", BASELINE, BaselineSubcommands.REMOVE.text(),
+        Command.usage("Remove nodes from baseline topology:", BASELINE, BaselineSubcommands.REMOVE.text(),
             constistIds, optional(CMD_AUTO_CONFIRMATION));
-        Command.usage(logger, "Set baseline topology:", BASELINE, BaselineSubcommands.SET.text(), constistIds,
+        Command.usage("Set baseline topology:", BASELINE, BaselineSubcommands.SET.text(), constistIds,
             optional(CMD_AUTO_CONFIRMATION));
-        Command.usage(logger, "Set baseline topology based on version:", BASELINE,
+        Command.usage("Set baseline topology based on version:", BASELINE,
             BaselineSubcommands.VERSION.text() + " topologyVersion", optional(CMD_AUTO_CONFIRMATION));
     }
 
@@ -76,14 +77,15 @@ public class BaselineCommand implements Command<BaselineArguments> {
      * @param clientCfg Client configuration.
      * @throws Exception If failed to execute baseline action.
      */
-    @Override public Object execute(GridClientConfiguration clientCfg, CommandLogger logger) throws Exception {
+    @Override public Object execute(GridClientConfiguration clientCfg, Logger logger) throws Exception {
         try (GridClient client = Command.startClient(clientCfg)) {
             VisorBaselineTaskResult res = executeTask(client, VisorBaselineTask.class, toVisorArguments(baselineArgs), clientCfg);
 
-            baselinePrint0(res, logger);
+            baselinePrint0(res);
         }
         catch (Throwable e) {
-            logger.error("Failed to execute baseline command='" + baselineArgs.getCmd().text() + "'", e);
+            logger.severe("Failed to execute baseline command='" + baselineArgs.getCmd().text() + "'");
+            logger.severe(CommandLogger.errorMessage(e));
 
             throw e;
         }
@@ -111,11 +113,11 @@ public class BaselineCommand implements Command<BaselineArguments> {
      *
      * @param res Task result with baseline topology.
      */
-    private void baselinePrint0(VisorBaselineTaskResult res, CommandLogger logger) {
-        logger.log("Cluster state: " + (res.isActive() ? "active" : "inactive"));
-        logger.log("Current topology version: " + res.getTopologyVersion());
+    private void baselinePrint0(VisorBaselineTaskResult res) {
+        CommandLogger.log("Cluster state: " + (res.isActive() ? "active" : "inactive"));
+        CommandLogger.log("Current topology version: " + res.getTopologyVersion());
 
-        logger.nl();
+        CommandLogger.nl();
 
         Map<String, VisorBaselineNode> baseline = res.getBaseline();
 
@@ -131,13 +133,13 @@ public class BaselineCommand implements Command<BaselineArguments> {
             .map(crd -> " (Coordinator: ConsistentId=" + crd.getConsistentId() + ", Order=" + crd.getOrder() + ")")
             .orElse("");
 
-        logger.log("Current topology version: " + res.getTopologyVersion() + crdStr);
-        logger.nl();
+        CommandLogger.log("Current topology version: " + res.getTopologyVersion() + crdStr);
+        CommandLogger.nl();
 
         if (F.isEmpty(baseline))
-            logger.log("Baseline nodes not found.");
+            CommandLogger.log("Baseline nodes not found.");
         else {
-            logger.log("Baseline nodes:");
+            CommandLogger.log("Baseline nodes:");
 
             for (VisorBaselineNode node : baseline.values()) {
                 VisorBaselineNode srvNode = srvs.get(node.getConsistentId());
@@ -146,13 +148,13 @@ public class BaselineCommand implements Command<BaselineArguments> {
 
                 String order = srvNode != null ? ", Order=" + srvNode.getOrder() : "";
 
-                logger.logWithIndent("ConsistentId=" + node.getConsistentId() + state + order, 2);
+                CommandLogger.logWithIndent("ConsistentId=" + node.getConsistentId() + state + order, 2);
             }
 
-            logger.log(DELIM);
-            logger.log("Number of baseline nodes: " + baseline.size());
+            CommandLogger.log(DELIM);
+            CommandLogger.log("Number of baseline nodes: " + baseline.size());
 
-            logger.nl();
+            CommandLogger.nl();
 
             List<VisorBaselineNode> others = new ArrayList<>();
 
@@ -162,14 +164,14 @@ public class BaselineCommand implements Command<BaselineArguments> {
             }
 
             if (F.isEmpty(others))
-                logger.log("Other nodes not found.");
+                CommandLogger.log("Other nodes not found.");
             else {
-                logger.log("Other nodes:");
+                CommandLogger.log("Other nodes:");
 
                 for (VisorBaselineNode node : others)
-                    logger.logWithIndent("ConsistentId=" + node.getConsistentId() + ", Order=" + node.getOrder(), 2);
+                    CommandLogger.logWithIndent("ConsistentId=" + node.getConsistentId() + ", Order=" + node.getOrder(), 2);
 
-                logger.log("Number of other nodes: " + others.size());
+                CommandLogger.log("Number of other nodes: " + others.size());
             }
         }
     }
@@ -210,4 +212,9 @@ public class BaselineCommand implements Command<BaselineArguments> {
 
         this.baselineArgs = baselineArgs.build();
     }
+
+    /** {@inheritDoc} */
+    @Override public String name() {
+        return BASELINE.toCommandName();
+    }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/Command.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/Command.java
index 34b130d..a7cdcfe 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/Command.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/Command.java
@@ -16,6 +16,7 @@
 
 package org.apache.ignite.internal.commandline;
 
+import java.util.logging.Logger;
 import org.apache.ignite.internal.client.GridClient;
 import org.apache.ignite.internal.client.GridClientConfiguration;
 import org.apache.ignite.internal.client.GridClientFactory;
@@ -52,10 +53,10 @@ public interface Command<T> {
      * @param desc Command description.
      * @param args Arguments.
      */
-    public static void usage(CommandLogger logger, String desc, CommandList cmd, String... args) {
-        logger.logWithIndent(desc);
-        logger.logWithIndent(CommandLogger.join(" ", UTILITY_NAME, cmd, CommandLogger.join(" ", args)), 2);
-        logger.nl();
+    public static void usage(String desc, CommandList cmd, String... args) {
+        CommandLogger.logWithIndent(desc);
+        CommandLogger.logWithIndent(CommandLogger.join(" ", UTILITY_NAME, cmd, CommandLogger.join(" ", args)), 2);
+        CommandLogger.nl();
     }
 
     /**
@@ -66,7 +67,7 @@ public interface Command<T> {
      * @return Result of operation (mostly usable for tests).
      * @throws Exception If error occur.
      */
-    public Object execute(GridClientConfiguration clientCfg, CommandLogger logger) throws Exception;
+    public Object execute(GridClientConfiguration clientCfg, Logger logger) throws Exception;
 
     /**
      * @return Message text to show user for. If null it means that confirmantion is not needed.
@@ -92,7 +93,11 @@ public interface Command<T> {
     /**
      * Print info for user about command (parameters, use cases and so on).
      *
-     * @param logger Would be used as output.
      */
-    public void printUsage(CommandLogger logger);
+    public void printUsage();
+
+    /**
+     * @return command name.
+     */
+    String name();
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommandHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommandHandler.java
index 98a8ddc..d3c7e34 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommandHandler.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommandHandler.java
@@ -16,11 +16,16 @@
 
 package org.apache.ignite.internal.commandline;
 
+import java.io.File;
 import java.time.LocalDateTime;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 import java.util.Scanner;
+import java.util.logging.FileHandler;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.logging.StreamHandler;
 import java.util.stream.Collectors;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.internal.client.GridClientAuthenticationException;
@@ -33,6 +38,9 @@ import org.apache.ignite.internal.client.impl.connection.GridClientConnectionRes
 import org.apache.ignite.internal.client.ssl.GridSslBasicContextFactory;
 import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.X;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.logger.java.JavaLoggerFileHandler;
+import org.apache.ignite.logger.java.JavaLoggerFormatter;
 import org.apache.ignite.plugin.security.SecurityCredentials;
 import org.apache.ignite.plugin.security.SecurityCredentialsBasicProvider;
 import org.apache.ignite.plugin.security.SecurityCredentialsProvider;
@@ -52,8 +60,37 @@ import static org.apache.ignite.ssl.SslContextFactory.DFLT_SSL_PROTOCOL;
  * Class that execute several commands passed via command line.
  */
 public class CommandHandler {
-    /** Logger. */
-    private final CommandLogger logger = new CommandLogger();
+    /** Command logger. */
+    private final CommandLogger commandLogger= new CommandLogger();
+
+    /** JULs logger. */
+    private final Logger logger = setupJavaLogger();
+
+    private Logger setupJavaLogger() {
+        Logger result;
+
+        result = Logger.getLogger(getClass().getName());
+        result.setLevel(Level.INFO);
+
+        // Adding logging to file.
+        try {
+            String namePattern = "control-utility-%g.log";
+            String absPathPattern;
+            absPathPattern = new File(JavaLoggerFileHandler.logDirectory(U.defaultWorkDirectory()), namePattern).getAbsolutePath();
+            FileHandler fileHandler = new FileHandler(absPathPattern, 1024 * 1024 * 1024, 5);
+            fileHandler.setFormatter(new JavaLoggerFormatter());
+            result.addHandler(fileHandler);
+        }
+        catch (Exception e) {
+            System.out.println("Failed to configure logging to file");
+        }
+
+        // Adding logging to console.
+        StreamHandler streamHandler = new StreamHandler(System.out, new JavaLoggerFormatter());
+        result.addHandler(streamHandler);
+
+        return result;
+    }
 
     /** */
     static final String CMD_HELP = "--help";
@@ -116,11 +153,13 @@ public class CommandHandler {
      * @return Exit code.
      */
     public int execute(List<String> rawArgs) {
-        logger.log("Control utility [ver. " + ACK_VER_STR + "]");
-        logger.log(COPYRIGHT);
-        logger.log("User: " + System.getProperty("user.name"));
-        logger.log("Time: " + LocalDateTime.now());
-        logger.log(DELIM);
+        logger.info("Control utility [ver. " + ACK_VER_STR + "]");
+        logger.info(COPYRIGHT);
+        logger.info("User: " + System.getProperty("user.name"));
+        logger.info("Time: " + LocalDateTime.now());
+        logger.info(DELIM);
+
+        String commandName = "";
 
         try {
             if (F.isEmpty(rawArgs) || (rawArgs.size() == 1 && CMD_HELP.equalsIgnoreCase(rawArgs.get(0)))) {
@@ -129,12 +168,13 @@ public class CommandHandler {
                 return EXIT_CODE_OK;
             }
 
-            ConnectionAndSslParameters args = new CommonArgParser(logger).parseAndValidate(rawArgs.iterator());
+            ConnectionAndSslParameters args = new CommonArgParser(commandLogger).parseAndValidate(rawArgs.iterator());
 
             Command command = args.command();
+            commandName = command.name();
 
             if (!args.autoConfirmation() && !confirm(command.confirmationPrompt())) {
-                logger.log("Operation cancelled.");
+                logger.info("Operation cancelled.");
 
                 return EXIT_CODE_OK;
             }
@@ -151,11 +191,13 @@ public class CommandHandler {
                 tryConnectAgain = false;
 
                 try {
+                    logger.info("Command [" + commandName + "] started");
+                    logger.info("Arguments: " + String.join(" ", rawArgs));
                     lastOperationRes = command.execute(clientCfg, logger);
                 }
                 catch (Throwable e) {
                     if (tryConnectMaxCount > 0 && isAuthError(e)) {
-                        logger.log(suppliedAuth ?
+                        logger.info(suppliedAuth ?
                             "Authentication error, please try again." :
                             "This cluster requires authentication.");
 
@@ -181,27 +223,32 @@ public class CommandHandler {
                 }
             }
 
+            logger.info("Command [" + commandName + "] finished with code: " + EXIT_CODE_OK);
             return EXIT_CODE_OK;
         }
         catch (IllegalArgumentException e) {
-            logger.error("Check arguments.", e);
+            logger.severe("Check arguments. " + CommandLogger.errorMessage(e));
+            logger.info("Command [" + commandName + "] finished with code: " + EXIT_CODE_INVALID_ARGUMENTS);
 
             return EXIT_CODE_INVALID_ARGUMENTS;
         }
         catch (Throwable e) {
             if (isAuthError(e)) {
-                logger.error("Authentication error.", e);
+                logger.severe("Authentication error. " + CommandLogger.errorMessage(e));
+                logger.info("Command [" + commandName + "] finished with code: " + ERR_AUTHENTICATION_FAILED);
 
                 return ERR_AUTHENTICATION_FAILED;
             }
 
             if (isConnectionError(e)) {
-                logger.error("Connection to cluster failed.", e);
+                logger.severe("Connection to cluster failed. " + CommandLogger.errorMessage(e));
+                logger.info("Command [" + commandName + "] finished with code: " + EXIT_CODE_CONNECTION_FAILED);
 
                 return EXIT_CODE_CONNECTION_FAILED;
             }
 
-            logger.error("", e);
+            logger.severe(CommandLogger.errorMessage(e));
+            logger.info("Command [" + commandName + "] finished with code: " + EXIT_CODE_UNEXPECTED_ERROR);
 
             return EXIT_CODE_UNEXPECTED_ERROR;
         }
@@ -396,7 +443,7 @@ public class CommandHandler {
         else {
             Scanner scanner = new Scanner(System.in);
 
-            logger.log(msg);
+            commandLogger.log(msg);
 
             return scanner.nextLine();
         }
@@ -421,40 +468,40 @@ public class CommandHandler {
 
     /** */
     private void printHelp() {
-        logger.log("Control.sh is used to execute admin commands on cluster or get common cluster info. " +
+        commandLogger.log("Control.sh is used to execute admin commands on cluster or get common cluster info. " +
             "The command has the following syntax:");
-        logger.nl();
+        commandLogger.nl();
 
-        logger.logWithIndent(CommandLogger.join(" ", CommandLogger.join(" ", UTILITY_NAME, CommandLogger.join(" ", getCommonOptions())),
+        commandLogger.logWithIndent(CommandLogger.join(" ", CommandLogger.join(" ", UTILITY_NAME, CommandLogger.join(" ", getCommonOptions())),
             optional("command"), "<command_parameters>"));
-        logger.nl();
-        logger.nl();
-
-        logger.log("This utility can do the following commands:");
-
-        Arrays.stream(CommandList.values()).forEach(c -> c.command().printUsage(logger));
-
-        logger.log("By default commands affecting the cluster require interactive confirmation.");
-        logger.log("Use " + CMD_AUTO_CONFIRMATION + " option to disable it.");
-        logger.nl();
-
-        logger.log("Default values:");
-        logger.logWithIndent("HOST_OR_IP=" + DFLT_HOST, 2);
-        logger.logWithIndent("PORT=" + DFLT_PORT, 2);
-        logger.logWithIndent("PING_INTERVAL=" + DFLT_PING_INTERVAL, 2);
-        logger.logWithIndent("PING_TIMEOUT=" + DFLT_PING_TIMEOUT, 2);
-        logger.logWithIndent("SSL_PROTOCOL=" + SslContextFactory.DFLT_SSL_PROTOCOL, 2);
-        logger.logWithIndent("SSL_KEY_ALGORITHM=" + SslContextFactory.DFLT_KEY_ALGORITHM, 2);
-        logger.logWithIndent("KEYSTORE_TYPE=" + SslContextFactory.DFLT_STORE_TYPE, 2);
-        logger.logWithIndent("TRUSTSTORE_TYPE=" + SslContextFactory.DFLT_STORE_TYPE, 2);
-
-        logger.nl();
-
-        logger.log("Exit codes:");
-        logger.logWithIndent(EXIT_CODE_OK + " - successful execution.", 2);
-        logger.logWithIndent(EXIT_CODE_INVALID_ARGUMENTS + " - invalid arguments.", 2);
-        logger.logWithIndent(EXIT_CODE_CONNECTION_FAILED + " - connection failed.", 2);
-        logger.logWithIndent(ERR_AUTHENTICATION_FAILED + " - authentication failed.", 2);
-        logger.logWithIndent(EXIT_CODE_UNEXPECTED_ERROR + " - unexpected error.", 2);
+        commandLogger.nl();
+        commandLogger.nl();
+
+        commandLogger.log("This utility can do the following commands:");
+
+        Arrays.stream(CommandList.values()).forEach(c -> c.command().printUsage());
+
+        commandLogger.log("By default commands affecting the cluster require interactive confirmation.");
+        commandLogger.log("Use " + CMD_AUTO_CONFIRMATION + " option to disable it.");
+        commandLogger.nl();
+
+        commandLogger.log("Default values:");
+        commandLogger.logWithIndent("HOST_OR_IP=" + DFLT_HOST, 2);
+        commandLogger.logWithIndent("PORT=" + DFLT_PORT, 2);
+        commandLogger.logWithIndent("PING_INTERVAL=" + DFLT_PING_INTERVAL, 2);
+        commandLogger.logWithIndent("PING_TIMEOUT=" + DFLT_PING_TIMEOUT, 2);
+        commandLogger.logWithIndent("SSL_PROTOCOL=" + SslContextFactory.DFLT_SSL_PROTOCOL, 2);
+        commandLogger.logWithIndent("SSL_KEY_ALGORITHM=" + SslContextFactory.DFLT_KEY_ALGORITHM, 2);
+        commandLogger.logWithIndent("KEYSTORE_TYPE=" + SslContextFactory.DFLT_STORE_TYPE, 2);
+        commandLogger.logWithIndent("TRUSTSTORE_TYPE=" + SslContextFactory.DFLT_STORE_TYPE, 2);
+
+        commandLogger.nl();
+
+        commandLogger.log("Exit codes:");
+        commandLogger.logWithIndent(EXIT_CODE_OK + " - successful execution.", 2);
+        commandLogger.logWithIndent(EXIT_CODE_INVALID_ARGUMENTS + " - invalid arguments.", 2);
+        commandLogger.logWithIndent(EXIT_CODE_CONNECTION_FAILED + " - connection failed.", 2);
+        commandLogger.logWithIndent(ERR_AUTHENTICATION_FAILED + " - authentication failed.", 2);
+        commandLogger.logWithIndent(EXIT_CODE_UNEXPECTED_ERROR + " - unexpected error.", 2);
     }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommandList.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommandList.java
index 280a40b..d595e05 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommandList.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommandList.java
@@ -92,4 +92,11 @@ public enum CommandList {
     @Override public String toString() { 
         return text; 
     }
+
+    /**
+     * @return command name
+     */
+    public String toCommandName() {
+        return text.substring(2).toUpperCase();
+    }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommandLogger.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommandLogger.java
index b19ad24..3bf6a92 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommandLogger.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommandLogger.java
@@ -18,6 +18,7 @@ package org.apache.ignite.internal.commandline;
 
 import java.util.Map;
 import java.util.UUID;
+import java.util.logging.Logger;
 import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.internal.SB;
 
@@ -93,11 +94,30 @@ public class CommandLogger {
     }
 
     /**
+     * Generates readable error message from exception
+     * @param e Exctption
+     * @return error message
+     */
+    public static String errorMessage(Throwable e) {
+        String msg = e.getMessage();
+
+        if (F.isEmpty(msg))
+            msg = e.getClass().getName();
+        else if (msg.startsWith("Failed to handle request")) {
+            int p = msg.indexOf("err=");
+
+            msg = msg.substring(p + 4, msg.length() - 1);
+        }
+
+        return msg;
+    }
+
+    /**
      * Output specified string to console.
      *
      * @param s String to output.
      */
-    public void log(String s) {
+    public static void log(String s) {
         System.out.println(s);
     }
 
@@ -107,7 +127,7 @@ public class CommandLogger {
      *
      * @param s String to output.
      */
-    public void logWithIndent(Object s) {
+    public static void logWithIndent(Object s) {
         log(indent(s));
     }
 
@@ -117,7 +137,7 @@ public class CommandLogger {
      *
      * @param s String to output.
      */
-    public void logWithIndent(Object s, int indentCnt) {
+    public static void logWithIndent(Object s, int indentCnt) {
         log(indent(s), indentCnt);
     }
 
@@ -169,14 +189,14 @@ public class CommandLogger {
      * @param format A format string as described in Format string syntax.
      * @param args Arguments referenced by the format specifiers in the format string.
      */
-    public void log(String format, Object... args) {
+    public static void log(String format, Object... args) {
         System.out.printf(format, args);
     }
 
     /**
      * Output empty line.
      */
-    public void nl() {
+    public static void nl() {
         System.out.println();
     }
 
@@ -191,18 +211,7 @@ public class CommandLogger {
         if (!F.isEmpty(s))
             log(s);
 
-        String msg = e.getMessage();
-
-        if (F.isEmpty(msg))
-            msg = e.getClass().getName();
-
-        if (msg.startsWith("Failed to handle request")) {
-            int p = msg.indexOf("err=");
-
-            msg = msg.substring(p + 4, msg.length() - 1);
-        }
-
-        log("Error: " + msg);
+        log("Error: " + errorMessage(e));
     }
 
 
@@ -224,4 +233,22 @@ public class CommandLogger {
 
         return false;
     }
+
+    public static boolean printErrors(Map<UUID, Exception> exceptions, String s, Logger logger) {
+        if (!F.isEmpty(exceptions)) {
+            logger.info(s);
+
+            for (Map.Entry<UUID, Exception> e : exceptions.entrySet()) {
+                logger.info(INDENT + "Node ID: " + e.getKey());
+
+                logger.info(INDENT + "Exception message:");
+                logger.info(INDENT + INDENT + e.getValue().getMessage());
+                logger.info("");
+            }
+
+            return true;
+        }
+
+        return false;
+    }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/DeactivateCommand.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/DeactivateCommand.java
index ad5e551..961e0ef 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/DeactivateCommand.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/DeactivateCommand.java
@@ -16,6 +16,7 @@
 
 package org.apache.ignite.internal.commandline;
 
+import java.util.logging.Logger;
 import org.apache.ignite.internal.client.GridClient;
 import org.apache.ignite.internal.client.GridClientClusterState;
 import org.apache.ignite.internal.client.GridClientConfiguration;
@@ -29,8 +30,8 @@ import static org.apache.ignite.internal.commandline.CommonArgParser.CMD_AUTO_CO
  */
 public class DeactivateCommand implements Command<Void> {
     /** {@inheritDoc} */
-    @Override public void printUsage(CommandLogger logger) {
-        Command.usage(logger, "Deactivate cluster:", DEACTIVATE, optional(CMD_AUTO_CONFIRMATION));
+    @Override public void printUsage() {
+        Command.usage("Deactivate cluster:", DEACTIVATE, optional(CMD_AUTO_CONFIRMATION));
     }
 
     /** {@inheritDoc} */
@@ -44,16 +45,16 @@ public class DeactivateCommand implements Command<Void> {
      * @param clientCfg Client configuration.
      * @throws Exception If failed to deactivate.
      */
-    @Override public Object execute(GridClientConfiguration clientCfg, CommandLogger logger) throws Exception {
+    @Override public Object execute(GridClientConfiguration clientCfg, Logger logger) throws Exception {
         try (GridClient client = Command.startClient(clientCfg)) {
             GridClientClusterState state = client.state();
 
             state.active(false);
 
-            logger.log("Cluster deactivated");
+            logger.info("Cluster deactivated");
         }
         catch (Exception e) {
-            logger.log("Failed to deactivate cluster.");
+            logger.severe("Failed to deactivate cluster.");
 
             throw e;
         }
@@ -65,4 +66,9 @@ public class DeactivateCommand implements Command<Void> {
     @Override public Void arg() {
         return null;
     }
+
+    /** {@inheritDoc} */
+    @Override public String name() {
+        return DEACTIVATE.toCommandName();
+    }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/StateCommand.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/StateCommand.java
index a2a3afd..69aa3ec 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/StateCommand.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/StateCommand.java
@@ -16,6 +16,7 @@
 
 package org.apache.ignite.internal.commandline;
 
+import java.util.logging.Logger;
 import org.apache.ignite.internal.client.GridClient;
 import org.apache.ignite.internal.client.GridClientClusterState;
 import org.apache.ignite.internal.client.GridClientConfiguration;
@@ -27,8 +28,8 @@ import static org.apache.ignite.internal.commandline.CommandList.STATE;
  */
 public class StateCommand implements Command<Void> {
     /** {@inheritDoc} */
-    @Override public void printUsage(CommandLogger logger) {
-        Command.usage(logger, "Print current cluster state:", STATE);
+    @Override public void printUsage() {
+        Command.usage("Print current cluster state:", STATE);
     }
 
     /**
@@ -37,14 +38,14 @@ public class StateCommand implements Command<Void> {
      * @param clientCfg Client configuration.
      * @throws Exception If failed to print state.
      */
-    @Override public Object execute(GridClientConfiguration clientCfg, CommandLogger logger) throws Exception {
+    @Override public Object execute(GridClientConfiguration clientCfg, Logger logger) throws Exception {
         try (GridClient client = Command.startClient(clientCfg)){
             GridClientClusterState state = client.state();
 
-            logger.log("Cluster is " + (state.active() ? "active" : "inactive"));
+            logger.info("Cluster is " + (state.active() ? "active" : "inactive"));
         }
         catch (Throwable e) {
-            logger.log("Failed to get cluster state.");
+            logger.severe("Failed to get cluster state.");
 
             throw e;
         }
@@ -56,4 +57,9 @@ public class StateCommand implements Command<Void> {
     @Override public Void arg() {
         return null;
     }
+
+    /** {@inheritDoc} */
+    @Override public String name() {
+        return STATE.toCommandName();
+    }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/TxCommands.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/TxCommands.java
index 1063d13..b9674d7 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/TxCommands.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/TxCommands.java
@@ -23,6 +23,7 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.logging.Logger;
 import java.util.regex.Pattern;
 import java.util.regex.PatternSyntaxException;
 import org.apache.ignite.cluster.ClusterNode;
@@ -69,12 +70,12 @@ public class TxCommands implements Command<VisorTxTaskArg> {
     private VisorTxTaskArg args;
 
     /** Logger. */
-    private CommandLogger logger;
+    private Logger logger;
 
     /** {@inheritDoc} */
-    @Override public void printUsage(CommandLogger logger) {
-        Command.usage(logger, "List or kill transactions:", TX, getTxOptions());
-        Command.usage(logger, "Print detailed information (topology and key lock ownership) about specific transaction:",
+    @Override public void printUsage() {
+        Command.usage("List or kill transactions:", TX, getTxOptions());
+        Command.usage("Print detailed information (topology and key lock ownership) about specific transaction:",
             TX, TX_INFO.argName(), or("<TX identifier as GridCacheVersion [topVer=..., order=..., nodeOrder=...] " +
                 "(can be found in logs)>", "<TX identifier as UUID (can be retrieved via --tx command)>"));
 
@@ -111,7 +112,7 @@ public class TxCommands implements Command<VisorTxTaskArg> {
      *
      * @param clientCfg Client configuration.
      */
-    @Override public Object execute(GridClientConfiguration clientCfg, CommandLogger logger) throws Exception {
+    @Override public Object execute(GridClientConfiguration clientCfg, Logger logger) throws Exception {
         this.logger = logger;
 
         try (GridClient client = Command.startClient(clientCfg)) {
@@ -121,11 +122,11 @@ public class TxCommands implements Command<VisorTxTaskArg> {
             Map<ClusterNode, VisorTxTaskResult> res = executeTask(client, VisorTxTask.class, args, clientCfg);
 
             if (res.isEmpty())
-                logger.log("Nothing found.");
+                logger.info("Nothing found.");
             else if (args.getOperation() == VisorTxOperation.KILL)
-                logger.log("Killed transactions:");
+                logger.info("Killed transactions:");
             else
-                logger.log("Matching transactions:");
+                logger.info("Matching transactions:");
 
             for (Map.Entry<ClusterNode, VisorTxTaskResult> entry : res.entrySet()) {
                 if (entry.getValue().getInfos().isEmpty())
@@ -133,7 +134,7 @@ public class TxCommands implements Command<VisorTxTaskArg> {
 
                 ClusterNode key = entry.getKey();
 
-                logger.log(key.getClass().getSimpleName() + " [id=" + key.id() +
+                logger.info(key.getClass().getSimpleName() + " [id=" + key.id() +
                     ", addrs=" + key.addresses() +
                     ", order=" + key.order() +
                     ", ver=" + key.version() +
@@ -142,13 +143,14 @@ public class TxCommands implements Command<VisorTxTaskArg> {
                     "]");
 
                 for (VisorTxInfo info : entry.getValue().getInfos())
-                    logger.log(info.toUserString());
+                    logger.info(info.toUserString());
             }
 
             return res;
         }
         catch (Throwable e) {
-            logger.error("Failed to perform operation.", e);
+            logger.severe("Failed to perform operation.");
+            logger.severe(CommandLogger.errorMessage(e));
 
             throw e;
         }
@@ -175,14 +177,14 @@ public class TxCommands implements Command<VisorTxTaskArg> {
 
                 ClusterNode key = entry.getKey();
 
-                logger.log(nodeDescription(key));
+                logger.info(nodeDescription(key));
 
                 for (VisorTxInfo info : entry.getValue().getInfos())
-                    logger.log(info.toUserString());
+                    logger.info(info.toUserString());
             }
         }
         catch (Throwable e) {
-            logger.log("Failed to perform operation.");
+            logger.severe("Failed to perform operation.");
 
             throw e;
         }
@@ -357,20 +359,20 @@ public class TxCommands implements Command<VisorTxTaskArg> {
         boolean histMode = false;
 
         if (nearXidVer != null) {
-            logger.log("Resolved transaction near XID version: " + nearXidVer);
+            logger.info("Resolved transaction near XID version: " + nearXidVer);
 
             args.txInfoArgument(new TxVerboseId(null, nearXidVer));
         }
         else {
-            logger.log("Active transactions not found.");
+            logger.info("Active transactions not found.");
 
             if (args.txInfoArgument().gridCacheVersion() != null) {
-                logger.log("Will try to peek history to find out whether transaction was committed / rolled back.");
+                logger.info("Will try to peek history to find out whether transaction was committed / rolled back.");
 
                 histMode = true;
             }
             else {
-                logger.log("You can specify transaction in GridCacheVersion format in order to peek history " +
+                logger.info("You can specify transaction in GridCacheVersion format in order to peek history " +
                     "to find out whether transaction was committed / rolled back.");
 
                 return null;
@@ -421,8 +423,8 @@ public class TxCommands implements Command<VisorTxTaskArg> {
 
         String indent = "";
 
-        logger.nl();
-        logger.log(indent + "Transaction detailed info:");
+        logger.info("");
+        logger.info(indent + "Transaction detailed info:");
 
         printTransactionDetailedInfo(
             res, usedCaches, usedCacheGroups, firstInfo, firstVerboseInfo, states, indent + DOUBLE_INDENT);
@@ -442,19 +444,19 @@ public class TxCommands implements Command<VisorTxTaskArg> {
     private void printTransactionDetailedInfo(Map<ClusterNode, VisorTxTaskResult> res, Map<Integer, String> usedCaches,
         Map<Integer, String> usedCacheGroups, VisorTxInfo firstInfo, TxVerboseInfo firstVerboseInfo,
         Set<TransactionState> states, String indent) {
-        logger.log(indent + "Near XID version: " + firstVerboseInfo.nearXidVersion());
-        logger.log(indent + "Near XID version (UUID): " + firstInfo.getNearXid());
-        logger.log(indent + "Isolation: " + firstInfo.getIsolation());
-        logger.log(indent + "Concurrency: " + firstInfo.getConcurrency());
-        logger.log(indent + "Timeout: " + firstInfo.getTimeout());
-        logger.log(indent + "Initiator node: " + firstVerboseInfo.nearNodeId());
-        logger.log(indent + "Initiator node (consistent ID): " + firstVerboseInfo.nearNodeConsistentId());
-        logger.log(indent + "Label: " + firstInfo.getLabel());
-        logger.log(indent + "Topology version: " + firstInfo.getTopologyVersion());
-        logger.log(indent + "Used caches (ID to name): " + usedCaches);
-        logger.log(indent + "Used cache groups (ID to name): " + usedCacheGroups);
-        logger.log(indent + "States across the cluster: " + states);
-        logger.log(indent + "Transaction topology: ");
+        logger.info(indent + "Near XID version: " + firstVerboseInfo.nearXidVersion());
+        logger.info(indent + "Near XID version (UUID): " + firstInfo.getNearXid());
+        logger.info(indent + "Isolation: " + firstInfo.getIsolation());
+        logger.info(indent + "Concurrency: " + firstInfo.getConcurrency());
+        logger.info(indent + "Timeout: " + firstInfo.getTimeout());
+        logger.info(indent + "Initiator node: " + firstVerboseInfo.nearNodeId());
+        logger.info(indent + "Initiator node (consistent ID): " + firstVerboseInfo.nearNodeConsistentId());
+        logger.info(indent + "Label: " + firstInfo.getLabel());
+        logger.info(indent + "Topology version: " + firstInfo.getTopologyVersion());
+        logger.info(indent + "Used caches (ID to name): " + usedCaches);
+        logger.info(indent + "Used cache groups (ID to name): " + usedCacheGroups);
+        logger.info(indent + "States across the cluster: " + states);
+        logger.info(indent + "Transaction topology: ");
 
         printTransactionTopology(res, indent + DOUBLE_INDENT);
     }
@@ -467,7 +469,7 @@ public class TxCommands implements Command<VisorTxTaskArg> {
      */
     private void printTransactionTopology(Map<ClusterNode, VisorTxTaskResult> res, String indent) {
         for (Map.Entry<ClusterNode, VisorTxTaskResult> entry : res.entrySet()) {
-            logger.log(indent + nodeDescription(entry.getKey()) + ':');
+            logger.info(indent + nodeDescription(entry.getKey()) + ':');
 
             printTransactionMappings(indent + DOUBLE_INDENT, entry);
         }
@@ -484,14 +486,14 @@ public class TxCommands implements Command<VisorTxTaskArg> {
             TxVerboseInfo verboseInfo = info.getTxVerboseInfo();
 
             if (verboseInfo != null) {
-                logger.log(indent + "Mapping [type=" + verboseInfo.txMappingType() + "]:");
+                logger.info(indent + "Mapping [type=" + verboseInfo.txMappingType() + "]:");
 
                 printTransactionMapping(indent + DOUBLE_INDENT, info, verboseInfo);
             }
             else {
-                logger.log(indent + "Mapping [type=HISTORICAL]:");
+                logger.info(indent + "Mapping [type=HISTORICAL]:");
 
-                logger.log(indent + DOUBLE_INDENT + "State: " + info.getState());
+                logger.info(indent + DOUBLE_INDENT + "State: " + info.getState());
             }
         }
     }
@@ -504,16 +506,16 @@ public class TxCommands implements Command<VisorTxTaskArg> {
      * @param verboseInfo Verbose info.
      */
     private void printTransactionMapping(String indent, VisorTxInfo info, TxVerboseInfo verboseInfo) {
-        logger.log(indent + "XID version (UUID): " + info.getXid());
-        logger.log(indent + "State: " + info.getState());
+        logger.info(indent + "XID version (UUID): " + info.getXid());
+        logger.info(indent + "State: " + info.getState());
 
         if (verboseInfo.txMappingType() == TxMappingType.REMOTE) {
-            logger.log(indent + "Primary node: " + verboseInfo.dhtNodeId());
-            logger.log(indent + "Primary node (consistent ID): " + verboseInfo.dhtNodeConsistentId());
+            logger.info(indent + "Primary node: " + verboseInfo.dhtNodeId());
+            logger.info(indent + "Primary node (consistent ID): " + verboseInfo.dhtNodeConsistentId());
         }
 
         if (!F.isEmpty(verboseInfo.localTxKeys())) {
-            logger.log(indent + "Mapped keys:");
+            logger.info(indent + "Mapped keys:");
 
             printTransactionKeys(indent + DOUBLE_INDENT, verboseInfo);
         }
@@ -527,11 +529,11 @@ public class TxCommands implements Command<VisorTxTaskArg> {
      */
     private void printTransactionKeys(String indent, TxVerboseInfo verboseInfo) {
         for (TxVerboseKey txVerboseKey : verboseInfo.localTxKeys()) {
-            logger.log(indent + (txVerboseKey.read() ? "Read" : "Write") +
+            logger.info(indent + (txVerboseKey.read() ? "Read" : "Write") +
                 " [lock=" + txVerboseKey.lockType() + "]: " + txVerboseKey.txKey());
 
             if (txVerboseKey.lockType() == TxKeyLockType.AWAITS_LOCK)
-                logger.log(indent + DOUBLE_INDENT + "Lock owner XID: " + txVerboseKey.ownerVersion());
+                logger.info(indent + DOUBLE_INDENT + "Lock owner XID: " + txVerboseKey.ownerVersion());
         }
     }
 
@@ -542,13 +544,13 @@ public class TxCommands implements Command<VisorTxTaskArg> {
      */
     private void printTxInfoHistoricalResult(Map<ClusterNode, VisorTxTaskResult> res) {
         if (F.isEmpty(res))
-            logger.log("Transaction was not found in history across the cluster.");
+            logger.info("Transaction was not found in history across the cluster.");
         else {
-            logger.log("Transaction was found in completed versions history of the following nodes:");
+            logger.info("Transaction was found in completed versions history of the following nodes:");
 
             for (Map.Entry<ClusterNode, VisorTxTaskResult> entry : res.entrySet()) {
-                logger.log(DOUBLE_INDENT + nodeDescription(entry.getKey()) + ':');
-                logger.log(DOUBLE_INDENT + DOUBLE_INDENT + "State: " + entry.getValue().getInfos().get(0).getState());
+                logger.info(DOUBLE_INDENT + nodeDescription(entry.getKey()) + ':');
+                logger.info(DOUBLE_INDENT + DOUBLE_INDENT + "State: " + entry.getValue().getInfos().get(0).getState());
             }
         }
     }
@@ -578,4 +580,9 @@ public class TxCommands implements Command<VisorTxTaskArg> {
             }
         }
     }
+
+    /** {@inheritDoc} */
+    @Override public String name() {
+        return TX.toCommandName();
+    }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/WalCommands.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/WalCommands.java
index 872d732..5a5a59f 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/WalCommands.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/WalCommands.java
@@ -20,6 +20,7 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
+import java.util.logging.Logger;
 import org.apache.ignite.IgniteSystemProperties;
 import org.apache.ignite.internal.client.GridClient;
 import org.apache.ignite.internal.client.GridClientConfiguration;
@@ -35,6 +36,7 @@ import org.apache.ignite.internal.visor.misc.VisorWalTaskResult;
 import static org.apache.ignite.IgniteSystemProperties.IGNITE_ENABLE_EXPERIMENTAL_COMMAND;
 import static org.apache.ignite.internal.commandline.CommandArgIterator.isCommandOrOption;
 import static org.apache.ignite.internal.commandline.CommandList.WAL;
+import static org.apache.ignite.internal.commandline.CommandLogger.INDENT;
 import static org.apache.ignite.internal.commandline.CommandLogger.optional;
 import static org.apache.ignite.internal.commandline.CommonArgParser.CMD_AUTO_CONFIRMATION;
 import static org.apache.ignite.internal.commandline.TaskExecutor.executeTask;
@@ -50,7 +52,7 @@ public class WalCommands implements Command<T2<String, String>> {
     static final String WAL_DELETE = "delete";
 
     /** */
-    private CommandLogger logger;
+    private Logger logger;
 
     /**
      * Wal action.
@@ -62,11 +64,11 @@ public class WalCommands implements Command<T2<String, String>> {
      */
     private String walArgs;
 
-    @Override public void printUsage(CommandLogger logger) {
+    @Override public void printUsage() {
         if (IgniteSystemProperties.getBoolean(IGNITE_ENABLE_EXPERIMENTAL_COMMAND, false)) {
-            Command.usage(logger, "Print absolute paths of unused archived wal segments on each node:", WAL,
+            Command.usage("Print absolute paths of unused archived wal segments on each node:", WAL,
                 WAL_PRINT, "[consistentId1,consistentId2,....,consistentIdN]");
-            Command.usage(logger,"Delete unused archived wal segments on each node:", WAL, WAL_DELETE,
+            Command.usage("Delete unused archived wal segments on each node:", WAL, WAL_DELETE,
                 "[consistentId1,consistentId2,....,consistentIdN]", optional(CMD_AUTO_CONFIRMATION));
         }
     }
@@ -77,7 +79,7 @@ public class WalCommands implements Command<T2<String, String>> {
      * @param clientCfg Client configuration.
      * @throws Exception If failed to execute wal action.
      */
-    @Override public Object execute(GridClientConfiguration clientCfg, CommandLogger logger) throws Exception {
+    @Override public Object execute(GridClientConfiguration clientCfg, Logger logger) throws Exception {
         this.logger = logger;
 
         try (GridClient client = Command.startClient(clientCfg)) {
@@ -197,8 +199,8 @@ public class WalCommands implements Command<T2<String, String>> {
      * @param taskRes Task result with baseline topology.
      */
     private void printUnusedWalSegments0(VisorWalTaskResult taskRes) {
-        logger.log("Unused wal segments per node:");
-        logger.nl();
+        logger.info("Unused wal segments per node:");
+        logger.info("");
 
         Map<String, Collection<String>> res = taskRes.results();
         Map<String, Exception> failRes = taskRes.exceptions();
@@ -207,22 +209,22 @@ public class WalCommands implements Command<T2<String, String>> {
         for (Map.Entry<String, Collection<String>> entry : res.entrySet()) {
             VisorClusterNode node = nodesInfo.get(entry.getKey());
 
-            logger.log("Node=" + node.getConsistentId());
-            logger.logWithIndent("addresses " + U.addressesAsString(node.getAddresses(), node.getHostNames()), 2);
+            logger.info("Node=" + node.getConsistentId());
+            logger.info(INDENT + INDENT +"addresses " + U.addressesAsString(node.getAddresses(), node.getHostNames()));
 
             for (String fileName : entry.getValue())
-                logger.logWithIndent(fileName);
+                logger.info(INDENT + fileName);
 
-            logger.nl();
+            logger.info("");
         }
 
         for (Map.Entry<String, Exception> entry : failRes.entrySet()) {
             VisorClusterNode node = nodesInfo.get(entry.getKey());
 
-            logger.log("Node=" + node.getConsistentId());
-            logger.logWithIndent("addresses " + U.addressesAsString(node.getAddresses(), node.getHostNames()), 2);
-            logger.logWithIndent("failed with error: " + entry.getValue().getMessage());
-            logger.nl();
+            logger.info("Node=" + node.getConsistentId());
+            logger.info(INDENT + INDENT + "addresses " + U.addressesAsString(node.getAddresses(), node.getHostNames()));
+            logger.info(INDENT + "failed with error: " + entry.getValue().getMessage());
+            logger.info("");
         }
     }
 
@@ -232,8 +234,8 @@ public class WalCommands implements Command<T2<String, String>> {
      * @param taskRes Task result with baseline topology.
      */
     private void printDeleteWalSegments0(VisorWalTaskResult taskRes) {
-        logger.log("WAL segments deleted for nodes:");
-        logger.nl();
+        logger.info("WAL segments deleted for nodes:");
+        logger.info("");
 
         Map<String, Collection<String>> res = taskRes.results();
         Map<String, Exception> errors = taskRes.exceptions();
@@ -242,18 +244,23 @@ public class WalCommands implements Command<T2<String, String>> {
         for (Map.Entry<String, Collection<String>> entry : res.entrySet()) {
             VisorClusterNode node = nodesInfo.get(entry.getKey());
 
-            logger.log("Node=" + node.getConsistentId());
-            logger.logWithIndent("addresses " + U.addressesAsString(node.getAddresses(), node.getHostNames()), 2);
-            logger.nl();
+            logger.info("Node=" + node.getConsistentId());
+            logger.info(INDENT + INDENT + "addresses " + U.addressesAsString(node.getAddresses(), node.getHostNames()));
+            logger.info("");
         }
 
         for (Map.Entry<String, Exception> entry : errors.entrySet()) {
             VisorClusterNode node = nodesInfo.get(entry.getKey());
 
-            logger.log("Node=" + node.getConsistentId());
-            logger.logWithIndent("addresses " + U.addressesAsString(node.getAddresses(), node.getHostNames()), 2);
-            logger.logWithIndent("failed with error: " + entry.getValue().getMessage());
-            logger.nl();
+            logger.info("Node=" + node.getConsistentId());
+            logger.info(INDENT + INDENT + "addresses " + U.addressesAsString(node.getAddresses(), node.getHostNames()));
+            logger.info(INDENT + "failed with error: " + entry.getValue().getMessage());
+            logger.info("");
         }
     }
+
+    /** {@inheritDoc} */
+    @Override public String name() {
+        return WAL.toCommandName();
+    }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheCommands.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheCommands.java
index aa9a774..3d8bc0a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheCommands.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheCommands.java
@@ -19,6 +19,7 @@ package org.apache.ignite.internal.commandline.cache;
 import java.util.Arrays;
 import java.util.Comparator;
 import java.util.Map;
+import java.util.logging.Logger;
 import org.apache.ignite.internal.client.GridClientConfiguration;
 import org.apache.ignite.internal.commandline.Command;
 import org.apache.ignite.internal.commandline.CommandArgIterator;
@@ -48,22 +49,17 @@ public class CacheCommands implements Command<CacheSubcommands> {
     protected static final String OP_NODE_ID = optional(NODE_ID);
 
     /** */
-    private CommandLogger logger;
-
-    /** */
     private CacheSubcommands subcommand;
 
     /** {@inheritDoc} */
-    @Override public void printUsage(CommandLogger logger) {
-        logger.logWithIndent("View caches information in a cluster. For more details type:");
-        logger.logWithIndent(CommandLogger.join(" ", UTILITY_NAME, CACHE, HELP), 2);
-        logger.nl();
+    @Override public void printUsage() {
+        CommandLogger.logWithIndent("View caches information in a cluster. For more details type:");
+        CommandLogger.logWithIndent(CommandLogger.join(" ", UTILITY_NAME, CACHE, HELP), 2);
+        CommandLogger.nl();
     }
 
     /** {@inheritDoc} */
-    @Override public Object execute(GridClientConfiguration clientCfg, CommandLogger logger) throws Exception {
-        this.logger = logger;
-
+    @Override public Object execute(GridClientConfiguration clientCfg, Logger logger) throws Exception {
         if (subcommand == CacheSubcommands.HELP) {
             printCacheHelp();
 
@@ -120,25 +116,25 @@ public class CacheCommands implements Command<CacheSubcommands> {
 
     /** */
     private void printCacheHelp() {
-        logger.logWithIndent("The '" + CACHE + " subcommand' is used to get information about and perform actions" +
+        CommandLogger.logWithIndent("The '" + CACHE + " subcommand' is used to get information about and perform actions" +
             " with caches. The command has the following syntax:");
-        logger.nl();
-        logger.logWithIndent(CommandLogger.join(" ", UTILITY_NAME, CommandLogger.join(" ", getCommonOptions())) + " " +
+        CommandLogger.nl();
+        CommandLogger.logWithIndent(CommandLogger.join(" ", UTILITY_NAME, CommandLogger.join(" ", getCommonOptions())) + " " +
             CACHE + " [subcommand] <subcommand_parameters>");
-        logger.nl();
-        logger.logWithIndent("The subcommands that take " + OP_NODE_ID + " as an argument ('" + LIST + "', '"
+        CommandLogger.nl();
+        CommandLogger.logWithIndent("The subcommands that take " + OP_NODE_ID + " as an argument ('" + LIST + "', '"
             + FIND_AND_DELETE_GARBAGE+ "', '" + CONTENTION + "' and '" + VALIDATE_INDEXES +
             "') will be executed on the given node or on all server nodes" +
             " if the option is not specified. Other commands will run on a random server node.");
-        logger.nl();
-        logger.nl();
-        logger.logWithIndent("Subcommands:");
+        CommandLogger.nl();
+        CommandLogger.nl();
+        CommandLogger.logWithIndent("Subcommands:");
 
         Arrays.stream(CacheCommandList.values()).forEach(c -> {
-            if (c.subcommand() != null) c.subcommand().printUsage(logger);
+            if (c.subcommand() != null) c.subcommand().printUsage();
         });
 
-        logger.nl();
+        CommandLogger.nl();
     }
 
 
@@ -151,7 +147,6 @@ public class CacheCommands implements Command<CacheSubcommands> {
      * @param args Cache command arguments.
      */
     protected static void usageCache(
-        CommandLogger logger,
         CacheSubcommands cmd,
         String description,
         Map<String, String> paramsDesc,
@@ -159,34 +154,33 @@ public class CacheCommands implements Command<CacheSubcommands> {
     ) {
         int indentsNum = 1;
 
-        logger.logWithIndent(DELIM, indentsNum);
-        logger.nl();
-        logger.logWithIndent(CommandLogger.join(" ", CACHE, cmd, CommandLogger.join(" ", args)), indentsNum++);
-        logger.nl();
-        logger.logWithIndent(description, indentsNum);
-        logger.nl();
+        CommandLogger.logWithIndent(DELIM, indentsNum);
+        CommandLogger.nl();
+        CommandLogger.logWithIndent(CommandLogger.join(" ", CACHE, cmd, CommandLogger.join(" ", args)), indentsNum++);
+        CommandLogger.nl();
+        CommandLogger.logWithIndent(description, indentsNum);
+        CommandLogger.nl();
 
         if (!F.isEmpty(paramsDesc)) {
-            logger.logWithIndent("Parameters:", indentsNum);
+            CommandLogger.logWithIndent("Parameters:", indentsNum);
 
-            usageCacheParams(logger, paramsDesc, indentsNum + 1);
+            usageCacheParams(paramsDesc, indentsNum + 1);
 
-            logger.nl();
+            CommandLogger.nl();
         }
     }
 
     /**
      * Print cache command arguments usage.
      *
-     * @param logger Command logger.
      * @param paramsDesc Cache command arguments description.
      * @param indentsNum Number of indents.
      */
-    private static void usageCacheParams(CommandLogger logger, Map<String, String> paramsDesc, int indentsNum) {
+    private static void usageCacheParams(Map<String, String> paramsDesc, int indentsNum) {
         int maxParamLen = paramsDesc.keySet().stream().max(Comparator.comparingInt(String::length)).get().length();
 
         for (Map.Entry<String, String> param : paramsDesc.entrySet())
-            logger.logWithIndent(extendToLen(param.getKey(), maxParamLen) + "  " + "- " + param.getValue(), indentsNum);
+            CommandLogger.logWithIndent(extendToLen(param.getKey(), maxParamLen) + "  " + "- " + param.getValue(), indentsNum);
     }
 
     /**
@@ -217,4 +211,9 @@ public class CacheCommands implements Command<CacheSubcommands> {
     @Override public CacheSubcommands arg() {
         return subcommand;
     }
+
+    /** {@inheritDoc} */
+    @Override public String name() {
+        return CACHE.toCommandName();
+    }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheContention.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheContention.java
index b09e30a..ac46a4e 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheContention.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheContention.java
@@ -17,6 +17,7 @@
 package org.apache.ignite.internal.commandline.cache;
 
 import java.util.UUID;
+import java.util.logging.Logger;
 import org.apache.ignite.internal.client.GridClient;
 import org.apache.ignite.internal.client.GridClientConfiguration;
 import org.apache.ignite.internal.commandline.Command;
@@ -39,10 +40,10 @@ import static org.apache.ignite.internal.commandline.cache.CacheSubcommands.CONT
  */
 public class CacheContention implements Command<CacheContention.Arguments> {
     /** {@inheritDoc} */
-    @Override public void printUsage(CommandLogger logger) {
+    @Override public void printUsage() {
         String description = "Show the keys that are point of contention for multiple transactions.";
 
-        usageCache(logger, CONTENTION, description, null, "minQueueSize",
+        usageCache(CONTENTION, description, null, "minQueueSize",
             OP_NODE_ID, optional("maxPrint"));
     }
 
@@ -100,7 +101,7 @@ public class CacheContention implements Command<CacheContention.Arguments> {
     }
 
     /** {@inheritDoc} */
-    @Override public Object execute(GridClientConfiguration clientCfg, CommandLogger logger) throws Exception {
+    @Override public Object execute(GridClientConfiguration clientCfg, Logger logger) throws Exception {
         VisorContentionTaskArg taskArg = new VisorContentionTaskArg(args.minQueueSize(), args.maxPrint());
 
         UUID nodeId = args.nodeId() == null ? BROADCAST_UUID : args.nodeId();
@@ -111,7 +112,7 @@ public class CacheContention implements Command<CacheContention.Arguments> {
             res = executeTaskByNameOnNode(client, VisorContentionTask.class.getName(), taskArg, nodeId, clientCfg);
         }
 
-        logger.printErrors(res.exceptions(), "Contention check failed on nodes:");
+        CommandLogger.printErrors(res.exceptions(), "Contention check failed on nodes:", logger);
 
         for (ContentionInfo info : res.getInfos())
             info.print();
@@ -135,4 +136,9 @@ public class CacheContention implements Command<CacheContention.Arguments> {
 
         args = new Arguments(nodeId, minQueueSize, maxPrint);
     }
+
+    /** {@inheritDoc} */
+    @Override public String name() {
+        return CONTENTION.text().toUpperCase();
+    }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheDistribution.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheDistribution.java
index bf37ffd..449f576 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheDistribution.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheDistribution.java
@@ -19,6 +19,7 @@ package org.apache.ignite.internal.commandline.cache;
 import java.util.HashSet;
 import java.util.Set;
 import java.util.UUID;
+import java.util.logging.Logger;
 import org.apache.ignite.internal.client.GridClient;
 import org.apache.ignite.internal.client.GridClientConfiguration;
 import org.apache.ignite.internal.commandline.Command;
@@ -46,11 +47,11 @@ import static org.apache.ignite.internal.commandline.cache.argument.Distribution
  */
 public class CacheDistribution implements Command<CacheDistribution.Arguments> {
     /** {@inheritDoc} */
-    @Override public void printUsage(CommandLogger logger) {
+    @Override public void printUsage() {
         String CACHES = "cacheName1,...,cacheNameN";
         String description = "Prints the information about partition distribution.";
 
-        usageCache(logger, DISTRIBUTION, description, null,
+        usageCache(DISTRIBUTION, description, null,
             or(NODE_ID, CommandHandler.NULL), optional(CACHES), optional(USER_ATTRIBUTES, "attrName1,...,attrNameN"));
     }
 
@@ -107,7 +108,7 @@ public class CacheDistribution implements Command<CacheDistribution.Arguments> {
     }
 
     /** {@inheritDoc} */
-    @Override public Object execute(GridClientConfiguration clientCfg, CommandLogger logger) throws Exception {
+    @Override public Object execute(GridClientConfiguration clientCfg, Logger logger) throws Exception {
         CacheDistributionTaskArg taskArg = new CacheDistributionTaskArg(args.caches(), args.getUserAttributes());
 
         UUID nodeId = args.nodeId() == null ? BROADCAST_UUID : args.nodeId();
@@ -118,7 +119,7 @@ public class CacheDistribution implements Command<CacheDistribution.Arguments> {
             res = executeTaskByNameOnNode(client, CacheDistributionTask.class.getName(), taskArg, nodeId, clientCfg);
         }
 
-        logger.printErrors(res.exceptions(), "Cache distrubution task failed on nodes:");
+        CommandLogger.printErrors(res.exceptions(), "Cache distrubution task failed on nodes:", logger);
 
         res.print(System.out);
 
@@ -159,4 +160,9 @@ public class CacheDistribution implements Command<CacheDistribution.Arguments> {
 
         args = new Arguments(caches, nodeId, userAttributes);
     }
+
+    /** {@inheritDoc} */
+    @Override public String name() {
+        return DISTRIBUTION.text().toUpperCase();
+    }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheValidateIndexes.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheValidateIndexes.java
index 7789fde..4666eb7 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheValidateIndexes.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheValidateIndexes.java
@@ -22,6 +22,7 @@ import java.util.Collections;
 import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
+import java.util.logging.Logger;
 import org.apache.ignite.internal.client.GridClient;
 import org.apache.ignite.internal.client.GridClientConfiguration;
 import org.apache.ignite.internal.commandline.Command;
@@ -39,6 +40,7 @@ import org.apache.ignite.internal.visor.verify.VisorValidateIndexesJobResult;
 import org.apache.ignite.internal.visor.verify.VisorValidateIndexesTaskArg;
 import org.apache.ignite.internal.visor.verify.VisorValidateIndexesTaskResult;
 
+import static org.apache.ignite.internal.commandline.CommandLogger.INDENT;
 import static org.apache.ignite.internal.commandline.CommandLogger.optional;
 import static org.apache.ignite.internal.commandline.CommandLogger.or;
 import static org.apache.ignite.internal.commandline.TaskExecutor.executeTaskByNameOnNode;
@@ -57,7 +59,7 @@ import static org.apache.ignite.internal.processors.cache.GridCacheUtils.UTILITY
  */
 public class CacheValidateIndexes implements Command<CacheValidateIndexes.Arguments> {
     /** {@inheritDoc} */
-    @Override public void printUsage(CommandLogger logger) {
+    @Override public void printUsage() {
         String CACHES = "cacheName1,...,cacheNameN";
         String description = "Verify counters and hash sums of primary and backup partitions for the specified " +
             "caches/cache groups on an idle cluster and print out the differences, if any. " +
@@ -72,7 +74,7 @@ public class CacheValidateIndexes implements Command<CacheValidateIndexes.Argume
         map.put(CHECK_FIRST + " N", "validate only the first N keys");
         map.put(CHECK_THROUGH + " K", "validate every Kth key");
 
-        usageCache(logger, VALIDATE_INDEXES, description, map,
+        usageCache(VALIDATE_INDEXES, description, map,
             optional(CACHES), OP_NODE_ID, optional(or(CHECK_FIRST + " N", CHECK_THROUGH + " K")));
     }
 
@@ -141,7 +143,7 @@ public class CacheValidateIndexes implements Command<CacheValidateIndexes.Argume
     }
 
     /** {@inheritDoc} */
-    @Override public Object execute(GridClientConfiguration clientCfg, CommandLogger logger) throws Exception {
+    @Override public Object execute(GridClientConfiguration clientCfg, Logger logger) throws Exception {
         VisorValidateIndexesTaskArg taskArg = new VisorValidateIndexesTaskArg(
             args.caches(),
             args.nodeId() != null ? Collections.singleton(args.nodeId()) : null,
@@ -153,7 +155,7 @@ public class CacheValidateIndexes implements Command<CacheValidateIndexes.Argume
             VisorValidateIndexesTaskResult taskRes = executeTaskByNameOnNode(
                 client, "org.apache.ignite.internal.visor.verify.VisorValidateIndexesTask", taskArg, null, clientCfg);
 
-            boolean errors = logger.printErrors(taskRes.exceptions(), "Index validation failed on nodes:");
+            boolean errors = CommandLogger.printErrors(taskRes.exceptions(), "Index validation failed on nodes:", logger);
 
             for (Map.Entry<UUID, VisorValidateIndexesJobResult> nodeEntry : taskRes.results().entrySet()) {
                 if (!nodeEntry.getValue().hasIssues())
@@ -161,13 +163,13 @@ public class CacheValidateIndexes implements Command<CacheValidateIndexes.Argume
 
                 errors = true;
 
-                logger.log("Index issues found on node " + nodeEntry.getKey() + ":");
+                logger.info("Index issues found on node " + nodeEntry.getKey() + ":");
 
                 Collection<IndexIntegrityCheckIssue> integrityCheckFailures = nodeEntry.getValue().integrityCheckFailures();
 
                 if (!integrityCheckFailures.isEmpty()) {
                     for (IndexIntegrityCheckIssue is : integrityCheckFailures)
-                        logger.logWithIndent(is);
+                        logger.info(INDENT + is);
                 }
 
                 Map<PartitionKey, ValidateIndexesPartitionResult> partRes = nodeEntry.getValue().partitionResult();
@@ -176,10 +178,10 @@ public class CacheValidateIndexes implements Command<CacheValidateIndexes.Argume
                     ValidateIndexesPartitionResult res = e.getValue();
 
                     if (!res.issues().isEmpty()) {
-                        logger.logWithIndent(CommandLogger.join(" ", e.getKey(), e.getValue()));
+                        logger.info(INDENT + CommandLogger.join(" ", e.getKey(), e.getValue()));
 
                         for (IndexValidationIssue is : res.issues())
-                            logger.logWithIndent(is, 2);
+                            logger.info(INDENT + INDENT + is);
                     }
                 }
 
@@ -189,20 +191,20 @@ public class CacheValidateIndexes implements Command<CacheValidateIndexes.Argume
                     ValidateIndexesPartitionResult res = e.getValue();
 
                     if (!res.issues().isEmpty()) {
-                        logger.logWithIndent(CommandLogger.join(" ", "SQL Index", e.getKey(), e.getValue()));
+                        logger.info(INDENT + CommandLogger.join(" ", "SQL Index", e.getKey(), e.getValue()));
 
                         for (IndexValidationIssue is : res.issues())
-                            logger.logWithIndent(is, 2);
+                            logger.info(INDENT + INDENT + is);
                     }
                 }
             }
 
             if (!errors)
-                logger.log("no issues found.");
+                logger.severe("no issues found.");
             else
-                logger.log("issues found (listed above).");
+                logger.severe("issues found (listed above).");
 
-            logger.nl();
+            logger.info("");
 
             return taskRes;
         }
@@ -270,4 +272,9 @@ public class CacheValidateIndexes implements Command<CacheValidateIndexes.Argume
 
         args = new Arguments(caches, nodeId, checkFirst, checkThrough);
     }
+
+    /** {@inheritDoc} */
+    @Override public String name() {
+        return VALIDATE_INDEXES.text().toUpperCase();
+    }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheViewer.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheViewer.java
index b5d0f14..94bf95c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheViewer.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheViewer.java
@@ -20,13 +20,13 @@ import java.util.Collection;
 import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.UUID;
+import java.util.logging.Logger;
 import java.util.stream.Collectors;
 import org.apache.ignite.internal.client.GridClient;
 import org.apache.ignite.internal.client.GridClientConfiguration;
 import org.apache.ignite.internal.client.GridClientException;
 import org.apache.ignite.internal.commandline.Command;
 import org.apache.ignite.internal.commandline.CommandArgIterator;
-import org.apache.ignite.internal.commandline.CommandLogger;
 import org.apache.ignite.internal.commandline.OutputFormat;
 import org.apache.ignite.internal.commandline.TaskExecutor;
 import org.apache.ignite.internal.commandline.argument.CommandArgUtils;
@@ -69,7 +69,7 @@ import static org.apache.ignite.internal.visor.verify.VisorViewCacheCmd.SEQ;
  */
 public class CacheViewer implements Command<CacheViewer.Arguments> {
     /** {@inheritDoc} */
-    @Override public void printUsage(CommandLogger logger) {
+    @Override public void printUsage() {
         String description = "Show information about caches, groups or sequences that match a regular expression. " +
             "When executed without parameters, this subcommand prints the list of caches.";
 
@@ -81,7 +81,7 @@ public class CacheViewer implements Command<CacheViewer.Arguments> {
         map.put(GROUP.toString(), "print information about groups.");
         map.put(SEQUENCE.toString(), "print information about sequences.");
 
-        usageCache(logger, LIST, description, map, "regexPattern",
+        usageCache(LIST, description, map, "regexPattern",
             optional(or(GROUP, SEQUENCE)), OP_NODE_ID, optional(CONFIG), optional(OUTPUT_FORMAT, MULTI_LINE));
     }
 
@@ -156,7 +156,7 @@ public class CacheViewer implements Command<CacheViewer.Arguments> {
     }
 
     /** {@inheritDoc} */
-    @Override public Object execute(GridClientConfiguration clientCfg, CommandLogger logger) throws Exception {
+    @Override public Object execute(GridClientConfiguration clientCfg, Logger logger) throws Exception {
         VisorViewCacheTaskArg taskArg = new VisorViewCacheTaskArg(args.regex(), args.cacheCommand());
 
         VisorViewCacheTaskResult res;
@@ -337,7 +337,7 @@ public class CacheViewer implements Command<CacheViewer.Arguments> {
         Map<String, VisorCacheConfiguration> caches,
         OutputFormat outputFormat,
         Map<String, Integer> cacheToMapped,
-        CommandLogger logger
+        Logger logger
     ) {
 
         for (Map.Entry<String, VisorCacheConfiguration> entry : caches.entrySet()) {
@@ -349,19 +349,19 @@ public class CacheViewer implements Command<CacheViewer.Arguments> {
 
                     params.put("Mapped", cacheToMapped.get(cacheName));
 
-                    logger.log("[cache = '%s']%n", cacheName);
+                    logger.info(String.format("[cache = '%s']%n", cacheName));
 
                     for (Map.Entry<String, Object> innerEntry : params.entrySet())
-                        logger.log("%s: %s%n", innerEntry.getKey(), innerEntry.getValue());
+                        logger.info(String.format("%s: %s%n", innerEntry.getKey(), innerEntry.getValue()));
 
-                    logger.nl();
+                    logger.info("");
 
                     break;
 
                 default:
                     int mapped = cacheToMapped.get(cacheName);
 
-                    logger.log("%s: %s %s=%s%n", entry.getKey(), toString(entry.getValue()), "mapped", mapped);
+                    logger.info(String.format("%s: %s %s=%s%n", entry.getKey(), toString(entry.getValue()), "mapped", mapped));
 
                     break;
             }
@@ -389,7 +389,7 @@ public class CacheViewer implements Command<CacheViewer.Arguments> {
         Arguments cacheArgs,
         VisorViewCacheTaskResult viewRes,
         GridClientConfiguration clientCfg,
-        CommandLogger logger
+        Logger logger
     ) throws GridClientException {
         VisorCacheConfigurationCollectorTaskArg taskArg = new VisorCacheConfigurationCollectorTaskArg(cacheArgs.regex());
 
@@ -410,7 +410,7 @@ public class CacheViewer implements Command<CacheViewer.Arguments> {
      * @param infos Caches info.
      * @param cmd Command.
      */
-    private void printCacheInfos(Collection<CacheInfo> infos, VisorViewCacheCmd cmd, CommandLogger logger) {
+    private void printCacheInfos(Collection<CacheInfo> infos, VisorViewCacheCmd cmd, Logger logger) {
         for (CacheInfo info : infos) {
             Map<String, Object> map = info.toMap(cmd);
 
@@ -423,7 +423,12 @@ public class CacheViewer implements Command<CacheViewer.Arguments> {
 
             sb.a("]");
 
-            logger.log(sb.toString());
+            logger.info(sb.toString());
         }
     }
+
+    /** {@inheritDoc} */
+    @Override public String name() {
+        return LIST.text().toUpperCase();
+    }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/FindAndDeleteGarbage.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/FindAndDeleteGarbage.java
index 3dfe6c8..91f9d9d 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/FindAndDeleteGarbage.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/FindAndDeleteGarbage.java
@@ -20,6 +20,7 @@ import java.util.Collections;
 import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
+import java.util.logging.Logger;
 import org.apache.ignite.internal.client.GridClient;
 import org.apache.ignite.internal.client.GridClientConfiguration;
 import org.apache.ignite.internal.commandline.Command;
@@ -32,6 +33,7 @@ import org.apache.ignite.internal.visor.cache.VisorFindAndDeleteGarbageInPersist
 import org.apache.ignite.internal.visor.cache.VisorFindAndDeleteGarbageInPersistenceTaskArg;
 import org.apache.ignite.internal.visor.cache.VisorFindAndDeleteGarbageInPersistenceTaskResult;
 
+import static org.apache.ignite.internal.commandline.CommandLogger.INDENT;
 import static org.apache.ignite.internal.commandline.CommandLogger.optional;
 import static org.apache.ignite.internal.commandline.TaskExecutor.executeTask;
 import static org.apache.ignite.internal.commandline.cache.CacheCommands.OP_NODE_ID;
@@ -43,12 +45,12 @@ import static org.apache.ignite.internal.commandline.cache.CacheSubcommands.FIND
  */
 public class FindAndDeleteGarbage implements Command<FindAndDeleteGarbage.Arguments> {
     /** {@inheritDoc} */
-    @Override public void printUsage(CommandLogger logger) {
+    @Override public void printUsage() {
         String GROUPS = "groupName1,...,groupNameN";
         String description = "Find and optionally delete garbage from shared cache groups which could be left " +
             "after cache destroy.";
 
-        usageCache(logger, FIND_AND_DELETE_GARBAGE, description, null,
+        usageCache(FIND_AND_DELETE_GARBAGE, description, null,
             optional(GROUPS), OP_NODE_ID, optional(FindAndDeleteGarbageArg.DELETE));
     }
 
@@ -105,7 +107,7 @@ public class FindAndDeleteGarbage implements Command<FindAndDeleteGarbage.Argume
     }
 
     /** {@inheritDoc} */
-    @Override public Object execute(GridClientConfiguration clientCfg, CommandLogger logger) throws Exception {
+    @Override public Object execute(GridClientConfiguration clientCfg, Logger logger) throws Exception {
         VisorFindAndDeleteGarbageInPersistenceTaskArg taskArg = new VisorFindAndDeleteGarbageInPersistenceTaskArg(
             args.groups(),
             args.delete(),
@@ -116,16 +118,16 @@ public class FindAndDeleteGarbage implements Command<FindAndDeleteGarbage.Argume
             VisorFindAndDeleteGarbageInPersistenceTaskResult taskRes = executeTask(
                 client, VisorFindAndDeleteGarbageInPersistenceTask.class, taskArg, clientCfg);
 
-            logger.printErrors(taskRes.exceptions(), "Scanning for garbage failed on nodes:");
+            CommandLogger.printErrors(taskRes.exceptions(), "Scanning for garbage failed on nodes:", logger);
 
             for (Map.Entry<UUID, VisorFindAndDeleteGarbageInPersistenceJobResult> nodeEntry : taskRes.result().entrySet()) {
                 if (!nodeEntry.getValue().hasGarbage()) {
-                    logger.log("Node " + nodeEntry.getKey() + " - garbage not found.");
+                    logger.info("Node " + nodeEntry.getKey() + " - garbage not found.");
 
                     continue;
                 }
 
-                logger.log("Garbage found on node " + nodeEntry.getKey() + ":");
+                logger.info("Garbage found on node " + nodeEntry.getKey() + ":");
 
                 VisorFindAndDeleteGarbageInPersistenceJobResult value = nodeEntry.getValue();
 
@@ -134,14 +136,14 @@ public class FindAndDeleteGarbage implements Command<FindAndDeleteGarbage.Argume
                 if (!grpPartErrorsCount.isEmpty()) {
                     for (Map.Entry<Integer, Map<Integer, Long>> entry : grpPartErrorsCount.entrySet()) {
                         for (Map.Entry<Integer, Long> e : entry.getValue().entrySet()) {
-                            logger.logWithIndent("Group=" + entry.getKey() +
+                            logger.info(INDENT + "Group=" + entry.getKey() +
                                 ", partition=" + e.getKey() +
                                 ", count of keys=" + e.getValue());
                         }
                     }
                 }
 
-                logger.nl();
+                logger.info("");
             }
 
             return taskRes;
@@ -181,4 +183,9 @@ public class FindAndDeleteGarbage implements Command<FindAndDeleteGarbage.Argume
 
         args = new Arguments(groups, nodeId, delete);
     }
+
+    /** {@inheritDoc} */
+    @Override public String name() {
+        return FIND_AND_DELETE_GARBAGE.text().toUpperCase();
+    }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/IdleVerify.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/IdleVerify.java
index 036bce4..b62f6fc 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/IdleVerify.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/IdleVerify.java
@@ -22,6 +22,7 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.logging.Logger;
 import java.util.regex.Pattern;
 import java.util.regex.PatternSyntaxException;
 import org.apache.ignite.IgniteException;
@@ -32,7 +33,6 @@ import org.apache.ignite.internal.client.GridClientException;
 import org.apache.ignite.internal.client.GridClientNode;
 import org.apache.ignite.internal.commandline.Command;
 import org.apache.ignite.internal.commandline.CommandArgIterator;
-import org.apache.ignite.internal.commandline.CommandLogger;
 import org.apache.ignite.internal.commandline.argument.CommandArgUtils;
 import org.apache.ignite.internal.commandline.cache.argument.IdleVerifyCommandArg;
 import org.apache.ignite.internal.processors.cache.verify.IdleVerifyResultV2;
@@ -72,7 +72,7 @@ import static org.apache.ignite.internal.visor.verify.CacheFilterEnum.USER;
  */
 public class IdleVerify implements Command<IdleVerify.Arguments> {
     /** {@inheritDoc} */
-    @Override public void printUsage(CommandLogger logger) {
+    @Override public void printUsage() {
         String CACHES = "cacheName1,...,cacheNameN";
         String description = "Verify counters and hash sums of primary and backup partitions for the specified caches/cache " +
             "groups on an idle cluster and print out the differences, if any. When no parameters are specified, " +
@@ -83,7 +83,7 @@ public class IdleVerify implements Command<IdleVerify.Arguments> {
             " you can verify: only " + USER + " caches, only user " + PERSISTENT + " caches, only user " +
             NOT_PERSISTENT + " caches, only " + SYSTEM + " caches, or " + ALL + " of the above.";
 
-        usageCache(logger,
+        usageCache(
             IDLE_VERIFY,
             description,
             Collections.singletonMap(CHECK_CRC.toString(),
@@ -182,7 +182,7 @@ public class IdleVerify implements Command<IdleVerify.Arguments> {
     }
 
     /** {@inheritDoc} */
-    @Override public Object execute(GridClientConfiguration clientCfg, CommandLogger logger) throws Exception {
+    @Override public Object execute(GridClientConfiguration clientCfg, Logger logger) throws Exception {
         try (GridClient client = Command.startClient(clientCfg)) {
             Collection<GridClientNode> nodes = client.compute().nodes(GridClientNode::connectable);
 
@@ -306,7 +306,7 @@ public class IdleVerify implements Command<IdleVerify.Arguments> {
     private void cacheIdleVerifyDump(
         GridClient client,
         GridClientConfiguration clientCfg,
-        CommandLogger logger
+        Logger logger
     ) throws GridClientException {
         VisorIdleVerifyDumpTaskArg arg = new VisorIdleVerifyDumpTaskArg(
             args.caches(),
@@ -318,7 +318,7 @@ public class IdleVerify implements Command<IdleVerify.Arguments> {
 
         String path = executeTask(client, VisorIdleVerifyDumpTask.class, arg, clientCfg);
 
-        logger.log("VisorIdleVerifyDumpTask successfully written output to '" + path + "'");
+        logger.info("VisorIdleVerifyDumpTask successfully written output to '" + path + "'");
     }
 
 
@@ -347,7 +347,7 @@ public class IdleVerify implements Command<IdleVerify.Arguments> {
     private void legacyCacheIdleVerify(
         GridClient client,
         GridClientConfiguration clientCfg,
-        CommandLogger logger
+        Logger logger
     ) throws GridClientException {
         VisorIdleVerifyTaskResult res = executeTask(
             client,
@@ -358,18 +358,23 @@ public class IdleVerify implements Command<IdleVerify.Arguments> {
         Map<PartitionKey, List<PartitionHashRecord>> conflicts = res.getConflicts();
 
         if (conflicts.isEmpty()) {
-            logger.log("idle_verify check has finished, no conflicts have been found.");
-            logger.nl();
+            logger.info("idle_verify check has finished, no conflicts have been found.");
+            logger.info("");
         }
         else {
-            logger.log("idle_verify check has finished, found " + conflicts.size() + " conflict partitions.");
-            logger.nl();
+            logger.info("idle_verify check has finished, found " + conflicts.size() + " conflict partitions.");
+            logger.info("");
 
             for (Map.Entry<PartitionKey, List<PartitionHashRecord>> entry : conflicts.entrySet()) {
-                logger.log("Conflict partition: " + entry.getKey());
+                logger.info("Conflict partition: " + entry.getKey());
 
-                logger.log("Partition instances: " + entry.getValue());
+                logger.info("Partition instances: " + entry.getValue());
             }
         }
     }
+
+    /** {@inheritDoc} */
+    @Override public String name() {
+        return IDLE_VERIFY.text().toUpperCase();
+    }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/ResetLostPartitions.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/ResetLostPartitions.java
index 68f2ca7..c8b21a7 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/ResetLostPartitions.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/ResetLostPartitions.java
@@ -17,11 +17,11 @@
 package org.apache.ignite.internal.commandline.cache;
 
 import java.util.Set;
+import java.util.logging.Logger;
 import org.apache.ignite.internal.client.GridClient;
 import org.apache.ignite.internal.client.GridClientConfiguration;
 import org.apache.ignite.internal.commandline.Command;
 import org.apache.ignite.internal.commandline.CommandArgIterator;
-import org.apache.ignite.internal.commandline.CommandLogger;
 import org.apache.ignite.internal.commandline.cache.reset_lost_partitions.CacheResetLostPartitionsTask;
 import org.apache.ignite.internal.commandline.cache.reset_lost_partitions.CacheResetLostPartitionsTaskArg;
 import org.apache.ignite.internal.commandline.cache.reset_lost_partitions.CacheResetLostPartitionsTaskResult;
@@ -35,11 +35,11 @@ import static org.apache.ignite.internal.commandline.cache.CacheSubcommands.RESE
  */
 public class ResetLostPartitions implements Command<Set<String>> {
     /** {@inheritDoc} */
-    @Override public void printUsage(CommandLogger logger) {
+    @Override public void printUsage() {
         String CACHES = "cacheName1,...,cacheNameN";
         String description = "Reset the state of lost partitions for the specified caches.";
 
-        usageCache(logger, RESET_LOST_PARTITIONS, description, null, CACHES);
+        usageCache(RESET_LOST_PARTITIONS, description, null, CACHES);
     }
 
     /**
@@ -53,7 +53,7 @@ public class ResetLostPartitions implements Command<Set<String>> {
     }
 
     /** {@inheritDoc} */
-    @Override public Object execute(GridClientConfiguration clientCfg, CommandLogger logger) throws Exception {
+    @Override public Object execute(GridClientConfiguration clientCfg, Logger logger) throws Exception {
         CacheResetLostPartitionsTaskArg taskArg = new CacheResetLostPartitionsTaskArg(caches);
 
         try (GridClient client = Command.startClient(clientCfg)) {
@@ -70,4 +70,9 @@ public class ResetLostPartitions implements Command<Set<String>> {
     @Override public void parseArguments(CommandArgIterator argIter) {
         caches = argIter.nextStringSet("Cache names");
     }
+
+    /** {@inheritDoc} */
+    @Override public String name() {
+        return RESET_LOST_PARTITIONS.text().toUpperCase();
+    }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/logger/java/JavaLoggerFileHandler.java b/modules/core/src/main/java/org/apache/ignite/logger/java/JavaLoggerFileHandler.java
index f37350a..e758d34 100644
--- a/modules/core/src/main/java/org/apache/ignite/logger/java/JavaLoggerFileHandler.java
+++ b/modules/core/src/main/java/org/apache/ignite/logger/java/JavaLoggerFileHandler.java
@@ -135,7 +135,7 @@ public final class JavaLoggerFileHandler extends StreamHandler {
      * @param workDir Work directory.
      * @return Logging directory.
      */
-    private static File logDirectory(String workDir) throws IgniteCheckedException {
+    public static File logDirectory(String workDir) throws IgniteCheckedException {
         return !F.isEmpty(U.IGNITE_LOG_DIR) ? new File(U.IGNITE_LOG_DIR) :
             U.resolveWorkDirectory(workDir, "log", false);
     }
diff --git a/modules/core/src/test/java/org/apache/ignite/util/GridCommandHandlerAbstractTest.java b/modules/core/src/test/java/org/apache/ignite/util/GridCommandHandlerAbstractTest.java
index ccfa7f8..edb77e4 100644
--- a/modules/core/src/test/java/org/apache/ignite/util/GridCommandHandlerAbstractTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/util/GridCommandHandlerAbstractTest.java
@@ -22,8 +22,11 @@ import java.nio.file.DirectoryStream;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.List;
+import java.util.logging.Handler;
+import java.util.logging.Logger;
 import java.util.stream.Collectors;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.configuration.AtomicConfiguration;
@@ -90,7 +93,7 @@ public class GridCommandHandlerAbstractTest extends GridCommonAbstractTest {
 
         sysOut = System.out;
 
-        testOut = new ByteArrayOutputStream(20 * 1024 * 1024);
+        testOut = new ByteArrayOutputStream(40 * 1024 * 1024);
 
         checkpointFreq = DataStorageConfiguration.DFLT_CHECKPOINT_FREQ;
     }
@@ -182,7 +185,13 @@ public class GridCommandHandlerAbstractTest extends GridCommonAbstractTest {
         if (!F.isEmpty(args) && !"--help".equalsIgnoreCase(args.get(0)))
             addExtraArguments(args);
 
-        return hnd.execute(args);
+        int exitCode = hnd.execute(args);
+
+        // Flush all Logger handlers to make log data available to test.
+        Logger logger = U.field(hnd, "logger");
+        Arrays.stream(logger.getHandlers()).forEach(Handler::flush);
+
+        return exitCode;
     }
 
     /**
diff --git a/modules/core/src/test/java/org/apache/ignite/util/GridCommandHandlerTest.java b/modules/core/src/test/java/org/apache/ignite/util/GridCommandHandlerTest.java
index 99f1fa6..1778498 100644
--- a/modules/core/src/test/java/org/apache/ignite/util/GridCommandHandlerTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/util/GridCommandHandlerTest.java
@@ -1022,8 +1022,15 @@ public class GridCommandHandlerTest extends GridCommandHandlerAbstractTest {
 
         assertEquals(EXIT_CODE_UNEXPECTED_ERROR, execute("--baseline", "add", consistentIDs));
 
-        assertTrue(testOut.toString(), testOut.toString().contains("Node not found for consistent ID:"));
-        assertFalse(testOut.toString(), testOut.toString().contains(getTestIgniteInstanceName() + "1"));
+        String testOutStr = testOut.toString();
+
+        // Ignite instase 1 can be logged only in arguments list.
+        boolean isInstanse1Found = Arrays.stream(testOutStr.split("\n"))
+                                        .filter(s -> s.contains("Arguments:"))
+                                        .noneMatch(s -> s.contains(getTestIgniteInstanceName() + "1"));
+
+        assertTrue(testOutStr, testOutStr.contains("Node not found for consistent ID:"));
+        assertFalse(testOutStr, isInstanse1Found);
     }
 
     /**
@@ -2306,20 +2313,21 @@ public class GridCommandHandlerTest extends GridCommandHandlerAbstractTest {
 
         out = testOut.toString();
 
-        // Find last row
-        int lastRowIndex = out.lastIndexOf('\n');
-
-        assertTrue(lastRowIndex > 0);
+        List<String> outLines = Arrays.stream(out.split("\n"))
+                                .map(String::trim)
+                                .collect(Collectors.toList());
 
-        // Last row is empty, but the previous line contains data
-        lastRowIndex = out.lastIndexOf('\n', lastRowIndex - 1);
+        int firstIndex = outLines.indexOf("[next group: id=1544803905, name=default]");
+        int lastIndex  = outLines.lastIndexOf("[next group: id=1544803905, name=default]");
 
-        assertTrue(lastRowIndex > 0);
+        String dataLine = outLines.get(firstIndex + 1);
+        String userArrtDataLine = outLines.get(lastIndex + 1);
 
-        String lastRow = out.substring(lastRowIndex);
+        long commaNum = dataLine.chars().filter(i -> i == ',').count();
+        long userArrtCommaNum = userArrtDataLine.chars().filter(i -> i == ',').count();
 
-        // Since 3 user attributes have been added, the total number of columns in response should be 12 (separators 11)
-        assertEquals(11, lastRow.split(",").length);
+        // Check that number of columns increased by 3
+        assertEquals(3, userArrtCommaNum - commaNum);
     }
 
     /**


[ignite] 26/31: GG-19147 Resharper inspections got broken after update

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch gg-19225
in repository https://gitbox.apache.org/repos/asf/ignite.git

commit 536d397a03a757631ea5227a85a09d13689454e1
Author: Alexandr Shapkin <as...@gridgain.com>
AuthorDate: Thu May 30 17:04:19 2019 +0300

    GG-19147 Resharper inspections got broken after update
    
    (cherry picked from commit bfd97007c584f57496db87aa9007796712a4f605)
---
 .../dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/NativeMethod.cs         | 1 +
 1 file changed, 1 insertion(+)

diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/NativeMethod.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/NativeMethod.cs
index 10bf64c..2c00816 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/NativeMethod.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/NativeMethod.cs
@@ -42,6 +42,7 @@ namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
         /// <summary>
         /// Function pointer (from <see cref="Marshal.GetFunctionPointerForDelegate"/>).
         /// </summary>
+        // ReSharper disable once NotAccessedField.Global
         public IntPtr FuncPtr;
     }
 }


[ignite] 10/31: IGNITE-10178 change tests that fail(Ignite JIRA) to @Ignore(Ignite JIRA). - Fixes #5824.

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch gg-19225
in repository https://gitbox.apache.org/repos/asf/ignite.git

commit 0acb359897ae22a83bd61881eef8338eb0a8d2a4
Author: Oleg Ignatenko <oi...@gridgain.com>
AuthorDate: Thu May 30 14:48:08 2019 +0300

    IGNITE-10178 change tests that fail(Ignite JIRA) to @Ignore(Ignite JIRA). - Fixes #5824.
    
    Signed-off-by: Dmitriy Pavlov <dp...@apache.org>
---
 .../internal/client/ClientSslParametersTest.java   | 10 +--
 .../jdbc/thin/JdbcThinStatementSelfTest.java       |  4 +-
 ...dbcThinTransactionsAbstractComplexSelfTest.java | 11 ++-
 .../internal/jdbc/thin/JdbcThinConnection.java     |  6 +-
 .../ignite/cache/ResetLostPartitionTest.java       |  8 +-
 .../ignite/failure/IoomFailureHandlerTest.java     |  4 +-
 .../AuthenticationProcessorNodeRestartTest.java    | 10 +--
 .../cache/CacheEventWithTxLabelTest.java           |  6 +-
 ...InterceptorPartitionCounterLocalSanityTest.java |  7 +-
 ...ceptorPartitionCounterRandomOperationsTest.java |  5 +-
 .../processors/cache/CacheMetricsManageTest.java   |  6 +-
 .../processors/cache/CacheRemoveAllSelfTest.java   |  6 +-
 .../cache/GridCacheAbstractIteratorsSelfTest.java  | 16 ++--
 .../cache/GridCacheClearAllSelfTest.java           |  4 +-
 .../GridCacheMixedPartitionExchangeSelfTest.java   |  6 +-
 ...ultinodeUpdateNearEnabledNoBackupsSelfTest.java | 10 +--
 ...ridCacheMultinodeUpdateNearEnabledSelfTest.java | 10 +--
 .../GridCacheMvccMultiThreadedUpdateSelfTest.java  |  6 +-
 .../cache/GridCachePartitionedGetSelfTest.java     |  4 +-
 .../GridCacheReturnValueTransferSelfTest.java      |  7 +-
 .../GridCacheValueConsistencyAbstractSelfTest.java |  7 +-
 .../cache/GridCacheVariableTopologySelfTest.java   |  4 +-
 .../processors/cache/IgniteCacheGroupsTest.java    | 34 +++-----
 ...IgniteCacheInvokeReadThroughSingleNodeTest.java |  6 +-
 .../cache/IgniteCacheInvokeReadThroughTest.java    |  6 +-
 .../cache/IgniteClusterActivateDeactivateTest.java |  6 +-
 ...usterActivateDeactivateTestWithPersistence.java |  6 +-
 ...eactivateTestWithPersistenceAndMemoryReuse.java |  6 +-
 ...teDynamicCacheStartFailWithPersistenceTest.java |  6 +-
 .../IgniteMvccTxSingleThreadedAbstractTest.java    |  7 +-
 .../cache/IgnitePdsDataRegionMetricsTxTest.java    |  6 +-
 .../IgniteTopologyValidatorGridSplitCacheTest.java |  4 +-
 .../cache/IgniteTxExceptionAbstractSelfTest.java   |  6 +-
 .../GridCacheBinaryObjectsAbstractSelfTest.java    |  4 +-
 ...dCachePartitionedAtomicSetFailoverSelfTest.java |  4 +-
 .../GridCachePartitionedSetFailoverSelfTest.java   |  4 +-
 .../cache/distributed/CacheBlockOnGetAllTest.java  | 97 +++++++++++++++-------
 .../cache/distributed/CacheBlockOnScanTest.java    | 13 ++-
 .../distributed/CacheBlockOnSingleGetTest.java     | 97 +++++++++++++++-------
 .../CacheDataLossOnPartitionMoveTest.java          |  6 +-
 .../CacheGetInsideLockChangingTopologyTest.java    |  5 +-
 .../CacheLateAffinityAssignmentTest.java           |  6 +-
 .../CacheLoadingConcurrentGridStartSelfTest.java   |  4 +-
 .../distributed/GridCacheBasicOpAbstractTest.java  |  4 +-
 .../GridCachePartitionNotLoadedEventSelfTest.java  |  8 +-
 .../GridCachePreloadRestartAbstractSelfTest.java   |  6 +-
 .../GridCacheTransformEventSelfTest.java           | 10 +--
 ...niteCacheGroupsPartitionLossPolicySelfTest.java |  4 +-
 .../IgniteMvccTxTimeoutAbstractTest.java           |  4 +-
 ...WriteSynchronizationModesMultithreadedTest.java |  6 +-
 .../IgniteTxRemoveTimeoutObjectsTest.java          |  4 +-
 .../dht/GridCacheDhtPreloadPutGetSelfTest.java     |  6 +-
 ...idCachePartitionedNearDisabledLockSelfTest.java |  4 +-
 ...achePartitionedNearDisabledMetricsSelfTest.java |  4 +-
 .../GridCachePartitionsStateValidationTest.java    |  6 +-
 .../dht/GridCacheTxNodeFailureSelfTest.java        |  4 +-
 .../IgniteAtomicLongChangingTopologySelfTest.java  |  4 +-
 .../dht/IgniteCacheClearDuringRebalanceTest.java   |  4 +-
 .../dht/NotMappedPartitionInTxTest.java            |  7 +-
 .../near/GridPartitionedBackupLoadSelfTest.java    |  4 +-
 .../GridCacheRebalancingSyncSelfTest.java          |  9 +-
 ...dCacheRebalancingWithAsyncClearingMvccTest.java |  6 +-
 ...eRebalanceOnCachesStoppingOrDestroyingTest.java |  6 +-
 .../GridCacheReplicatedLockSelfTest.java           |  4 +-
 .../GridCacheSyncReplicatedPreloadSelfTest.java    |  4 +-
 .../replicated/GridReplicatedTxPreloadTest.java    |  4 +-
 .../GridCacheReplicatedPreloadSelfTest.java        |  4 +-
 .../eviction/paged/PageEvictionMetricTest.java     |  6 +-
 .../PageEvictionPagesRecyclingAndReusingTest.java  |  6 +-
 .../paged/PageEvictionReadThroughTest.java         |  6 +-
 .../eviction/paged/PageEvictionTouchOrderTest.java |  9 +-
 .../PageEvictionWithRebalanceAbstractTest.java     |  6 +-
 .../IgniteCacheExpiryPolicyAbstractTest.java       |  4 +-
 ...heAtomicNearEnabledMultiJvmFullApiSelfTest.java |  4 +-
 .../IgnitePdsCacheAssignmentNodeRestartsTest.java  |  6 +-
 .../IgnitePdsContinuousRestartTest.java            |  6 +-
 .../IgnitePdsPartitionFilesDestroyTest.java        |  6 +-
 .../IgnitePdsPartitionsStateRecoveryTest.java      |  4 +-
 ...gniteRebalanceScheduleResendPartitionsTest.java |  6 +-
 ...ocalWalModeChangeDuringRebalancingSelfTest.java |  6 +-
 .../ClientAffinityAssignmentWithBaselineTest.java  |  6 +-
 ...itePdsPageEvictionDuringPartitionClearTest.java |  6 +-
 .../db/IgnitePdsPartitionPreloadTest.java          |  7 +-
 ...gnitePdsRebalancingOnNotStableTopologyTest.java |  6 +-
 .../wal/IgniteNodeStoppedDuringDisableWALTest.java |  6 +-
 ...eWalFlushMultiNodeFailoverAbstractSelfTest.java |  4 +-
 .../db/wal/IgniteWalFormatFileFailoverTest.java    |  7 +-
 .../db/wal/IgniteWalHistoryReservationsTest.java   | 10 +--
 .../db/wal/reader/IgniteWalReaderTest.java         |  4 +-
 .../IgniteChangeGlobalStateServiceTest.java        |  4 +-
 .../IgniteChangeGlobalStateTest.java               |  5 +-
 .../join/JoinActiveNodeToActiveCluster.java        |  9 +-
 .../join/JoinActiveNodeToInActiveCluster.java      |  7 +-
 .../join/JoinInActiveNodeToActiveCluster.java      |  6 +-
 .../join/JoinInActiveNodeToInActiveCluster.java    |  7 +-
 .../wal/ExplicitWalDeltaConsistencyTest.java       |  6 +-
 .../CacheContinuousQueryExecuteInPrimaryTest.java  | 10 +--
 .../CacheKeepBinaryIterationStoreEnabledTest.java  |  7 +-
 ...ionIntegrityWithPrimaryIndexCorruptionTest.java |  6 +-
 .../cache/transactions/TxRollbackAsyncTest.java    | 12 ++-
 .../TxRollbackOnIncorrectParamsTest.java           |  6 +-
 .../transactions/TxRollbackOnTimeoutTest.java      |  6 +-
 .../TxRollbackOnTopologyChangeTest.java            | 10 +--
 .../database/IgniteDbDynamicCacheSelfTest.java     |  6 +-
 .../database/IgniteDbPutGetAbstractTest.java       |  4 +-
 .../DataStreamerMultiThreadedSelfTest.java         |  4 +-
 .../DataStreamerMultinodeCreateCacheTest.java      |  4 +-
 .../igfs/IgfsPrimaryMultiNodeSelfTest.java         |  4 +-
 ...PrimaryRelaxedConsistencyMultiNodeSelfTest.java |  4 +-
 .../ignite/internal/util/IgniteDevOnlyLogTest.java |  4 +-
 .../IpcSharedMemoryCrashDetectionSelfTest.java     |  4 +-
 .../tcp/TcpDiscoveryMultiThreadedTest.java         | 16 ++--
 .../IndexingCachePartitionLossPolicySelfTest.java  |  4 +-
 .../near/IgniteCacheQueryNodeRestartSelfTest2.java |  6 +-
 .../ignite/stream/mqtt/IgniteMqttStreamerTest.java | 12 ++-
 .../GridSpringCacheManagerMultiJvmSelfTest.java    |  4 +-
 116 files changed, 478 insertions(+), 446 deletions(-)

diff --git a/modules/clients/src/test/java/org/apache/ignite/internal/client/ClientSslParametersTest.java b/modules/clients/src/test/java/org/apache/ignite/internal/client/ClientSslParametersTest.java
index 1ec02ae..e18f961 100644
--- a/modules/clients/src/test/java/org/apache/ignite/internal/client/ClientSslParametersTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/internal/client/ClientSslParametersTest.java
@@ -144,7 +144,7 @@ public class ClientSslParametersTest extends GridCommonAbstractTest {
         };
 
         startGrid();
-        
+
         checkSuccessfulClientStart(
             new String[] {
                 "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
@@ -164,7 +164,7 @@ public class ClientSslParametersTest extends GridCommonAbstractTest {
         };
 
         startGrid();
-        
+
         checkClientStartFailure(
             new String[] {
                 "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
@@ -180,14 +180,12 @@ public class ClientSslParametersTest extends GridCommonAbstractTest {
     @Test
     @Ignore("https://issues.apache.org/jira/browse/IGNITE-10245")
     public void testNonExistentCipherSuite() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-10245");
-
         cipherSuites = new String[] {
             "TLS_RSA_WITH_AES_128_GCM_SHA256"
         };
 
         startGrid();
-        
+
         checkClientStartFailure(
             new String[] {
                 "TLC_FAKE_CIPHER",
@@ -225,8 +223,6 @@ public class ClientSslParametersTest extends GridCommonAbstractTest {
     @Test
     @Ignore("https://issues.apache.org/jira/browse/IGNITE-10245")
     public void testNonExistentProtocol() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-10245");
-
         protocols = new String[] {
             "SSLv3"
         };
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinStatementSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinStatementSelfTest.java
index 58ed1e5..22dc1e5 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinStatementSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinStatementSelfTest.java
@@ -31,6 +31,7 @@ import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.testframework.GridTestUtils;
+import org.junit.Ignore;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
 
@@ -658,9 +659,8 @@ public class JdbcThinStatementSelfTest extends JdbcThinAbstractSelfTest {
      * @throws Exception If failed.
      */
     @org.junit.Test
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-5440")
     public void testSetEscapeProcessing() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-5440");
-
         stmt.setEscapeProcessing(false);
 
         final String sqlText = "select {fn CONVERT(1, SQL_BOOLEAN)}";
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinTransactionsAbstractComplexSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinTransactionsAbstractComplexSelfTest.java
index e61b232..9a15f55 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinTransactionsAbstractComplexSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinTransactionsAbstractComplexSelfTest.java
@@ -355,7 +355,7 @@ public abstract class JdbcThinTransactionsAbstractComplexSelfTest extends JdbcTh
      */
     @Test
     public void testColocatedJoinSelectAndInsertInTransaction() throws SQLException {
-        // We'd like to put some Google into cities wgit checith over 1K population which don't have it yet
+        // We'd like to put some Google into cities with over 1K population which don't have it yet
         executeInTransaction(new TransactionClosure() {
             @Override public void apply(Connection conn) {
                 List<Integer> ids = flat(execute(conn, "SELECT distinct City.id from City left join Company c on " +
@@ -815,7 +815,7 @@ public abstract class JdbcThinTransactionsAbstractComplexSelfTest extends JdbcTh
     /**
      * @param c Connection to begin a transaction on.
      */
-    private void begin(Connection c) throws SQLException {
+    private void begin(Connection c) {
         if (autoCommit())
             execute(c, "BEGIN");
     }
@@ -865,7 +865,7 @@ public abstract class JdbcThinTransactionsAbstractComplexSelfTest extends JdbcTh
      * @return Result set.
      * @throws RuntimeException if failed.
      */
-    protected List<List<?>> execute(Connection conn, String sql, Object... args) {
+    @Override protected List<List<?>> execute(Connection conn, String sql, Object... args) {
         try {
             return super.execute(conn, sql, args);
         }
@@ -900,7 +900,7 @@ public abstract class JdbcThinTransactionsAbstractComplexSelfTest extends JdbcTh
      * @param params Connection parameters.
      * @return Thin JDBC connection to specified node.
      */
-    protected Connection connect(IgniteEx node, String params) {
+    @Override protected Connection connect(IgniteEx node, String params) {
         try {
             return super.connect(node, params);
         }
@@ -1050,7 +1050,7 @@ public abstract class JdbcThinTransactionsAbstractComplexSelfTest extends JdbcTh
     /**
      * Closure to be executed in scope of a transaction.
      */
-    private abstract class TransactionClosure implements IgniteInClosure<Connection> {
+    private abstract static class TransactionClosure implements IgniteInClosure<Connection> {
         // No-op.
     }
 
@@ -1066,7 +1066,6 @@ public abstract class JdbcThinTransactionsAbstractComplexSelfTest extends JdbcTh
      * @param rows Rows.
      * @return Rows as a single list.
      */
-    @SuppressWarnings("unchecked")
     private static <T> List<T> flat(Collection<? extends Collection<?>> rows) {
         return new ArrayList<>(F.flatCollections((Collection<? extends Collection<T>>)rows));
     }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java
index 431efdf..1044034 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java
@@ -29,7 +29,6 @@ import java.sql.PreparedStatement;
 import java.sql.SQLClientInfoException;
 import java.sql.SQLException;
 import java.sql.SQLFeatureNotSupportedException;
-import java.sql.SQLTimeoutException;
 import java.sql.SQLPermission;
 import java.sql.SQLTimeoutException;
 import java.sql.SQLWarning;
@@ -43,9 +42,9 @@ import java.util.IdentityHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
+import java.util.Set;
 import java.util.Timer;
 import java.util.TimerTask;
-import java.util.Set;
 import java.util.concurrent.Executor;
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -780,7 +779,6 @@ public class JdbcThinConnection implements Connection {
      * @return Server response.
      * @throws SQLException On any error.
      */
-    @SuppressWarnings("unchecked")
     <R extends JdbcResult> R sendRequest(JdbcRequest req, JdbcThinStatement stmt) throws SQLException {
         ensureConnected();
 
@@ -1186,4 +1184,4 @@ public class JdbcThinConnection implements Connection {
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/modules/core/src/test/java/org/apache/ignite/cache/ResetLostPartitionTest.java b/modules/core/src/test/java/org/apache/ignite/cache/ResetLostPartitionTest.java
index 0f5c72b..9a38920 100644
--- a/modules/core/src/test/java/org/apache/ignite/cache/ResetLostPartitionTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/cache/ResetLostPartitionTest.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
@@ -32,9 +32,7 @@ import org.apache.ignite.internal.processors.cache.distributed.dht.topology.Grid
 import org.apache.ignite.internal.processors.cache.distributed.dht.topology.GridDhtPartitionTopologyImpl;
 import org.apache.ignite.internal.util.typedef.internal.CU;
 import org.apache.ignite.internal.util.typedef.internal.U;
-import org.apache.ignite.testframework.MvccFeatureChecker;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
-import org.junit.Assume;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
diff --git a/modules/core/src/test/java/org/apache/ignite/failure/IoomFailureHandlerTest.java b/modules/core/src/test/java/org/apache/ignite/failure/IoomFailureHandlerTest.java
index f111da3..a177e25 100644
--- a/modules/core/src/test/java/org/apache/ignite/failure/IoomFailureHandlerTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/failure/IoomFailureHandlerTest.java
@@ -27,6 +27,7 @@ import org.apache.ignite.internal.IgniteEx;
 import org.apache.ignite.internal.mem.IgniteOutOfMemoryException;
 import org.apache.ignite.internal.util.typedef.X;
 import org.apache.ignite.transactions.Transaction;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -123,10 +124,9 @@ public class IoomFailureHandlerTest extends AbstractFailureHandlerTest {
     /**
      * Test IgniteOutOfMemoryException handling with PDS.
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-10185")
     @Test
     public void testIoomErrorMvccPdsHandling() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-10185");
-
         testIoomErrorHandling(true, true);
     }
 
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/authentication/AuthenticationProcessorNodeRestartTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/authentication/AuthenticationProcessorNodeRestartTest.java
index fd14734..74385d5 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/authentication/AuthenticationProcessorNodeRestartTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/authentication/AuthenticationProcessorNodeRestartTest.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
@@ -26,6 +26,7 @@ import org.apache.ignite.internal.IgniteInternalFuture;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.testframework.GridTestUtils;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -93,9 +94,8 @@ public class AuthenticationProcessorNodeRestartTest extends GridCommonAbstractTe
      * @throws Exception If failed.
      */
     @Test
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-7472")
     public void testConcurrentAddUpdateRemoveNodeRestartCoordinator() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-7472");
-
         final IgniteInternalFuture restartFut = restartCoordinator();
 
         AuthorizationContext.context(actxDflt);
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheEventWithTxLabelTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheEventWithTxLabelTest.java
index 5a9c2e9..62475d4 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheEventWithTxLabelTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheEventWithTxLabelTest.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheInterceptorPartitionCounterLocalSanityTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheInterceptorPartitionCounterLocalSanityTest.java
index 6adf6d9..a2c415f 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheInterceptorPartitionCounterLocalSanityTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheInterceptorPartitionCounterLocalSanityTest.java
@@ -46,6 +46,7 @@ import org.apache.ignite.transactions.TransactionConcurrency;
 import org.apache.ignite.transactions.TransactionIsolation;
 import org.eclipse.jetty.util.BlockingArrayQueue;
 import org.jetbrains.annotations.NotNull;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -148,10 +149,9 @@ public class CacheInterceptorPartitionCounterLocalSanityTest extends GridCommonA
     /**
      * @throws Exception If failed.
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9530")
     @Test
     public void testLocalMvccTx() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9530");
-
         CacheConfiguration<Object, Object> ccfg = cacheConfiguration(TRANSACTIONAL_SNAPSHOT,false);
 
         doTestPartitionCounterOperation(ccfg);
@@ -160,10 +160,9 @@ public class CacheInterceptorPartitionCounterLocalSanityTest extends GridCommonA
     /**
      * @throws Exception If failed.
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9530")
     @Test
     public void testLocalMvccTxWithStore() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9530");
-
         CacheConfiguration<Object, Object> ccfg = cacheConfiguration(TRANSACTIONAL_SNAPSHOT,true);
 
         doTestPartitionCounterOperation(ccfg);
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheInterceptorPartitionCounterRandomOperationsTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheInterceptorPartitionCounterRandomOperationsTest.java
index e613ee2..e50d6d2 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheInterceptorPartitionCounterRandomOperationsTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheInterceptorPartitionCounterRandomOperationsTest.java
@@ -53,6 +53,7 @@ import org.apache.ignite.transactions.TransactionConcurrency;
 import org.apache.ignite.transactions.TransactionIsolation;
 import org.eclipse.jetty.util.BlockingArrayQueue;
 import org.jetbrains.annotations.NotNull;
+import org.junit.Assume;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -409,8 +410,8 @@ public class CacheInterceptorPartitionCounterRandomOperationsTest extends GridCo
      */
     protected void doTestPartitionCounterOperation(CacheConfiguration<Object, Object> ccfg)
         throws Exception {
-        if (ccfg.getAtomicityMode() == TRANSACTIONAL_SNAPSHOT)
-            fail("https://issues.apache.org/jira/browse/IGNITE-9323");
+        Assume.assumeFalse("https://issues.apache.org/jira/browse/IGNITE-9323",
+            ccfg.getAtomicityMode() == TRANSACTIONAL_SNAPSHOT);
 
         ignite(0).createCache(ccfg);
 
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheMetricsManageTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheMetricsManageTest.java
index 2254bd6..fe390dc 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheMetricsManageTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheMetricsManageTest.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheRemoveAllSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheRemoveAllSelfTest.java
index b2b13da..191e064 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheRemoveAllSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheRemoveAllSelfTest.java
@@ -23,10 +23,11 @@ import org.apache.ignite.cache.CachePeekMode;
 import org.apache.ignite.internal.IgniteInternalFuture;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.testframework.GridTestUtils;
+import org.apache.ignite.testframework.MvccFeatureChecker;
+import org.junit.Assume;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
-import org.apache.ignite.testframework.MvccFeatureChecker;
 
 /**
  * Test remove all method.
@@ -35,8 +36,7 @@ import org.apache.ignite.testframework.MvccFeatureChecker;
 public class CacheRemoveAllSelfTest extends GridCacheAbstractSelfTest {
     /** {@inheritDoc} */
     @Override public void setUp() throws Exception {
-        if (MvccFeatureChecker.forcedMvcc())
-            fail("https://issues.apache.org/jira/browse/IGNITE-10082");
+        Assume.assumeFalse("https://issues.apache.org/jira/browse/IGNITE-10082", MvccFeatureChecker.forcedMvcc());
 
         super.setUp();
     }
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractIteratorsSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractIteratorsSelfTest.java
index 7a67e8e..6c21d24 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractIteratorsSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractIteratorsSelfTest.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
@@ -49,11 +49,9 @@ public abstract class GridCacheAbstractIteratorsSelfTest extends GridCacheAbstra
      */
     protected abstract int entryCount();
 
-    /**
-     * @throws Exception If failed.
-     */
+    /** */
     @Test
-    public void testCacheIterator() throws Exception {
+    public void testCacheIterator() {
         int cnt = 0;
 
         for (Cache.Entry<String, Integer> entry : jcache()) {
@@ -99,9 +97,7 @@ public abstract class GridCacheAbstractIteratorsSelfTest extends GridCacheAbstra
         }, 3, "iterator-thread");
     }
 
-    /**
-     * @throws Exception If failed.
-     */
+    /** */
     @Test
     public void testEntrySetIterator() throws Exception {
         Assume.assumeFalse("https://issues.apache.org/jira/browse/IGNITE-10082", MvccFeatureChecker.forcedMvcc());
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheClearAllSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheClearAllSelfTest.java
index 3608f51..c152e31 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheClearAllSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheClearAllSelfTest.java
@@ -26,6 +26,7 @@ import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.lang.IgnitePredicate;
 import org.apache.ignite.testframework.MvccFeatureChecker;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.junit.Assume;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -66,8 +67,7 @@ public class GridCacheClearAllSelfTest extends GridCommonAbstractTest {
 
     /** {@inheritDoc} */
     @Override protected void beforeTestsStarted() throws Exception {
-        if (MvccFeatureChecker.forcedMvcc())
-            fail("https://issues.apache.org/jira/browse/IGNITE-7952");
+        Assume.assumeFalse("https://issues.apache.org/jira/browse/IGNITE-7952", MvccFeatureChecker.forcedMvcc());
 
         super.beforeTestsStarted();
     }
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMixedPartitionExchangeSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMixedPartitionExchangeSelfTest.java
index 6bbd39c..2e198e0 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMixedPartitionExchangeSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMixedPartitionExchangeSelfTest.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMultinodeUpdateNearEnabledNoBackupsSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMultinodeUpdateNearEnabledNoBackupsSelfTest.java
index 3ed81b8..392e63e 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMultinodeUpdateNearEnabledNoBackupsSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMultinodeUpdateNearEnabledNoBackupsSelfTest.java
@@ -17,10 +17,11 @@
 package org.apache.ignite.internal.processors.cache;
 
 import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.testframework.MvccFeatureChecker;
+import org.junit.Assume;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
-import org.apache.ignite.testframework.MvccFeatureChecker;
 
 /**
  *
@@ -44,9 +45,8 @@ public class GridCacheMultinodeUpdateNearEnabledNoBackupsSelfTest extends GridCa
     /** {@inheritDoc} */
     @Test
     @Override public void testInvoke() throws Exception {
-        if (!MvccFeatureChecker.forcedMvcc())
-            fail("https://issues.apache.org/jira/browse/IGNITE-809");
-        else
-            super.testInvoke();
+        Assume.assumeTrue("https://issues.apache.org/jira/browse/IGNITE-809", MvccFeatureChecker.forcedMvcc());
+
+        super.testInvoke();
     }
 }
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMultinodeUpdateNearEnabledSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMultinodeUpdateNearEnabledSelfTest.java
index cd29a51..5aac5f5 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMultinodeUpdateNearEnabledSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMultinodeUpdateNearEnabledSelfTest.java
@@ -18,10 +18,11 @@ package org.apache.ignite.internal.processors.cache;
 
 import org.apache.ignite.cache.CacheAtomicityMode;
 import org.apache.ignite.configuration.NearCacheConfiguration;
+import org.apache.ignite.testframework.MvccFeatureChecker;
+import org.junit.Assume;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
-import org.apache.ignite.testframework.MvccFeatureChecker;
 
 import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL;
 
@@ -51,9 +52,8 @@ public class GridCacheMultinodeUpdateNearEnabledSelfTest extends GridCacheMultin
     /** {@inheritDoc} */
     @Test
     @Override public void testInvoke() throws Exception {
-        if (!MvccFeatureChecker.forcedMvcc())
-            fail("https://issues.apache.org/jira/browse/IGNITE-809");
-        else
-            super.testInvoke();
+        Assume.assumeTrue("https://issues.apache.org/jira/browse/IGNITE-809", MvccFeatureChecker.forcedMvcc());
+
+        super.testInvoke();
     }
 }
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMvccMultiThreadedUpdateSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMvccMultiThreadedUpdateSelfTest.java
index ec69f48..235b0dd 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMvccMultiThreadedUpdateSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMvccMultiThreadedUpdateSelfTest.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCachePartitionedGetSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCachePartitionedGetSelfTest.java
index 8a45837..a0d3f28 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCachePartitionedGetSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCachePartitionedGetSelfTest.java
@@ -30,6 +30,7 @@ import org.apache.ignite.internal.processors.cache.distributed.near.GridNearGetR
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearSingleGetRequest;
 import org.apache.ignite.testframework.MvccFeatureChecker;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.junit.Assume;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -116,8 +117,7 @@ public class GridCachePartitionedGetSelfTest extends GridCommonAbstractTest {
      */
     @Test
     public void testGetFromBackupNode() throws Exception {
-        if (MvccFeatureChecker.forcedMvcc())
-            fail("https://issues.apache.org/jira/browse/IGNITE-10274");
+        Assume.assumeFalse("https://issues.apache.org/jira/browse/IGNITE-10274", MvccFeatureChecker.forcedMvcc());
 
         MvccFeatureChecker.skipIfNotSupported(MvccFeatureChecker.Feature.EVICTION);
 
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheReturnValueTransferSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheReturnValueTransferSelfTest.java
index 4923d7a..ca93242 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheReturnValueTransferSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheReturnValueTransferSelfTest.java
@@ -31,6 +31,7 @@ import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -79,11 +80,10 @@ public class GridCacheReturnValueTransferSelfTest extends GridCommonAbstractTest
      * @throws Exception If failed.
      * TODO IGNITE-581 enable when fixed.
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-581")
     @Test
     public void testTransformTransactionalNoBackups() throws Exception {
         // Test works too long and fails.
-        fail("https://issues.apache.org/jira/browse/IGNITE-581");
-
         checkTransform(TRANSACTIONAL, 0);
     }
 
@@ -91,11 +91,10 @@ public class GridCacheReturnValueTransferSelfTest extends GridCommonAbstractTest
      * @throws Exception If failed.
      * TODO IGNITE-581 enable when fixed.
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-581")
     @Test
     public void testTransformTransactionalOneBackup() throws Exception {
         // Test works too long and fails.
-        fail("https://issues.apache.org/jira/browse/IGNITE-581");
-
         checkTransform(TRANSACTIONAL, 1);
     }
 
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheValueConsistencyAbstractSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheValueConsistencyAbstractSelfTest.java
index 8dde578..cc55db5 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheValueConsistencyAbstractSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheValueConsistencyAbstractSelfTest.java
@@ -26,6 +26,7 @@ import org.apache.ignite.cluster.ClusterNode;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.NearCacheConfiguration;
 import org.apache.ignite.testframework.MvccFeatureChecker;
+import org.junit.Assume;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -235,8 +236,7 @@ public abstract class GridCacheValueConsistencyAbstractSelfTest extends GridCach
      */
     @Test
     public void testPutConsistencyMultithreaded() throws Exception {
-        if (nearEnabled())
-            fail("https://issues.apache.org/jira/browse/IGNITE-627");
+        Assume.assumeFalse("https://issues.apache.org/jira/browse/IGNITE-627", nearEnabled());
 
         for (int i = 0; i < 20; i++) {
             log.info("Iteration: " + i);
@@ -289,8 +289,7 @@ public abstract class GridCacheValueConsistencyAbstractSelfTest extends GridCach
      */
     @Test
     public void testPutRemoveConsistencyMultithreaded() throws Exception {
-        if (nearEnabled())
-            fail("https://issues.apache.org/jira/browse/IGNITE-627");
+        Assume.assumeFalse("https://issues.apache.org/jira/browse/IGNITE-627", nearEnabled());
 
        for (int i = 0; i < 10; i++) {
            log.info("Iteration: " + i);
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheVariableTopologySelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheVariableTopologySelfTest.java
index d5b86b7..be59905 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheVariableTopologySelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheVariableTopologySelfTest.java
@@ -35,6 +35,7 @@ import org.apache.ignite.testframework.MvccFeatureChecker;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
 import org.apache.ignite.transactions.Transaction;
 import org.apache.ignite.transactions.TransactionRollbackException;
+import org.junit.Assume;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -52,8 +53,7 @@ public class GridCacheVariableTopologySelfTest extends GridCommonAbstractTest {
 
     /** {@inheritDoc} */
     @Override public void setUp() throws Exception {
-        if (MvccFeatureChecker.forcedMvcc())
-            fail("https://issues.apache.org/jira/browse/IGNITE-7388");
+        Assume.assumeFalse("https://issues.apache.org/jira/browse/IGNITE-7388", MvccFeatureChecker.forcedMvcc());
 
         super.setUp();
     }
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheGroupsTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheGroupsTest.java
index 78b1eea..f2b9739 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheGroupsTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheGroupsTest.java
@@ -357,10 +357,9 @@ public class IgniteCacheGroupsTest extends GridCommonAbstractTest {
     /**
      * @throws Exception If failed.
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9530")
     @Test
     public void testScanQueryMvccTxLocal() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9530");
-
         scanQuery(LOCAL, TRANSACTIONAL_SNAPSHOT);
     }
 
@@ -383,10 +382,9 @@ public class IgniteCacheGroupsTest extends GridCommonAbstractTest {
     /**
      * @throws Exception If failed.
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-7311")
     @Test
     public void testEntriesTtlMvccTxPartitioned() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-7311");
-
         entriesTtl(PARTITIONED, TRANSACTIONAL_SNAPSHOT);
     }
 
@@ -409,10 +407,9 @@ public class IgniteCacheGroupsTest extends GridCommonAbstractTest {
     /**
      * @throws Exception If failed.
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-7311")
     @Test
     public void testEntriesTtlMvccTxReplicated() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-7311");
-
         entriesTtl(REPLICATED, TRANSACTIONAL_SNAPSHOT);
     }
 
@@ -435,11 +432,9 @@ public class IgniteCacheGroupsTest extends GridCommonAbstractTest {
     /**
      * @throws Exception If failed.
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9530,https://issues.apache.org/jira/browse/IGNITE-7311")
     @Test
     public void testEntriesTtlMvccTxLocal() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9530");
-        fail("https://issues.apache.org/jira/browse/IGNITE-7311");
-
         entriesTtl(LOCAL, TRANSACTIONAL_SNAPSHOT);
     }
 
@@ -510,10 +505,9 @@ public class IgniteCacheGroupsTest extends GridCommonAbstractTest {
     /**
      * @throws Exception If failed.
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9530")
     @Test
     public void testCacheIteratorMvccTxLocal() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9530");
-
         cacheIterator(LOCAL, TRANSACTIONAL_SNAPSHOT);
     }
 
@@ -608,10 +602,9 @@ public class IgniteCacheGroupsTest extends GridCommonAbstractTest {
     /**
      * @throws Exception If failed.
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9530")
     @Test
     public void testContinuousQueryMvccTxLocal() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9530");
-
         continuousQuery(LOCAL, TRANSACTIONAL_SNAPSHOT);
     }
 
@@ -2049,10 +2042,9 @@ public class IgniteCacheGroupsTest extends GridCommonAbstractTest {
     /**
      * @throws Exception If failed.
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-7952")
     @Test
     public void testCacheApiMvccTxPartitioned() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-7952");
-
         cacheApiTest(PARTITIONED, TRANSACTIONAL_SNAPSHOT);
     }
 
@@ -2067,10 +2059,9 @@ public class IgniteCacheGroupsTest extends GridCommonAbstractTest {
     /**
      * @throws Exception If failed.
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-7952")
     @Test
     public void testCacheApiMvccTxReplicated() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-7952");
-
         cacheApiTest(REPLICATED, TRANSACTIONAL_SNAPSHOT);
     }
 
@@ -2902,10 +2893,9 @@ public class IgniteCacheGroupsTest extends GridCommonAbstractTest {
     /**
      * @throws Exception If failed.
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-7954")
     @Test
     public void testLoadCacheMvccTxPartitioned() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-7954");
-
         loadCache(PARTITIONED, TRANSACTIONAL_SNAPSHOT);
     }
 
@@ -2920,10 +2910,9 @@ public class IgniteCacheGroupsTest extends GridCommonAbstractTest {
     /**
      * @throws Exception If failed.
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-7954")
     @Test
     public void testLoadCacheMvccTxReplicated() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-7954");
-
         loadCache(REPLICATED, TRANSACTIONAL_SNAPSHOT);
     }
 
@@ -2946,10 +2935,9 @@ public class IgniteCacheGroupsTest extends GridCommonAbstractTest {
     /**
      * @throws Exception If failed.
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9530")
     @Test
     public void testLoadCacheMvccTxLocal() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9530");
-
         loadCache(LOCAL, TRANSACTIONAL_SNAPSHOT);
     }
 
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheInvokeReadThroughSingleNodeTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheInvokeReadThroughSingleNodeTest.java
index 743b158..e286422 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheInvokeReadThroughSingleNodeTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheInvokeReadThroughSingleNodeTest.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheInvokeReadThroughTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheInvokeReadThroughTest.java
index 171a374..ad0db6b 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheInvokeReadThroughTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheInvokeReadThroughTest.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteClusterActivateDeactivateTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteClusterActivateDeactivateTest.java
index 5739a79..a5debd3 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteClusterActivateDeactivateTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteClusterActivateDeactivateTest.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteClusterActivateDeactivateTestWithPersistence.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteClusterActivateDeactivateTestWithPersistence.java
index f6a5b58..43f7493 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteClusterActivateDeactivateTestWithPersistence.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteClusterActivateDeactivateTestWithPersistence.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteClusterActivateDeactivateTestWithPersistenceAndMemoryReuse.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteClusterActivateDeactivateTestWithPersistenceAndMemoryReuse.java
index 9eb330c..509a4d8 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteClusterActivateDeactivateTestWithPersistenceAndMemoryReuse.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteClusterActivateDeactivateTestWithPersistenceAndMemoryReuse.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteDynamicCacheStartFailWithPersistenceTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteDynamicCacheStartFailWithPersistenceTest.java
index 9af4c4e..c7dbb1e 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteDynamicCacheStartFailWithPersistenceTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteDynamicCacheStartFailWithPersistenceTest.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteMvccTxSingleThreadedAbstractTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteMvccTxSingleThreadedAbstractTest.java
index 8fb64ae..5ae3338 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteMvccTxSingleThreadedAbstractTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteMvccTxSingleThreadedAbstractTest.java
@@ -17,6 +17,7 @@
 package org.apache.ignite.internal.processors.cache;
 
 import org.apache.ignite.IgniteCheckedException;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -32,10 +33,9 @@ public abstract class IgniteMvccTxSingleThreadedAbstractTest extends IgniteTxAbs
     /**
      * @throws IgniteCheckedException If test failed.
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-10261")
     @Test
     public void testPessimisticRepeatableReadCommit() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-10261");
-
         checkCommit(PESSIMISTIC, REPEATABLE_READ);
 
         finalChecks();
@@ -44,10 +44,9 @@ public abstract class IgniteMvccTxSingleThreadedAbstractTest extends IgniteTxAbs
     /**
      * @throws IgniteCheckedException If test failed.
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-10261")
     @Test
     public void testPessimisticRepeatableReadRollback() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-10261");
-
         checkRollback(PESSIMISTIC, REPEATABLE_READ);
 
         finalChecks();
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgnitePdsDataRegionMetricsTxTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgnitePdsDataRegionMetricsTxTest.java
index e469623..faf8fa7 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgnitePdsDataRegionMetricsTxTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgnitePdsDataRegionMetricsTxTest.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteTopologyValidatorGridSplitCacheTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteTopologyValidatorGridSplitCacheTest.java
index eb158e1..e0bec5e 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteTopologyValidatorGridSplitCacheTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteTopologyValidatorGridSplitCacheTest.java
@@ -42,6 +42,7 @@ import org.apache.ignite.resources.LoggerResource;
 import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
 import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
 import org.apache.ignite.testframework.MvccFeatureChecker;
+import org.junit.Assume;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -201,8 +202,7 @@ public class IgniteTopologyValidatorGridSplitCacheTest extends IgniteCacheTopolo
 
     /** {@inheritDoc} */
     @Override protected void beforeTest() throws Exception {
-        if (MvccFeatureChecker.forcedMvcc())
-            fail("https://issues.apache.org/jira/browse/IGNITE-7952");
+        Assume.assumeFalse("https://issues.apache.org/jira/browse/IGNITE-7952", MvccFeatureChecker.forcedMvcc());
 
         super.beforeTest();
 
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteTxExceptionAbstractSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteTxExceptionAbstractSelfTest.java
index 47e1406..41e9b66 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteTxExceptionAbstractSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteTxExceptionAbstractSelfTest.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/binary/GridCacheBinaryObjectsAbstractSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/binary/GridCacheBinaryObjectsAbstractSelfTest.java
index e4bf32f..98ba369 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/binary/GridCacheBinaryObjectsAbstractSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/binary/GridCacheBinaryObjectsAbstractSelfTest.java
@@ -73,6 +73,7 @@ import org.apache.ignite.transactions.Transaction;
 import org.apache.ignite.transactions.TransactionConcurrency;
 import org.apache.ignite.transactions.TransactionIsolation;
 import org.jetbrains.annotations.Nullable;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -585,10 +586,9 @@ public abstract class GridCacheBinaryObjectsAbstractSelfTest extends GridCommonA
     /**
      * @throws Exception If failed.
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-3244")
     @Test
     public void testCustomArrays() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-3244");
-
         IgniteCache<Integer, TestObject[]> cache = jcache(0);
 
         for (int i = 0; i < ENTRY_CNT; i++) {
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/datastructures/partitioned/GridCachePartitionedAtomicSetFailoverSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/datastructures/partitioned/GridCachePartitionedAtomicSetFailoverSelfTest.java
index 6296472..b17f778 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/datastructures/partitioned/GridCachePartitionedAtomicSetFailoverSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/datastructures/partitioned/GridCachePartitionedAtomicSetFailoverSelfTest.java
@@ -18,6 +18,7 @@ package org.apache.ignite.internal.processors.cache.datastructures.partitioned;
 
 import org.apache.ignite.cache.CacheAtomicityMode;
 import org.apache.ignite.internal.processors.cache.datastructures.GridCacheSetFailoverAbstractSelfTest;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -35,8 +36,9 @@ public class GridCachePartitionedAtomicSetFailoverSelfTest extends GridCacheSetF
     }
 
     /** {@inheritDoc} */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-170")
     @Test
     @Override public void testNodeRestart() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-170");
+        // No-op
     }
 }
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/datastructures/partitioned/GridCachePartitionedSetFailoverSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/datastructures/partitioned/GridCachePartitionedSetFailoverSelfTest.java
index 402447d..4697ce5 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/datastructures/partitioned/GridCachePartitionedSetFailoverSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/datastructures/partitioned/GridCachePartitionedSetFailoverSelfTest.java
@@ -18,6 +18,7 @@ package org.apache.ignite.internal.processors.cache.datastructures.partitioned;
 
 import org.apache.ignite.cache.CacheAtomicityMode;
 import org.apache.ignite.internal.processors.cache.datastructures.GridCacheSetFailoverAbstractSelfTest;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -34,8 +35,9 @@ public class GridCachePartitionedSetFailoverSelfTest extends GridCacheSetFailove
         return TRANSACTIONAL;
     }
 
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-1593")
     @Test
     @Override public void testNodeRestart(){
-        fail("https://issues.apache.org/jira/browse/IGNITE-1593");
+        // No-op
     }
 }
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheBlockOnGetAllTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheBlockOnGetAllTest.java
index 2d2e85b..dc945cf 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheBlockOnGetAllTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheBlockOnGetAllTest.java
@@ -20,6 +20,7 @@ import java.util.HashSet;
 import java.util.Random;
 import java.util.Set;
 import org.jetbrains.annotations.NotNull;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -55,225 +56,257 @@ public class CacheBlockOnGetAllTest extends CacheBlockOnReadAbstractTest {
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = ATOMIC, cacheMode = PARTITIONED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9915")
     @Test
     @Override public void testStopBaselineAtomicPartitioned() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9915");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = ATOMIC, cacheMode = REPLICATED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9915")
     @Test
     @Override public void testStopBaselineAtomicReplicated() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9915");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = TRANSACTIONAL, cacheMode = PARTITIONED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9915")
     @Test
     @Override public void testStopBaselineTransactionalPartitioned() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9915");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = TRANSACTIONAL, cacheMode = REPLICATED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9915")
     @Test
     @Override public void testStopBaselineTransactionalReplicated() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9915");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = ATOMIC, cacheMode = PARTITIONED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9883")
     @Test
     @Override public void testCreateCacheAtomicPartitioned() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9883");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = ATOMIC, cacheMode = REPLICATED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9883")
     @Test
     @Override public void testCreateCacheAtomicReplicated() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9883");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = TRANSACTIONAL, cacheMode = PARTITIONED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9883")
     @Test
     @Override public void testCreateCacheTransactionalPartitioned() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9883");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = TRANSACTIONAL, cacheMode = REPLICATED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9883")
     @Test
     @Override public void testCreateCacheTransactionalReplicated() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9883");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = ATOMIC, cacheMode = PARTITIONED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9883")
     @Test
     @Override public void testDestroyCacheAtomicPartitioned() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9883");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = ATOMIC, cacheMode = REPLICATED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9883")
     @Test
     @Override public void testDestroyCacheAtomicReplicated() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9883");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = TRANSACTIONAL, cacheMode = PARTITIONED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9883")
     @Test
     @Override public void testDestroyCacheTransactionalPartitioned() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9883");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = TRANSACTIONAL, cacheMode = REPLICATED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9883")
     @Test
     @Override public void testDestroyCacheTransactionalReplicated() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9883");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = ATOMIC, cacheMode = PARTITIONED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9883")
     @Test
     @Override public void testStartServerAtomicPartitioned() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9883");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = ATOMIC, cacheMode = REPLICATED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9883")
     @Test
     @Override public void testStartServerAtomicReplicated() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9883");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = TRANSACTIONAL, cacheMode = PARTITIONED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9883")
     @Test
     @Override public void testStartServerTransactionalPartitioned() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9883");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = TRANSACTIONAL, cacheMode = REPLICATED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9883")
     @Test
     @Override public void testStartServerTransactionalReplicated() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9883");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = ATOMIC, cacheMode = PARTITIONED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9883")
     @Test
     @Override public void testStopServerAtomicPartitioned() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9883");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = ATOMIC, cacheMode = REPLICATED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9883")
     @Test
     @Override public void testStopServerAtomicReplicated() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9883");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = TRANSACTIONAL, cacheMode = PARTITIONED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9883")
     @Test
     @Override public void testStopServerTransactionalPartitioned() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9883");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = TRANSACTIONAL, cacheMode = REPLICATED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9883")
     @Test
     @Override public void testStopServerTransactionalReplicated() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9883");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = ATOMIC, cacheMode = PARTITIONED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9883")
     @Test
     @Override public void testUpdateBaselineTopologyAtomicPartitioned() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9883");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = ATOMIC, cacheMode = REPLICATED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9883")
     @Test
     @Override public void testUpdateBaselineTopologyAtomicReplicated() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9883");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = TRANSACTIONAL, cacheMode = PARTITIONED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9883")
     @Test
     @Override public void testUpdateBaselineTopologyTransactionalPartitioned() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9883");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = TRANSACTIONAL, cacheMode = REPLICATED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9883")
     @Test
     @Override public void testUpdateBaselineTopologyTransactionalReplicated() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9883");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = ATOMIC, cacheMode = PARTITIONED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9987")
     @Test
     @Override public void testStartClientAtomicPartitioned() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9987");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = ATOMIC, cacheMode = REPLICATED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9987")
     @Test
     @Override public void testStartClientAtomicReplicated() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9987");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = TRANSACTIONAL, cacheMode = PARTITIONED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9987")
     @Test
     @Override public void testStartClientTransactionalPartitioned() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9987");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = TRANSACTIONAL, cacheMode = REPLICATED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9987")
     @Test
     @Override public void testStartClientTransactionalReplicated() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9987");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = ATOMIC, cacheMode = PARTITIONED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9987")
     @Test
     @Override public void testStopClientAtomicPartitioned() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9987");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = ATOMIC, cacheMode = REPLICATED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9987")
     @Test
     @Override public void testStopClientAtomicReplicated() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9987");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = TRANSACTIONAL, cacheMode = PARTITIONED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9987")
     @Test
     @Override public void testStopClientTransactionalPartitioned() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9987");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = TRANSACTIONAL, cacheMode = REPLICATED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9987")
     @Test
     @Override public void testStopClientTransactionalReplicated() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9987");
+        // No-op
     }
 }
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheBlockOnScanTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheBlockOnScanTest.java
index 6991138..4ed4187 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheBlockOnScanTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheBlockOnScanTest.java
@@ -20,6 +20,7 @@ import java.util.Objects;
 import java.util.Random;
 import org.apache.ignite.cache.query.ScanQuery;
 import org.jetbrains.annotations.NotNull;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -80,30 +81,34 @@ public class CacheBlockOnScanTest extends CacheBlockOnReadAbstractTest {
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = ATOMIC, cacheMode = REPLICATED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9987")
     @Test
     @Override public void testStartClientAtomicReplicated() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9987");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = TRANSACTIONAL, cacheMode = REPLICATED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9987")
     @Test
     @Override public void testStartClientTransactionalReplicated() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9987");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = ATOMIC, cacheMode = REPLICATED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9987")
     @Test
     @Override public void testStopClientAtomicReplicated() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9987");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = TRANSACTIONAL, cacheMode = REPLICATED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9987")
     @Test
     @Override public void testStopClientTransactionalReplicated() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9987");
+        // No-op
     }
 
     /** {@inheritDoc} */
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheBlockOnSingleGetTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheBlockOnSingleGetTest.java
index 27ae6c0..f96bce1 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheBlockOnSingleGetTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheBlockOnSingleGetTest.java
@@ -18,6 +18,7 @@ package org.apache.ignite.internal.processors.cache.distributed;
 
 import java.util.Random;
 import org.jetbrains.annotations.NotNull;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -49,225 +50,257 @@ public class CacheBlockOnSingleGetTest extends CacheBlockOnReadAbstractTest {
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = ATOMIC, cacheMode = PARTITIONED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9915")
     @Test
     @Override public void testStopBaselineAtomicPartitioned() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9915");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = ATOMIC, cacheMode = REPLICATED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9915")
     @Test
     @Override public void testStopBaselineAtomicReplicated() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9915");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = TRANSACTIONAL, cacheMode = PARTITIONED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9915")
     @Test
     @Override public void testStopBaselineTransactionalPartitioned() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9915");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = TRANSACTIONAL, cacheMode = REPLICATED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9915")
     @Test
     @Override public void testStopBaselineTransactionalReplicated() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9915");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = ATOMIC, cacheMode = PARTITIONED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9883")
     @Test
     @Override public void testCreateCacheAtomicPartitioned() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9883");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = ATOMIC, cacheMode = REPLICATED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9883")
     @Test
     @Override public void testCreateCacheAtomicReplicated() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9883");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = TRANSACTIONAL, cacheMode = PARTITIONED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9883")
     @Test
     @Override public void testCreateCacheTransactionalPartitioned() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9883");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = TRANSACTIONAL, cacheMode = REPLICATED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9883")
     @Test
     @Override public void testCreateCacheTransactionalReplicated() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9883");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = ATOMIC, cacheMode = PARTITIONED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9883")
     @Test
     @Override public void testDestroyCacheAtomicPartitioned() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9883");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = ATOMIC, cacheMode = REPLICATED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9883")
     @Test
     @Override public void testDestroyCacheAtomicReplicated() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9883");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = TRANSACTIONAL, cacheMode = PARTITIONED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9883")
     @Test
     @Override public void testDestroyCacheTransactionalPartitioned() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9883");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = TRANSACTIONAL, cacheMode = REPLICATED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9883")
     @Test
     @Override public void testDestroyCacheTransactionalReplicated() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9883");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = ATOMIC, cacheMode = PARTITIONED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9883")
     @Test
     @Override public void testStartServerAtomicPartitioned() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9883");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = ATOMIC, cacheMode = REPLICATED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9883")
     @Test
     @Override public void testStartServerAtomicReplicated() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9883");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = TRANSACTIONAL, cacheMode = PARTITIONED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9883")
     @Test
     @Override public void testStartServerTransactionalPartitioned() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9883");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = TRANSACTIONAL, cacheMode = REPLICATED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9883")
     @Test
     @Override public void testStartServerTransactionalReplicated() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9883");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = ATOMIC, cacheMode = PARTITIONED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9883")
     @Test
     @Override public void testStopServerAtomicPartitioned() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9883");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = ATOMIC, cacheMode = REPLICATED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9883")
     @Test
     @Override public void testStopServerAtomicReplicated() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9883");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = TRANSACTIONAL, cacheMode = PARTITIONED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9883")
     @Test
     @Override public void testStopServerTransactionalPartitioned() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9883");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = TRANSACTIONAL, cacheMode = REPLICATED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9883")
     @Test
     @Override public void testStopServerTransactionalReplicated() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9883");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = ATOMIC, cacheMode = PARTITIONED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9883")
     @Test
     @Override public void testUpdateBaselineTopologyAtomicPartitioned() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9883");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = ATOMIC, cacheMode = REPLICATED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9883")
     @Test
     @Override public void testUpdateBaselineTopologyAtomicReplicated() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9883");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = TRANSACTIONAL, cacheMode = PARTITIONED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9883")
     @Test
     @Override public void testUpdateBaselineTopologyTransactionalPartitioned() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9883");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = TRANSACTIONAL, cacheMode = REPLICATED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9883")
     @Test
     @Override public void testUpdateBaselineTopologyTransactionalReplicated() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9883");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = ATOMIC, cacheMode = PARTITIONED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9987")
     @Test
     @Override public void testStartClientAtomicPartitioned() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9987");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = ATOMIC, cacheMode = REPLICATED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9987")
     @Test
     @Override public void testStartClientAtomicReplicated() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9987");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = TRANSACTIONAL, cacheMode = PARTITIONED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9987")
     @Test
     @Override public void testStartClientTransactionalPartitioned() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9987");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = TRANSACTIONAL, cacheMode = REPLICATED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9987")
     @Test
     @Override public void testStartClientTransactionalReplicated() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9987");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = ATOMIC, cacheMode = PARTITIONED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9987")
     @Test
     @Override public void testStopClientAtomicPartitioned() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9987");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = ATOMIC, cacheMode = REPLICATED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9987")
     @Test
     @Override public void testStopClientAtomicReplicated() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9987");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = TRANSACTIONAL, cacheMode = PARTITIONED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9987")
     @Test
     @Override public void testStopClientTransactionalPartitioned() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9987");
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Params(baseline = 1, atomicityMode = TRANSACTIONAL, cacheMode = REPLICATED)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9987")
     @Test
     @Override public void testStopClientTransactionalReplicated() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9987");
+        // No-op
     }
 }
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheDataLossOnPartitionMoveTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheDataLossOnPartitionMoveTest.java
index 41ea6a9..1ecf317 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheDataLossOnPartitionMoveTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheDataLossOnPartitionMoveTest.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheGetInsideLockChangingTopologyTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheGetInsideLockChangingTopologyTest.java
index 8de2cf6..ca5f2dc 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheGetInsideLockChangingTopologyTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheGetInsideLockChangingTopologyTest.java
@@ -27,7 +27,6 @@ import javax.cache.CacheException;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.IgniteException;
-import org.apache.ignite.IgniteSystemProperties;
 import org.apache.ignite.cache.CacheAtomicityMode;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
@@ -40,6 +39,7 @@ import org.apache.ignite.testframework.GridTestUtils;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
 import org.apache.ignite.transactions.Transaction;
 import org.apache.ignite.transactions.TransactionConcurrency;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -363,10 +363,9 @@ public class CacheGetInsideLockChangingTopologyTest extends GridCommonAbstractTe
     /**
      * @throws Exception If failed.
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-2204")
     @Test
     public void testMultithreaded() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-2204");
-
         final AtomicBoolean finished = new AtomicBoolean();
 
         final int NEW_NODE = SRVS + CLIENTS;
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheLateAffinityAssignmentTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheLateAffinityAssignmentTest.java
index 80d4a39..9f6d7b6 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheLateAffinityAssignmentTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheLateAffinityAssignmentTest.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheLoadingConcurrentGridStartSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheLoadingConcurrentGridStartSelfTest.java
index bdf013a..ea7ebd7 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheLoadingConcurrentGridStartSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheLoadingConcurrentGridStartSelfTest.java
@@ -51,6 +51,7 @@ import org.apache.ignite.testframework.GridTestUtils;
 import org.apache.ignite.testframework.MvccFeatureChecker;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
 import org.jetbrains.annotations.Nullable;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -173,10 +174,9 @@ public class CacheLoadingConcurrentGridStartSelfTest extends GridCommonAbstractT
     /**
      * @throws Exception if failed
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-4210")
     @Test
     public void testLoadCacheFromStore() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-4210");
-
         loadCache(new IgniteInClosure<Ignite>() {
             @Override public void apply(Ignite grid) {
                 grid.cache(DEFAULT_CACHE_NAME).loadCache(null);
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/GridCacheBasicOpAbstractTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/GridCacheBasicOpAbstractTest.java
index c2d7332..d720e51 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/GridCacheBasicOpAbstractTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/GridCacheBasicOpAbstractTest.java
@@ -30,6 +30,7 @@ import org.apache.ignite.lang.IgnitePredicate;
 import org.apache.ignite.testframework.MvccFeatureChecker;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
 import org.apache.ignite.transactions.Transaction;
+import org.junit.Assume;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -75,8 +76,7 @@ public abstract class GridCacheBasicOpAbstractTest extends GridCommonAbstractTes
     @Override protected void beforeTest() throws Exception {
         MvccFeatureChecker.skipIfNotSupported(MvccFeatureChecker.Feature.CACHE_EVENTS);
 
-        if (MvccFeatureChecker.forcedMvcc())
-            fail("https://issues.apache.org/jira/browse/IGNITE-7952");
+        Assume.assumeFalse("https://issues.apache.org/jira/browse/IGNITE-7952", MvccFeatureChecker.forcedMvcc());
 
         for (Ignite g : G.allGrids())
             g.cache(DEFAULT_CACHE_NAME).clear();
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/GridCachePartitionNotLoadedEventSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/GridCachePartitionNotLoadedEventSelfTest.java
index fc2f1ff..c70494f 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/GridCachePartitionNotLoadedEventSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/GridCachePartitionNotLoadedEventSelfTest.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
@@ -34,8 +34,8 @@ import org.apache.ignite.internal.processors.cache.distributed.dht.preloader.Gri
 import org.apache.ignite.internal.util.lang.GridAbsPredicate;
 import org.apache.ignite.lang.IgnitePredicate;
 import org.apache.ignite.testframework.GridTestUtils;
-import org.apache.ignite.testframework.MvccFeatureChecker;
 import org.apache.ignite.testframework.GridTestUtils.SF;
+import org.apache.ignite.testframework.MvccFeatureChecker;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
 import org.apache.ignite.util.TestTcpCommunicationSpi;
 import org.eclipse.jetty.util.ConcurrentHashSet;
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/GridCachePreloadRestartAbstractSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/GridCachePreloadRestartAbstractSelfTest.java
index 31ded1c..55b038a 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/GridCachePreloadRestartAbstractSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/GridCachePreloadRestartAbstractSelfTest.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/GridCacheTransformEventSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/GridCacheTransformEventSelfTest.java
index 3a5b3a6..9dc548d 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/GridCacheTransformEventSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/GridCacheTransformEventSelfTest.java
@@ -42,6 +42,7 @@ import org.apache.ignite.resources.IgniteInstanceResource;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
 import org.apache.ignite.transactions.TransactionConcurrency;
 import org.apache.ignite.transactions.TransactionIsolation;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -331,10 +332,9 @@ public class GridCacheTransformEventSelfTest extends GridCommonAbstractTest {
      *
      * @throws Exception If failed.
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9530")
     @Test
     public void testMvccTxLocalPessimisticRepeatableRead() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9530");
-
         checkMvccTx(LOCAL, PESSIMISTIC, REPEATABLE_READ);
     }
 
@@ -403,10 +403,9 @@ public class GridCacheTransformEventSelfTest extends GridCommonAbstractTest {
      *
      * @throws Exception If failed.
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9321")
     @Test
     public void testMvccTxPartitionedPessimisticRepeatableRead() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9321");
-
         checkMvccTx(PARTITIONED, PESSIMISTIC, REPEATABLE_READ);
     }
 
@@ -476,10 +475,9 @@ public class GridCacheTransformEventSelfTest extends GridCommonAbstractTest {
      *
      * @throws Exception If failed.
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9321")
     @Test
     public void testMvccTxReplicatedPessimisticRepeatableRead() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9321");
-
         checkMvccTx(REPLICATED, PESSIMISTIC, REPEATABLE_READ);
     }
 
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/IgniteCacheGroupsPartitionLossPolicySelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/IgniteCacheGroupsPartitionLossPolicySelfTest.java
index 5a82eca..14aa72b 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/IgniteCacheGroupsPartitionLossPolicySelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/IgniteCacheGroupsPartitionLossPolicySelfTest.java
@@ -37,6 +37,7 @@ import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.G;
 import org.apache.ignite.internal.util.typedef.P1;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -135,10 +136,9 @@ public class IgniteCacheGroupsPartitionLossPolicySelfTest extends GridCommonAbst
     /**
      * @throws Exception if failed.
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-5078")
     @Test
     public void testIgnore() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-5078");
-
         prepareTopology();
 
         String cacheName = ThreadLocalRandom.current().nextBoolean() ? CACHE_1 : CACHE_2;
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/IgniteMvccTxTimeoutAbstractTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/IgniteMvccTxTimeoutAbstractTest.java
index 40475bd..6fd0e3c 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/IgniteMvccTxTimeoutAbstractTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/IgniteMvccTxTimeoutAbstractTest.java
@@ -27,6 +27,7 @@ import org.apache.ignite.transactions.Transaction;
 import org.apache.ignite.transactions.TransactionConcurrency;
 import org.apache.ignite.transactions.TransactionIsolation;
 import org.apache.ignite.transactions.TransactionTimeoutException;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -38,6 +39,7 @@ import static org.apache.ignite.transactions.TransactionIsolation.REPEATABLE_REA
  * Simple cache test.
  */
 @RunWith(JUnit4.class)
+@Ignore("https://issues.apache.org/jira/browse/IGNITE-7388")
 public class IgniteMvccTxTimeoutAbstractTest extends GridCommonAbstractTest {
     /** Random number generator. */
     private static final Random RAND = new Random();
@@ -52,8 +54,6 @@ public class IgniteMvccTxTimeoutAbstractTest extends GridCommonAbstractTest {
      * @throws Exception If failed.
      */
     @Override protected void beforeTestsStarted() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-7388");
-
         startGridsMultiThreaded(GRID_COUNT, true);
     }
 
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/IgniteTxCacheWriteSynchronizationModesMultithreadedTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/IgniteTxCacheWriteSynchronizationModesMultithreadedTest.java
index a3bfc70..480076b 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/IgniteTxCacheWriteSynchronizationModesMultithreadedTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/IgniteTxCacheWriteSynchronizationModesMultithreadedTest.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/IgniteTxRemoveTimeoutObjectsTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/IgniteTxRemoveTimeoutObjectsTest.java
index f5334a2..928047f 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/IgniteTxRemoveTimeoutObjectsTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/IgniteTxRemoveTimeoutObjectsTest.java
@@ -34,6 +34,7 @@ import org.apache.ignite.testframework.GridTestUtils;
 import org.apache.ignite.testframework.MvccFeatureChecker;
 import org.apache.ignite.transactions.Transaction;
 import org.apache.ignite.transactions.TransactionTimeoutException;
+import org.junit.Assume;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -61,8 +62,7 @@ public class IgniteTxRemoveTimeoutObjectsTest extends GridCacheAbstractSelfTest
 
     /** {@inheritDoc} */
     @Override public void setUp() throws Exception {
-        if (MvccFeatureChecker.forcedMvcc())
-            fail("https://issues.apache.org/jira/browse/IGNITE-7388");
+        Assume.assumeFalse("https://issues.apache.org/jira/browse/IGNITE-7388", MvccFeatureChecker.forcedMvcc());
 
         if (nearEnabled())
             MvccFeatureChecker.skipIfNotSupported(MvccFeatureChecker.Feature.NEAR_CACHE);
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridCacheDhtPreloadPutGetSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridCacheDhtPreloadPutGetSelfTest.java
index 2f7c578..e72e83a 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridCacheDhtPreloadPutGetSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridCacheDhtPreloadPutGetSelfTest.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridCachePartitionedNearDisabledLockSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridCachePartitionedNearDisabledLockSelfTest.java
index 91444ab..a33dde0 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridCachePartitionedNearDisabledLockSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridCachePartitionedNearDisabledLockSelfTest.java
@@ -18,6 +18,7 @@ package org.apache.ignite.internal.processors.cache.distributed.dht;
 
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridCachePartitionedLockSelfTest;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -44,8 +45,9 @@ public class GridCachePartitionedNearDisabledLockSelfTest extends GridCacheParti
     }
 
     /** {@inheritDoc} */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-835")
     @Test
     @Override public void testLockReentrancy() throws Throwable {
-        fail("https://issues.apache.org/jira/browse/IGNITE-835");
+        // No-op
     }
 }
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridCachePartitionedNearDisabledMetricsSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridCachePartitionedNearDisabledMetricsSelfTest.java
index c329e13..def8422 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridCachePartitionedNearDisabledMetricsSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridCachePartitionedNearDisabledMetricsSelfTest.java
@@ -22,6 +22,7 @@ import org.apache.ignite.cache.CacheMetrics;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.internal.processors.cache.GridCacheAbstractSelfTest;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -80,10 +81,9 @@ public class GridCachePartitionedNearDisabledMetricsSelfTest extends GridCacheAb
     /**
      * @throws Exception If failed.
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-819")
     @Test
     public void testGettingRemovedKey() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-819");
-
         IgniteCache<Integer, Integer> cache = grid(0).cache(DEFAULT_CACHE_NAME);
 
         cache.put(0, 0);
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridCachePartitionsStateValidationTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridCachePartitionsStateValidationTest.java
index 80d8a60..d11e52d 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridCachePartitionsStateValidationTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridCachePartitionsStateValidationTest.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridCacheTxNodeFailureSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridCacheTxNodeFailureSelfTest.java
index 745b4ce..069351c 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridCacheTxNodeFailureSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridCacheTxNodeFailureSelfTest.java
@@ -44,6 +44,7 @@ import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
 import org.apache.ignite.transactions.Transaction;
 import org.apache.ignite.transactions.TransactionConcurrency;
 import org.apache.ignite.transactions.TransactionRollbackException;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -141,10 +142,9 @@ public class GridCacheTxNodeFailureSelfTest extends GridCommonAbstractTest {
     /**
      * @throws Exception If failed.
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-1731")
     @Test
     public void testPrimaryNodeFailureBackupRollbackOptimistic() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-1731");
-
         checkPrimaryNodeFailureBackupCommit(OPTIMISTIC, false, false);
     }
 
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/IgniteAtomicLongChangingTopologySelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/IgniteAtomicLongChangingTopologySelfTest.java
index 003f188..28a1d1a 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/IgniteAtomicLongChangingTopologySelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/IgniteAtomicLongChangingTopologySelfTest.java
@@ -43,6 +43,7 @@ import org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi;
 import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
 import org.apache.ignite.testframework.GridTestUtils;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -169,10 +170,9 @@ public class IgniteAtomicLongChangingTopologySelfTest extends GridCommonAbstract
     /**
      * @throws Exception If failed.
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9015")
     @Test
     public void testClientSetCreateCloseFailover() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9015");
-
         checkClientSetCreateCloseFailover(false);
     }
 
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/IgniteCacheClearDuringRebalanceTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/IgniteCacheClearDuringRebalanceTest.java
index 269274c..56731db 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/IgniteCacheClearDuringRebalanceTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/IgniteCacheClearDuringRebalanceTest.java
@@ -26,6 +26,7 @@ import org.apache.ignite.internal.IgniteEx;
 import org.apache.ignite.testframework.GridTestUtils;
 import org.apache.ignite.testframework.MvccFeatureChecker;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.junit.Assume;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -42,8 +43,7 @@ public class IgniteCacheClearDuringRebalanceTest extends GridCommonAbstractTest
 
     /** {@inheritDoc} */
     @Override protected void beforeTest() throws Exception {
-        if(MvccFeatureChecker.forcedMvcc())
-            fail("https://issues.apache.org/jira/browse/IGNITE-7952");
+        Assume.assumeFalse("https://issues.apache.org/jira/browse/IGNITE-7952", MvccFeatureChecker.forcedMvcc());
     }
 
     /** {@inheritDoc} */
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/NotMappedPartitionInTxTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/NotMappedPartitionInTxTest.java
index c87d60e..75b6dd4 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/NotMappedPartitionInTxTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/NotMappedPartitionInTxTest.java
@@ -38,6 +38,7 @@ import org.apache.ignite.transactions.Transaction;
 import org.apache.ignite.transactions.TransactionConcurrency;
 import org.apache.ignite.transactions.TransactionIsolation;
 import org.jetbrains.annotations.Nullable;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -114,10 +115,9 @@ public class NotMappedPartitionInTxTest extends GridCommonAbstractTest {
     /**
      *
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-10377")
     @Test
     public void testOneServerMvcc() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-10377");
-
         try {
             atomicityMode = CacheAtomicityMode.TRANSACTIONAL_SNAPSHOT;
 
@@ -160,10 +160,9 @@ public class NotMappedPartitionInTxTest extends GridCommonAbstractTest {
     /**
      *
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-10377")
     @Test
     public void testFourServersMvcc() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-10377");
-
         try {
             atomicityMode = CacheAtomicityMode.TRANSACTIONAL_SNAPSHOT;
 
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/GridPartitionedBackupLoadSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/GridPartitionedBackupLoadSelfTest.java
index 3c783d5..a231105 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/GridPartitionedBackupLoadSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/GridPartitionedBackupLoadSelfTest.java
@@ -25,6 +25,7 @@ import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.testframework.MvccFeatureChecker;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.junit.Assume;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -75,8 +76,7 @@ public class GridPartitionedBackupLoadSelfTest extends GridCommonAbstractTest {
 
     /** {@inheritDoc} */
     @Override protected void beforeTest() throws Exception {
-        if (MvccFeatureChecker.forcedMvcc())
-            fail("https://issues.apache.org/jira/browse/IGNITE-8582");
+        Assume.assumeFalse("https://issues.apache.org/jira/browse/IGNITE-8582", MvccFeatureChecker.forcedMvcc());
 
         startGridsMultiThreaded(GRID_CNT);
     }
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/rebalancing/GridCacheRebalancingSyncSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/rebalancing/GridCacheRebalancingSyncSelfTest.java
index 440ffab..1c0f685 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/rebalancing/GridCacheRebalancingSyncSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/rebalancing/GridCacheRebalancingSyncSelfTest.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
@@ -58,10 +58,9 @@ import org.apache.ignite.resources.LoggerResource;
 import org.apache.ignite.spi.IgniteSpiException;
 import org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi;
 import org.apache.ignite.testframework.GridTestUtils;
-import org.apache.ignite.testframework.MvccFeatureChecker;
 import org.apache.ignite.testframework.GridTestUtils.SF;
+import org.apache.ignite.testframework.MvccFeatureChecker;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
-import org.junit.Assume;
 import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/rebalancing/GridCacheRebalancingWithAsyncClearingMvccTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/rebalancing/GridCacheRebalancingWithAsyncClearingMvccTest.java
index daf674e..89bd634 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/rebalancing/GridCacheRebalancingWithAsyncClearingMvccTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/rebalancing/GridCacheRebalancingWithAsyncClearingMvccTest.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/rebalancing/IgniteRebalanceOnCachesStoppingOrDestroyingTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/rebalancing/IgniteRebalanceOnCachesStoppingOrDestroyingTest.java
index 9a496f9..3e1367b 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/rebalancing/IgniteRebalanceOnCachesStoppingOrDestroyingTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/rebalancing/IgniteRebalanceOnCachesStoppingOrDestroyingTest.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/replicated/GridCacheReplicatedLockSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/replicated/GridCacheReplicatedLockSelfTest.java
index 45506f0..aeef0ea 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/replicated/GridCacheReplicatedLockSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/replicated/GridCacheReplicatedLockSelfTest.java
@@ -18,6 +18,7 @@ package org.apache.ignite.internal.processors.cache.distributed.replicated;
 
 import org.apache.ignite.cache.CacheMode;
 import org.apache.ignite.internal.processors.cache.distributed.GridCacheLockAbstractTest;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -35,8 +36,9 @@ public class GridCacheReplicatedLockSelfTest extends GridCacheLockAbstractTest {
     }
 
     /** {@inheritDoc} */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-835")
     @Test
     @Override public void testLockReentrancy() throws Throwable {
-        fail("https://issues.apache.org/jira/browse/IGNITE-835");
+        // No-op
     }
 }
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/replicated/GridCacheSyncReplicatedPreloadSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/replicated/GridCacheSyncReplicatedPreloadSelfTest.java
index f65a4d45..d5b169a 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/replicated/GridCacheSyncReplicatedPreloadSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/replicated/GridCacheSyncReplicatedPreloadSelfTest.java
@@ -25,6 +25,7 @@ import org.apache.ignite.internal.IgniteKernal;
 import org.apache.ignite.testframework.MvccFeatureChecker;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
 import org.jetbrains.annotations.Nullable;
+import org.junit.Assume;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -80,8 +81,7 @@ public class GridCacheSyncReplicatedPreloadSelfTest extends GridCommonAbstractTe
     @SuppressWarnings({"TooBroadScope"})
     @Test
     public void testNodeRestart() throws Exception {
-        if (MvccFeatureChecker.forcedMvcc())
-            fail("https://issues.apache.org/jira/browse/IGNITE-10082");
+        Assume.assumeFalse("https://issues.apache.org/jira/browse/IGNITE-10082", MvccFeatureChecker.forcedMvcc());
 
         int keyCnt = 1000;
         int retries = 20;
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/replicated/GridReplicatedTxPreloadTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/replicated/GridReplicatedTxPreloadTest.java
index 940a15a..d467b55 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/replicated/GridReplicatedTxPreloadTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/replicated/GridReplicatedTxPreloadTest.java
@@ -19,6 +19,7 @@ package org.apache.ignite.internal.processors.cache.distributed.replicated;
 import org.apache.ignite.cache.CacheMode;
 import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.internal.processors.cache.distributed.IgniteTxPreloadAbstractTest;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -41,8 +42,9 @@ public class GridReplicatedTxPreloadTest extends IgniteTxPreloadAbstractTest {
     }
 
     /** {@inheritDoc} */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-1755")
     @Test
     @Override public void testLocalTxPreloadingOptimistic() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-1755");
+        // No-op
     }
 }
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/replicated/preloader/GridCacheReplicatedPreloadSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/replicated/preloader/GridCacheReplicatedPreloadSelfTest.java
index c955b4e..a31952f 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/replicated/preloader/GridCacheReplicatedPreloadSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/replicated/preloader/GridCacheReplicatedPreloadSelfTest.java
@@ -53,6 +53,7 @@ import org.apache.ignite.spi.eventstorage.memory.MemoryEventStorageSpi;
 import org.apache.ignite.testframework.GridTestUtils;
 import org.apache.ignite.testframework.MvccFeatureChecker;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.junit.Assume;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -760,8 +761,7 @@ public class GridCacheReplicatedPreloadSelfTest extends GridCommonAbstractTest {
      */
     @Test
     public void testMultipleNodes() throws Exception {
-        if (MvccFeatureChecker.forcedMvcc())
-            fail("https://issues.apache.org/jira/browse/IGNITE-10082");
+        Assume.assumeFalse("https://issues.apache.org/jira/browse/IGNITE-10082", MvccFeatureChecker.forcedMvcc());
 
         preloadMode = ASYNC;
         batchSize = 256;
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/PageEvictionMetricTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/PageEvictionMetricTest.java
index 47f3e6e..a923870 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/PageEvictionMetricTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/PageEvictionMetricTest.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/PageEvictionPagesRecyclingAndReusingTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/PageEvictionPagesRecyclingAndReusingTest.java
index 35667bc..cf5c83d 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/PageEvictionPagesRecyclingAndReusingTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/PageEvictionPagesRecyclingAndReusingTest.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/PageEvictionReadThroughTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/PageEvictionReadThroughTest.java
index 6f6dc08..c2535ee 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/PageEvictionReadThroughTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/PageEvictionReadThroughTest.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/PageEvictionTouchOrderTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/PageEvictionTouchOrderTest.java
index 8914095..e006381 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/PageEvictionTouchOrderTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/PageEvictionTouchOrderTest.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
@@ -93,9 +93,6 @@ public class PageEvictionTouchOrderTest extends PageEvictionAbstractTest {
     @Ignore("https://issues.apache.org/jira/browse/IGNITE-10738,https://issues.apache.org/jira/browse/IGNITE-7956")
     @Test
     public void testTouchOrderWithFairFifoEvictionMvccTxPartitioned() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-10448");
-        fail("https://issues.apache.org/jira/browse/IGNITE-7956");
-
         testTouchOrderWithFairFifoEviction(CacheAtomicityMode.TRANSACTIONAL_SNAPSHOT, CacheMode.PARTITIONED);
     }
 
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/PageEvictionWithRebalanceAbstractTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/PageEvictionWithRebalanceAbstractTest.java
index 28c670d..c13568e 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/PageEvictionWithRebalanceAbstractTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/paged/PageEvictionWithRebalanceAbstractTest.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/expiry/IgniteCacheExpiryPolicyAbstractTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/expiry/IgniteCacheExpiryPolicyAbstractTest.java
index 7378591..40f7254 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/expiry/IgniteCacheExpiryPolicyAbstractTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/expiry/IgniteCacheExpiryPolicyAbstractTest.java
@@ -57,6 +57,7 @@ import org.apache.ignite.testframework.GridTestUtils;
 import org.apache.ignite.transactions.Transaction;
 import org.apache.ignite.transactions.TransactionConcurrency;
 import org.jetbrains.annotations.Nullable;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -359,10 +360,9 @@ public abstract class IgniteCacheExpiryPolicyAbstractTest extends IgniteCacheAbs
     /**
      * @throws Exception If failed.
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-305")
     @Test
     public void testAccess() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-305");
-
         factory = new FactoryBuilder.SingletonFactory<>(new TestPolicy(60_000L, 61_000L, 62_000L));
 
         startGrids();
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/multijvm/GridCacheAtomicNearEnabledMultiJvmFullApiSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/multijvm/GridCacheAtomicNearEnabledMultiJvmFullApiSelfTest.java
index 09b2541..2077fd4 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/multijvm/GridCacheAtomicNearEnabledMultiJvmFullApiSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/multijvm/GridCacheAtomicNearEnabledMultiJvmFullApiSelfTest.java
@@ -17,6 +17,7 @@
 package org.apache.ignite.internal.processors.cache.multijvm;
 
 import org.apache.ignite.internal.processors.cache.distributed.near.GridCacheAtomicNearEnabledMultiNodeFullApiSelfTest;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -33,8 +34,9 @@ public class GridCacheAtomicNearEnabledMultiJvmFullApiSelfTest extends
     }
 
     /** {@inheritDoc} */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-1112")
     @Test
     @Override public void testPutAllPutAll() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-1112");
+        // No-op
     }
 }
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/IgnitePdsCacheAssignmentNodeRestartsTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/IgnitePdsCacheAssignmentNodeRestartsTest.java
index ff6c53c..73cf107 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/IgnitePdsCacheAssignmentNodeRestartsTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/IgnitePdsCacheAssignmentNodeRestartsTest.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/IgnitePdsContinuousRestartTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/IgnitePdsContinuousRestartTest.java
index 894cc6b..5638f1a 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/IgnitePdsContinuousRestartTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/IgnitePdsContinuousRestartTest.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/IgnitePdsPartitionFilesDestroyTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/IgnitePdsPartitionFilesDestroyTest.java
index 8507085..56a5e6c 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/IgnitePdsPartitionFilesDestroyTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/IgnitePdsPartitionFilesDestroyTest.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/IgnitePdsPartitionsStateRecoveryTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/IgnitePdsPartitionsStateRecoveryTest.java
index fdf3733..879a3e3 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/IgnitePdsPartitionsStateRecoveryTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/IgnitePdsPartitionsStateRecoveryTest.java
@@ -31,6 +31,7 @@ import org.apache.ignite.internal.processors.cache.distributed.dht.topology.Grid
 import org.apache.ignite.testframework.MvccFeatureChecker;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
 import org.junit.Assert;
+import org.junit.Assume;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -144,8 +145,7 @@ public class IgnitePdsPartitionsStateRecoveryTest extends GridCommonAbstractTest
      */
     @Test
     public void testPartitionsStateConsistencyAfterRecoveryNoCheckpoints() throws Exception {
-        if (MvccFeatureChecker.forcedMvcc())
-            fail("https://issues.apache.org/jira/browse/IGNITE-10603");
+        Assume.assumeFalse("https://issues.apache.org/jira/browse/IGNITE-10603", MvccFeatureChecker.forcedMvcc());
 
         IgniteEx ignite = startGrid(0);
 
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/IgniteRebalanceScheduleResendPartitionsTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/IgniteRebalanceScheduleResendPartitionsTest.java
index f2c3439..d4cf257 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/IgniteRebalanceScheduleResendPartitionsTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/IgniteRebalanceScheduleResendPartitionsTest.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/LocalWalModeChangeDuringRebalancingSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/LocalWalModeChangeDuringRebalancingSelfTest.java
index 567bbff..be377b8 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/LocalWalModeChangeDuringRebalancingSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/LocalWalModeChangeDuringRebalancingSelfTest.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/baseline/ClientAffinityAssignmentWithBaselineTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/baseline/ClientAffinityAssignmentWithBaselineTest.java
index 7ae8875..fcba76f 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/baseline/ClientAffinityAssignmentWithBaselineTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/baseline/ClientAffinityAssignmentWithBaselineTest.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/IgnitePdsPageEvictionDuringPartitionClearTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/IgnitePdsPageEvictionDuringPartitionClearTest.java
index d251572..1152e8b 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/IgnitePdsPageEvictionDuringPartitionClearTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/IgnitePdsPageEvictionDuringPartitionClearTest.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/IgnitePdsPartitionPreloadTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/IgnitePdsPartitionPreloadTest.java
index 9e98d77..8e922e4 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/IgnitePdsPartitionPreloadTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/IgnitePdsPartitionPreloadTest.java
@@ -37,6 +37,7 @@ import org.apache.ignite.internal.util.typedef.G;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.lang.IgnitePredicate;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -558,10 +559,9 @@ public class IgnitePdsPartitionPreloadTest extends GridCommonAbstractTest {
     }
 
     /** */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9530")
     @Test
     public void testPreloadLocalTransactionalSyncMvcc() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9530");
-
         cfgFactory = () -> cacheConfiguration(TRANSACTIONAL_SNAPSHOT).setCacheMode(LOCAL);
 
         preloadPartition(
@@ -578,10 +578,9 @@ public class IgnitePdsPartitionPreloadTest extends GridCommonAbstractTest {
     }
 
     /** */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9530")
     @Test
     public void testPreloadLocalTransactionalAsyncMvcc() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9530");
-
         cfgFactory = () -> cacheConfiguration(TRANSACTIONAL_SNAPSHOT).setCacheMode(LOCAL);
 
         preloadPartition(
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/IgnitePdsRebalancingOnNotStableTopologyTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/IgnitePdsRebalancingOnNotStableTopologyTest.java
index 0c0b2a1..ed7e2fa 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/IgnitePdsRebalancingOnNotStableTopologyTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/IgnitePdsRebalancingOnNotStableTopologyTest.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/IgniteNodeStoppedDuringDisableWALTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/IgniteNodeStoppedDuringDisableWALTest.java
index 3228bff..77009b5 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/IgniteNodeStoppedDuringDisableWALTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/IgniteNodeStoppedDuringDisableWALTest.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/IgniteWalFlushMultiNodeFailoverAbstractSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/IgniteWalFlushMultiNodeFailoverAbstractSelfTest.java
index 439feca..89cc64c 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/IgniteWalFlushMultiNodeFailoverAbstractSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/IgniteWalFlushMultiNodeFailoverAbstractSelfTest.java
@@ -47,6 +47,7 @@ import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
 import org.apache.ignite.transactions.Transaction;
 import org.apache.ignite.transactions.TransactionConcurrency;
 import org.apache.ignite.transactions.TransactionIsolation;
+import org.junit.Assume;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -72,8 +73,7 @@ public abstract class IgniteWalFlushMultiNodeFailoverAbstractSelfTest extends Gr
 
     /** {@inheritDoc} */
     @Override protected void beforeTest() throws Exception {
-        if (MvccFeatureChecker.forcedMvcc())
-            fail("https://issues.apache.org/jira/browse/IGNITE-10550");
+        Assume.assumeFalse("https://issues.apache.org/jira/browse/IGNITE-10550", MvccFeatureChecker.forcedMvcc());
 
         super.beforeTest();
 
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/IgniteWalFormatFileFailoverTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/IgniteWalFormatFileFailoverTest.java
index 41bdc7e..e0faef4 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/IgniteWalFormatFileFailoverTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/IgniteWalFormatFileFailoverTest.java
@@ -40,6 +40,7 @@ import org.apache.ignite.internal.processors.cache.persistence.wal.FileWriteAhea
 import org.apache.ignite.internal.util.typedef.X;
 import org.apache.ignite.testframework.GridTestUtils;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -111,10 +112,9 @@ public class IgniteWalFormatFileFailoverTest extends GridCommonAbstractTest {
     /**
      * @throws Exception If failed.
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-10035")
     @Test
     public void testFailureHandlerTriggeredFsync() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-10035");
-
         fsync = true;
 
         failFormatFileOnClusterActivate();
@@ -123,10 +123,9 @@ public class IgniteWalFormatFileFailoverTest extends GridCommonAbstractTest {
     /**
      * @throws Exception If failed.
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-10035")
     @Test
     public void testFailureHandlerTriggered() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-10035");
-
         fsync = false;
 
         failFormatFileOnClusterActivate();
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/IgniteWalHistoryReservationsTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/IgniteWalHistoryReservationsTest.java
index 9ee1493..b9c28e3 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/IgniteWalHistoryReservationsTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/IgniteWalHistoryReservationsTest.java
@@ -40,6 +40,7 @@ import org.apache.ignite.testframework.GridTestUtils;
 import org.apache.ignite.testframework.MvccFeatureChecker;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
 import org.junit.Assert;
+import org.junit.Assume;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -260,8 +261,7 @@ public class IgniteWalHistoryReservationsTest extends GridCommonAbstractTest {
      */
     @Test
     public void testRemovesArePreloadedIfHistoryIsAvailable() throws Exception {
-        if (MvccFeatureChecker.forcedMvcc())
-            fail("https://issues.apache.org/jira/browse/IGNITE-10551");
+        Assume.assumeFalse("https://issues.apache.org/jira/browse/IGNITE-10551", MvccFeatureChecker.forcedMvcc());
 
         int entryCnt = 10_000;
 
@@ -313,8 +313,7 @@ public class IgniteWalHistoryReservationsTest extends GridCommonAbstractTest {
      */
     @Test
     public void testNodeIsClearedIfHistoryIsUnavailable() throws Exception {
-        if (MvccFeatureChecker.forcedMvcc())
-            fail("https://issues.apache.org/jira/browse/IGNITE-10551");
+        Assume.assumeFalse("https://issues.apache.org/jira/browse/IGNITE-10551", MvccFeatureChecker.forcedMvcc());
 
         int entryCnt = 10_000;
 
@@ -377,8 +376,7 @@ public class IgniteWalHistoryReservationsTest extends GridCommonAbstractTest {
      */
     @Test
     public void testWalHistoryPartiallyRemoved() throws Exception {
-        if (MvccFeatureChecker.forcedMvcc())
-            fail("https://issues.apache.org/jira/browse/IGNITE-10551");
+        Assume.assumeFalse("https://issues.apache.org/jira/browse/IGNITE-10551", MvccFeatureChecker.forcedMvcc());
 
         int entryCnt = 10_000;
 
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/reader/IgniteWalReaderTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/reader/IgniteWalReaderTest.java
index b976739..65ebc1e 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/reader/IgniteWalReaderTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/reader/IgniteWalReaderTest.java
@@ -84,6 +84,7 @@ import org.apache.ignite.transactions.Transaction;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.junit.Assert;
+import org.junit.Assume;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -912,8 +913,7 @@ public class IgniteWalReaderTest extends GridCommonAbstractTest {
      */
     @Test
     public void testRemoveOperationPresentedForDataEntryForAtomic() throws Exception {
-        if (MvccFeatureChecker.forcedMvcc())
-            return;
+        Assume.assumeFalse(MvccFeatureChecker.forcedMvcc());
 
         runRemoveOperationTest(CacheAtomicityMode.ATOMIC);
     }
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/IgniteChangeGlobalStateServiceTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/IgniteChangeGlobalStateServiceTest.java
index fab7a73..bde6c27 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/IgniteChangeGlobalStateServiceTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/IgniteChangeGlobalStateServiceTest.java
@@ -24,6 +24,7 @@ import org.apache.ignite.services.Service;
 import org.apache.ignite.services.ServiceConfiguration;
 import org.apache.ignite.services.ServiceContext;
 import org.apache.ignite.services.ServiceDescriptor;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -51,10 +52,9 @@ public class IgniteChangeGlobalStateServiceTest extends IgniteChangeGlobalStateA
     /**
      *
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-6629")
     @Test
     public void testDeployService() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-6629");
-
         Ignite ig1P = primary(0);
 
         Ignite ig1B = backUp(0);
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/IgniteChangeGlobalStateTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/IgniteChangeGlobalStateTest.java
index 2b8d72c..5ceeb7d 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/IgniteChangeGlobalStateTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/IgniteChangeGlobalStateTest.java
@@ -20,7 +20,6 @@ import java.util.Arrays;
 import java.util.List;
 import java.util.concurrent.Callable;
 import java.util.concurrent.CyclicBarrier;
-import java.util.concurrent.atomic.AtomicInteger;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteAtomicSequence;
 import org.apache.ignite.IgniteCache;
@@ -31,6 +30,7 @@ import org.apache.ignite.internal.IgniteEx;
 import org.apache.ignite.internal.IgniteInternalFuture;
 import org.apache.ignite.internal.processors.cache.GridCacheProcessor;
 import org.apache.ignite.internal.util.typedef.F;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -555,10 +555,9 @@ public class IgniteChangeGlobalStateTest extends IgniteChangeGlobalStateAbstract
     /**
      * @throws Exception If failed.
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-10723")
     @Test
     public void testActivateAfterFailGetLock() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-10723");
-
         Ignite ig1P = primary(0);
         Ignite ig2P = primary(1);
         Ignite ig3P = primary(2);
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/join/JoinActiveNodeToActiveCluster.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/join/JoinActiveNodeToActiveCluster.java
index 27a3983..de19d14 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/join/JoinActiveNodeToActiveCluster.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/join/JoinActiveNodeToActiveCluster.java
@@ -17,12 +17,13 @@
 package org.apache.ignite.internal.processors.cache.persistence.standbycluster.join;
 
 import java.util.Map;
-import org.apache.ignite.internal.processors.cache.persistence.standbycluster.AbstractNodeJoinTemplate;
 import org.apache.ignite.internal.IgniteEx;
 import org.apache.ignite.internal.processors.cache.DynamicCacheDescriptor;
 import org.apache.ignite.internal.processors.cache.GridCacheAdapter;
+import org.apache.ignite.internal.processors.cache.persistence.standbycluster.AbstractNodeJoinTemplate;
 import org.apache.ignite.internal.util.typedef.internal.CU;
 import org.junit.Assert;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -240,10 +241,9 @@ public class JoinActiveNodeToActiveCluster extends AbstractNodeJoinTemplate {
     }
 
     /** {@inheritDoc} */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-5518")
     @Test
     @Override public void testJoinClientStaticCacheConfigurationInCluster() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-5518");
-
         joinClientStaticCacheConfigurationInClusterTemplate().execute();
     }
 
@@ -256,10 +256,9 @@ public class JoinActiveNodeToActiveCluster extends AbstractNodeJoinTemplate {
     /**
      *
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-5518")
     @Test
     @Override public void testJoinClientStaticCacheConfigurationDifferentOnBoth() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-5518");
-
         joinClientStaticCacheConfigurationDifferentOnBothTemplate().execute();
     }
 
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/join/JoinActiveNodeToInActiveCluster.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/join/JoinActiveNodeToInActiveCluster.java
index 8874886..941989c 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/join/JoinActiveNodeToInActiveCluster.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/join/JoinActiveNodeToInActiveCluster.java
@@ -17,6 +17,7 @@
 package org.apache.ignite.internal.processors.cache.persistence.standbycluster.join;
 
 import org.apache.ignite.internal.processors.cache.persistence.standbycluster.AbstractNodeJoinTemplate;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -200,10 +201,9 @@ public class JoinActiveNodeToInActiveCluster extends AbstractNodeJoinTemplate {
     }
 
     /** {@inheritDoc} */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-5518")
     @Test
     @Override public void testJoinClientStaticCacheConfigurationInCluster() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-5518");
-
         joinClientStaticCacheConfigurationInClusterTemplate().execute();
     }
 
@@ -214,10 +214,9 @@ public class JoinActiveNodeToInActiveCluster extends AbstractNodeJoinTemplate {
     }
 
     /** {@inheritDoc} */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-5518")
     @Test
     @Override public void testJoinClientStaticCacheConfigurationDifferentOnBoth() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-5518");
-
         joinClientStaticCacheConfigurationDifferentOnBothTemplate().execute();
     }
 
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/join/JoinInActiveNodeToActiveCluster.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/join/JoinInActiveNodeToActiveCluster.java
index 257c88f..2321162 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/join/JoinInActiveNodeToActiveCluster.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/join/JoinInActiveNodeToActiveCluster.java
@@ -17,12 +17,13 @@
 package org.apache.ignite.internal.processors.cache.persistence.standbycluster.join;
 
 import java.util.Map;
-import org.apache.ignite.internal.processors.cache.persistence.standbycluster.AbstractNodeJoinTemplate;
 import org.apache.ignite.internal.IgniteEx;
 import org.apache.ignite.internal.processors.cache.DynamicCacheDescriptor;
 import org.apache.ignite.internal.processors.cache.GridCacheAdapter;
+import org.apache.ignite.internal.processors.cache.persistence.standbycluster.AbstractNodeJoinTemplate;
 import org.apache.ignite.internal.util.typedef.internal.CU;
 import org.junit.Assert;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -251,10 +252,9 @@ public class JoinInActiveNodeToActiveCluster extends AbstractNodeJoinTemplate {
     }
 
     /** {@inheritDoc} */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-5518")
     @Test
     @Override public void testJoinClientStaticCacheConfigurationDifferentOnBoth() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-5518");
-
         joinClientStaticCacheConfigurationDifferentOnBothTemplate().execute();
     }
 
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/join/JoinInActiveNodeToInActiveCluster.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/join/JoinInActiveNodeToInActiveCluster.java
index 1adc374..f1784be 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/join/JoinInActiveNodeToInActiveCluster.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/standbycluster/join/JoinInActiveNodeToInActiveCluster.java
@@ -17,6 +17,7 @@
 package org.apache.ignite.internal.processors.cache.persistence.standbycluster.join;
 
 import org.apache.ignite.internal.processors.cache.persistence.standbycluster.AbstractNodeJoinTemplate;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -200,10 +201,9 @@ public class JoinInActiveNodeToInActiveCluster extends AbstractNodeJoinTemplate
     }
 
     /** {@inheritDoc} */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-5518")
     @Test
     @Override public void testJoinClientStaticCacheConfigurationInCluster() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-5518");
-
         joinClientStaticCacheConfigurationInClusterTemplate().execute();
     }
 
@@ -214,10 +214,9 @@ public class JoinInActiveNodeToInActiveCluster extends AbstractNodeJoinTemplate
     }
 
     /** {@inheritDoc} */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-5518")
     @Test
     @Override public void testJoinClientStaticCacheConfigurationDifferentOnBoth() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-5518");
-
         joinClientStaticCacheConfigurationDifferentOnBothTemplate().execute();
     }
 
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/wal/ExplicitWalDeltaConsistencyTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/wal/ExplicitWalDeltaConsistencyTest.java
index dabd1dd..a3bacd7 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/wal/ExplicitWalDeltaConsistencyTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/wal/ExplicitWalDeltaConsistencyTest.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryExecuteInPrimaryTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryExecuteInPrimaryTest.java
index f1f1b4e..69ee3ad 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryExecuteInPrimaryTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryExecuteInPrimaryTest.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
@@ -43,6 +43,7 @@ import org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
 import org.apache.ignite.transactions.Transaction;
 import org.jetbrains.annotations.NotNull;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -167,10 +168,9 @@ public class CacheContinuousQueryExecuteInPrimaryTest extends GridCommonAbstract
     /**
      * @throws Exception If failed.
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9530")
     @Test
     public void testMvccTransactionLocalCache() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9530");
-
         CacheConfiguration<Integer, String> ccfg = cacheConfiguration(TRANSACTIONAL_SNAPSHOT, LOCAL);
 
         doTestWithoutEventsEntries(ccfg);
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheKeepBinaryIterationStoreEnabledTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheKeepBinaryIterationStoreEnabledTest.java
index 260e573..88705ac 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheKeepBinaryIterationStoreEnabledTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheKeepBinaryIterationStoreEnabledTest.java
@@ -23,6 +23,7 @@ import org.apache.ignite.cache.CacheMode;
 import org.apache.ignite.cache.CacheWriteSynchronizationMode;
 import org.apache.ignite.cache.store.CacheStoreAdapter;
 import org.apache.ignite.configuration.CacheConfiguration;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -54,15 +55,17 @@ public class CacheKeepBinaryIterationStoreEnabledTest extends CacheKeepBinaryIte
     }
 
     /** {@inheritDoc} */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-8582")
     @Test
     @Override public void testMvccTxOnHeap() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-8582");
+        // No-op
     }
 
     /** {@inheritDoc} */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-8582")
     @Test
     @Override public void testMvccTxOnHeapLocalEntries() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-8582");
+        // No-op
     }
 
     /**
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TransactionIntegrityWithPrimaryIndexCorruptionTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TransactionIntegrityWithPrimaryIndexCorruptionTest.java
index 715970e..d83561f 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TransactionIntegrityWithPrimaryIndexCorruptionTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TransactionIntegrityWithPrimaryIndexCorruptionTest.java
@@ -33,10 +33,11 @@ import org.apache.ignite.internal.processors.cache.persistence.tree.io.PageIO;
 import org.apache.ignite.internal.processors.cache.persistence.tree.util.PageHandler;
 import org.apache.ignite.internal.processors.cache.tree.SearchRow;
 import org.apache.ignite.testframework.GridTestUtils;
+import org.apache.ignite.testframework.MvccFeatureChecker;
+import org.junit.Assume;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
-import org.apache.ignite.testframework.MvccFeatureChecker;
 
 import static org.apache.ignite.internal.processors.cache.distributed.dht.topology.GridDhtPartitionState.OWNING;
 
@@ -50,8 +51,7 @@ public class TransactionIntegrityWithPrimaryIndexCorruptionTest extends Abstract
 
     /** {@inheritDoc} */
     @Override protected void beforeTest() throws Exception {
-        if (MvccFeatureChecker.forcedMvcc())
-            fail("https://issues.apache.org/jira/browse/IGNITE-10470");
+        Assume.assumeFalse("https://issues.apache.org/jira/browse/IGNITE-10470", MvccFeatureChecker.forcedMvcc());
 
         super.beforeTest();
     }
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TxRollbackAsyncTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TxRollbackAsyncTest.java
index ef50258..380cb7c 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TxRollbackAsyncTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TxRollbackAsyncTest.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
@@ -482,8 +482,7 @@ public class TxRollbackAsyncTest extends GridCommonAbstractTest {
      */
     @Test
     public void testEnlistManyReadOptimistic() throws Exception {
-        if (MvccFeatureChecker.forcedMvcc())
-            return; // Optimistic transactions are not supported by MVCC.
+        Assume.assumeFalse(MvccFeatureChecker.forcedMvcc()); // Optimistic transactions are not supported by MVCC.
 
         testEnlistMany(false, SERIALIZABLE, OPTIMISTIC);
     }
@@ -493,8 +492,7 @@ public class TxRollbackAsyncTest extends GridCommonAbstractTest {
      */
     @Test
     public void testEnlistManyWriteOptimistic() throws Exception {
-        if (MvccFeatureChecker.forcedMvcc())
-            return; // Optimistic transactions are not supported by MVCC.
+        Assume.assumeFalse(MvccFeatureChecker.forcedMvcc()); // Optimistic transactions are not supported by MVCC.
 
         testEnlistMany(true, SERIALIZABLE, OPTIMISTIC);
     }
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TxRollbackOnIncorrectParamsTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TxRollbackOnIncorrectParamsTest.java
index e08bfbe..48d29a0 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TxRollbackOnIncorrectParamsTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TxRollbackOnIncorrectParamsTest.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TxRollbackOnTimeoutTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TxRollbackOnTimeoutTest.java
index de47804..bb85776 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TxRollbackOnTimeoutTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TxRollbackOnTimeoutTest.java
@@ -53,14 +53,15 @@ import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.lang.IgniteInClosure;
 import org.apache.ignite.plugin.extensions.communication.Message;
 import org.apache.ignite.testframework.GridTestUtils;
-import org.apache.ignite.testframework.MvccFeatureChecker;
 import org.apache.ignite.testframework.GridTestUtils.SF;
+import org.apache.ignite.testframework.MvccFeatureChecker;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
 import org.apache.ignite.transactions.Transaction;
 import org.apache.ignite.transactions.TransactionConcurrency;
 import org.apache.ignite.transactions.TransactionDeadlockException;
 import org.apache.ignite.transactions.TransactionIsolation;
 import org.apache.ignite.transactions.TransactionTimeoutException;
+import org.junit.Assume;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -129,8 +130,7 @@ public class TxRollbackOnTimeoutTest extends GridCommonAbstractTest {
 
     /** {@inheritDoc} */
     @Override protected void beforeTest() throws Exception {
-        if (MvccFeatureChecker.forcedMvcc())
-            fail("https://issues.apache.org/jira/browse/IGNITE-7388");
+        Assume.assumeFalse("https://issues.apache.org/jira/browse/IGNITE-7388", MvccFeatureChecker.forcedMvcc());
 
         super.beforeTest();
 
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TxRollbackOnTopologyChangeTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TxRollbackOnTopologyChangeTest.java
index 980715f6..3c07498 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TxRollbackOnTopologyChangeTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TxRollbackOnTopologyChangeTest.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
@@ -17,7 +17,6 @@
 package org.apache.ignite.internal.processors.cache.transactions;
 
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.List;
 import java.util.Random;
 import java.util.concurrent.Callable;
@@ -25,15 +24,12 @@ import java.util.concurrent.CyclicBarrier;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicIntegerArray;
-import org.apache.ignite.Ignite;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.configuration.TransactionConfiguration;
 import org.apache.ignite.internal.IgniteEx;
 import org.apache.ignite.internal.IgniteInternalFuture;
 import org.apache.ignite.internal.TestRecordingCommunicationSpi;
-import org.apache.ignite.internal.processors.cache.GridCacheFuture;
-import org.apache.ignite.internal.util.typedef.G;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.testframework.MvccFeatureChecker;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/database/IgniteDbDynamicCacheSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/database/IgniteDbDynamicCacheSelfTest.java
index a49f1d8..b75c44e 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/database/IgniteDbDynamicCacheSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/database/IgniteDbDynamicCacheSelfTest.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/database/IgniteDbPutGetAbstractTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/database/IgniteDbPutGetAbstractTest.java
index 415e754..6d48ead 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/database/IgniteDbPutGetAbstractTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/database/IgniteDbPutGetAbstractTest.java
@@ -45,6 +45,7 @@ import org.apache.ignite.internal.util.typedef.X;
 import org.apache.ignite.testframework.GridTestUtils;
 import org.apache.ignite.testframework.MvccFeatureChecker;
 import org.junit.Assert;
+import org.junit.Assume;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -470,8 +471,7 @@ public abstract class IgniteDbPutGetAbstractTest extends IgniteDbAbstractTest {
      */
     @Test
     public void testSizeClear() throws Exception {
-        if (MvccFeatureChecker.forcedMvcc())
-            fail("https://issues.apache.org/jira/browse/IGNITE-7952");
+        Assume.assumeFalse("https://issues.apache.org/jira/browse/IGNITE-7952", MvccFeatureChecker.forcedMvcc());
 
         final IgniteCache<Integer, DbValue> cache = cache(DEFAULT_CACHE_NAME);
 
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/datastreamer/DataStreamerMultiThreadedSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/datastreamer/DataStreamerMultiThreadedSelfTest.java
index 41b61e8..27f55aa 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/datastreamer/DataStreamerMultiThreadedSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/datastreamer/DataStreamerMultiThreadedSelfTest.java
@@ -30,6 +30,7 @@ import org.apache.ignite.lang.IgniteFuture;
 import org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi;
 import org.apache.ignite.testframework.GridTestUtils;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -84,10 +85,9 @@ public class DataStreamerMultiThreadedSelfTest extends GridCommonAbstractTest {
     /**
      * @throws Exception If failed.
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-1602")
     @Test
     public void testStartStopIgnitesDynamicCache() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-1602");
-
         dynamicCache = true;
 
         startStopIgnites();
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/datastreamer/DataStreamerMultinodeCreateCacheTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/datastreamer/DataStreamerMultinodeCreateCacheTest.java
index 6e12907..6fa47a2 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/datastreamer/DataStreamerMultinodeCreateCacheTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/datastreamer/DataStreamerMultinodeCreateCacheTest.java
@@ -26,6 +26,7 @@ import org.apache.ignite.internal.IgniteInternalFuture;
 import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
 import org.apache.ignite.testframework.GridTestUtils;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -53,10 +54,9 @@ public class DataStreamerMultinodeCreateCacheTest extends GridCommonAbstractTest
     /**
      * @throws Exception If failed.
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-1603")
     @Test
     public void testCreateCacheAndStream() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-1603");
-
         final int THREADS = 5;
 
         startGrids(THREADS);
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsPrimaryMultiNodeSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsPrimaryMultiNodeSelfTest.java
index fb58215..c1f64c9 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsPrimaryMultiNodeSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsPrimaryMultiNodeSelfTest.java
@@ -16,6 +16,7 @@
 
 package org.apache.ignite.internal.processors.igfs;
 
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -33,8 +34,9 @@ public class IgfsPrimaryMultiNodeSelfTest extends IgfsPrimarySelfTest {
     /**
      * @throws Exception If failed.
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-8823")
     @Test
     @Override public void testCreateConsistencyMultithreaded() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-8823");
+        // No-op
     }
 }
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsPrimaryRelaxedConsistencyMultiNodeSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsPrimaryRelaxedConsistencyMultiNodeSelfTest.java
index 375de8a..aba94f6 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsPrimaryRelaxedConsistencyMultiNodeSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsPrimaryRelaxedConsistencyMultiNodeSelfTest.java
@@ -16,6 +16,7 @@
 
 package org.apache.ignite.internal.processors.igfs;
 
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -30,10 +31,9 @@ public class IgfsPrimaryRelaxedConsistencyMultiNodeSelfTest extends IgfsPrimaryR
         return 4;
     }
 
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-8823")
     @Test
     @Override public void testCreateConsistencyMultithreaded() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-8823");
-
         super.testCreateConsistencyMultithreaded();
     }
 }
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/util/IgniteDevOnlyLogTest.java b/modules/core/src/test/java/org/apache/ignite/internal/util/IgniteDevOnlyLogTest.java
index 3b5cd10..0d3137e 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/util/IgniteDevOnlyLogTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/util/IgniteDevOnlyLogTest.java
@@ -25,6 +25,7 @@ import org.apache.ignite.lang.IgniteRunnable;
 import org.apache.ignite.resources.IgniteInstanceResource;
 import org.apache.ignite.testframework.GridStringLogger;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -58,10 +59,9 @@ public class IgniteDevOnlyLogTest extends GridCommonAbstractTest {
     }
 
     /** Check that dev-only messages appear in the log. */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9328")
     @Test
     public void testDevOnlyQuietMessage() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9328");
-
         additionalArgs = Collections.singletonList("-D" + IgniteSystemProperties.IGNITE_QUIET + "=true");
 
         log = new GridStringLogger(false, grid(0).log());
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/util/ipc/shmem/IpcSharedMemoryCrashDetectionSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/util/ipc/shmem/IpcSharedMemoryCrashDetectionSelfTest.java
index 24ccc33..8747aac 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/util/ipc/shmem/IpcSharedMemoryCrashDetectionSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/util/ipc/shmem/IpcSharedMemoryCrashDetectionSelfTest.java
@@ -35,6 +35,7 @@ import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.testframework.junits.IgniteTestResources;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
 import org.jetbrains.annotations.Nullable;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -116,10 +117,9 @@ public class IpcSharedMemoryCrashDetectionSelfTest extends GridCommonAbstractTes
     /**
      * @throws Exception If failed.
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-1386")
     @Test
     public void testIgfsClientServerInteractionsUponServerKilling() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-1386");
-
         Collection<Integer> shmemIdsBeforeInteractions = IpcSharedMemoryUtils.sharedMemoryIds();
 
         info("Shared memory IDs before starting server-client interactions: " + shmemIdsBeforeInteractions);
diff --git a/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoveryMultiThreadedTest.java b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoveryMultiThreadedTest.java
index 753baad..2e6c611 100644
--- a/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoveryMultiThreadedTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoveryMultiThreadedTest.java
@@ -55,6 +55,7 @@ import org.apache.ignite.spi.IgniteSpiException;
 import org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi;
 import org.apache.ignite.testframework.GridTestUtils;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -217,20 +218,18 @@ public class TcpDiscoveryMultiThreadedTest extends GridCommonAbstractTest {
     /**
      * @throws Exception If any error occurs.
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-1123")
     @Test
     public void testMultiThreadedClientsServersRestart() throws Throwable {
-        fail("https://issues.apache.org/jira/browse/IGNITE-1123");
-
         multiThreadedClientsServersRestart(GRID_CNT, CLIENT_GRID_CNT);
     }
 
     /**
      * @throws Exception If any error occurs.
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-1123")
     @Test
     public void testMultiThreadedServersRestart() throws Throwable {
-        fail("https://issues.apache.org/jira/browse/IGNITE-1123");
-
         multiThreadedClientsServersRestart(GRID_CNT * 2, 0);
     }
 
@@ -500,10 +499,9 @@ public class TcpDiscoveryMultiThreadedTest extends GridCommonAbstractTest {
     /**
      * @throws Exception If failed.
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-10198")
     @Test
     public void testCustomEventOnJoinCoordinatorStop() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-10198");
-
         for (int k = 0; k < 10; k++) {
             log.info("Iteration: " + k);
 
@@ -599,10 +597,9 @@ public class TcpDiscoveryMultiThreadedTest extends GridCommonAbstractTest {
     /**
      * @throws Exception If failed.
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-10198")
     @Test
     public void testClientContinuousQueryCoordinatorStop() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-10198");
-
         for (int k = 0; k < 10; k++) {
             log.info("Iteration: " + k);
 
@@ -671,10 +668,9 @@ public class TcpDiscoveryMultiThreadedTest extends GridCommonAbstractTest {
     /**
      * @throws Exception If failed.
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-10249")
     @Test
     public void testCustomEventNodeRestart() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-10249");
-
         clientFlagGlobal = false;
 
         Ignite ignite = startGrid(0);
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IndexingCachePartitionLossPolicySelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IndexingCachePartitionLossPolicySelfTest.java
index 46c3a0b..7deb410 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IndexingCachePartitionLossPolicySelfTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IndexingCachePartitionLossPolicySelfTest.java
@@ -36,12 +36,12 @@ public class IndexingCachePartitionLossPolicySelfTest extends IgniteCachePartiti
     }
 
     /** {@inheritDoc} */
-    protected void checkQueryPasses(Ignite node, boolean loc, int... parts) {
+    @Override protected void checkQueryPasses(Ignite node, boolean loc, int... parts) {
         executeQuery(node, loc, parts);
     }
 
     /** {@inheritDoc} */
-    protected void checkQueryFails(Ignite node, boolean loc, int... parts) {
+    @Override protected void checkQueryFails(Ignite node, boolean loc, int... parts) {
         // TODO: Local queries ignore partition loss, see https://issues.apache.org/jira/browse/IGNITE-7039.
         if (loc)
             return;
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/IgniteCacheQueryNodeRestartSelfTest2.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/IgniteCacheQueryNodeRestartSelfTest2.java
index 9460417..a167bea 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/IgniteCacheQueryNodeRestartSelfTest2.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/IgniteCacheQueryNodeRestartSelfTest2.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
diff --git a/modules/mqtt/src/test/java/org/apache/ignite/stream/mqtt/IgniteMqttStreamerTest.java b/modules/mqtt/src/test/java/org/apache/ignite/stream/mqtt/IgniteMqttStreamerTest.java
index f35fd6b..2180d02 100644
--- a/modules/mqtt/src/test/java/org/apache/ignite/stream/mqtt/IgniteMqttStreamerTest.java
+++ b/modules/mqtt/src/test/java/org/apache/ignite/stream/mqtt/IgniteMqttStreamerTest.java
@@ -16,6 +16,9 @@
 
 package org.apache.ignite.stream.mqtt;
 
+import com.github.rholder.retry.StopStrategies;
+import com.github.rholder.retry.WaitStrategies;
+import com.google.common.base.Splitter;
 import java.net.ServerSocket;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -26,7 +29,6 @@ import java.util.TreeSet;
 import java.util.UUID;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
-
 import org.apache.activemq.broker.BrokerService;
 import org.apache.activemq.broker.region.policy.PolicyEntry;
 import org.apache.activemq.broker.region.policy.PolicyMap;
@@ -43,15 +45,12 @@ import org.apache.ignite.lang.IgniteInClosure;
 import org.apache.ignite.stream.StreamMultipleTupleExtractor;
 import org.apache.ignite.stream.StreamSingleTupleExtractor;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
-
-import com.github.rholder.retry.StopStrategies;
-import com.github.rholder.retry.WaitStrategies;
-import com.google.common.base.Splitter;
 import org.eclipse.paho.client.mqttv3.MqttClient;
 import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
 import org.eclipse.paho.client.mqttv3.MqttException;
 import org.eclipse.paho.client.mqttv3.MqttMessage;
 import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -194,10 +193,9 @@ public class IgniteMqttStreamerTest extends GridCommonAbstractTest {
     /**
      * @throws Exception If failed.
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-2255")
     @Test
     public void testConnectionStatusWithBrokerDisconnection() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-2255");
-
         // Configure streamer.
         streamer.setSingleTupleExtractor(singleTupleExtractor());
         streamer.setTopic(SINGLE_TOPIC_NAME);
diff --git a/modules/spring/src/test/java/org/apache/ignite/cache/spring/GridSpringCacheManagerMultiJvmSelfTest.java b/modules/spring/src/test/java/org/apache/ignite/cache/spring/GridSpringCacheManagerMultiJvmSelfTest.java
index 4bcc905..c2fae44 100644
--- a/modules/spring/src/test/java/org/apache/ignite/cache/spring/GridSpringCacheManagerMultiJvmSelfTest.java
+++ b/modules/spring/src/test/java/org/apache/ignite/cache/spring/GridSpringCacheManagerMultiJvmSelfTest.java
@@ -28,6 +28,7 @@ import org.apache.ignite.internal.IgniteInternalFuture;
 import org.apache.ignite.testframework.GridTestUtils;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
 import org.apache.ignite.testframework.junits.multijvm.IgniteProcessProxy;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -57,10 +58,9 @@ public class GridSpringCacheManagerMultiJvmSelfTest extends GridCommonAbstractTe
     /**
      * @throws Exception If failed.
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9488")
     @Test
     public void testSyncCache() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9488");
-
         IgniteEx loc = startGrid(0);
 
         final int threads = 4;


[ignite] 09/31: IGNITE-10623 More graceful error handling when node is stopping - Fixes #5623.

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch gg-19225
in repository https://gitbox.apache.org/repos/asf/ignite.git

commit 5b47baa78b351cd8f7f09cc16fad8804ece69d14
Author: EdShangGG <es...@gridgain.com>
AuthorDate: Tue Dec 11 18:37:45 2018 +0300

    IGNITE-10623 More graceful error handling when node is stopping - Fixes #5623.
    
    Signed-off-by: Alexey Goncharuk <al...@gmail.com>
    (cherry picked from commit d7111f3eec448009a6d3c9ff3731ac2e121660f2)
---
 .../processors/cache/GridCacheMvccManager.java     | 23 ++++++++++++++++++----
 1 file changed, 19 insertions(+), 4 deletions(-)

diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvccManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvccManager.java
index e023a42..52b1d90 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvccManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvccManager.java
@@ -426,11 +426,26 @@ public class GridCacheMvccManager extends GridCacheSharedManagerAdapter {
      * @param err Error.
      */
     private void cancelClientFutures(IgniteCheckedException err) {
-        for (GridCacheFuture<?> fut : activeFutures())
-            ((GridFutureAdapter)fut).onDone(err);
+        cancelFuturesWithException(err, activeFutures());
+        cancelFuturesWithException(err, atomicFuts.values());
+    }
 
-        for (GridCacheAtomicFuture<?> future : atomicFuts.values())
-            ((GridFutureAdapter)future).onDone(err);
+    /**
+     * @param err Error to complete future with.
+     * @param futures Collection of futures.
+     */
+    private void cancelFuturesWithException(
+        IgniteCheckedException err,
+        Collection<? extends IgniteInternalFuture<?>> futures
+    ) {
+        for (IgniteInternalFuture<?> fut : futures) {
+            try {
+                ((GridFutureAdapter)fut).onDone(err);
+            }
+            catch (Exception e) {
+                U.warn(log, "Failed to complete future on node stop (will ignore): " + fut, e);
+            }
+        }
     }
 
     /**


[ignite] 06/31: GG-18939 Web Console: Fixed dependency generation for Ignite CE libraries. #57

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch gg-19225
in repository https://gitbox.apache.org/repos/asf/ignite.git

commit c4e0f962fef48f4274e028f5e3222f8a7427b4d2
Author: Vasiliy Sisko <vs...@gridgain.com>
AuthorDate: Thu May 30 15:34:03 2019 +0700

    GG-18939 Web Console: Fixed dependency generation for Ignite CE libraries. #57
    
    (cherry picked from commit f4a199027f34f258cb2b4660b47d41c8fe2034a7)
---
 .../generator/generator/Maven.service.js           | 59 ++++++++++++----------
 1 file changed, 32 insertions(+), 27 deletions(-)

diff --git a/modules/web-console/frontend/app/configuration/generator/generator/Maven.service.js b/modules/web-console/frontend/app/configuration/generator/generator/Maven.service.js
index 7df7c12..9e4e301 100644
--- a/modules/web-console/frontend/app/configuration/generator/generator/Maven.service.js
+++ b/modules/web-console/frontend/app/configuration/generator/generator/Maven.service.js
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
@@ -52,14 +52,14 @@ export default class IgniteMavenGenerator {
         return _.isArray(version) ? _.find(version, (v) => versionService.since(igniteVer, v.range)).version : version;
     }
 
-    pickDependency(acc, key, dfltVer, igniteVer, storedVer) {
+    pickDependency(acc, key, artifactGrp, dfltVer, igniteVer, storedVer) {
         const deps = POM_DEPENDENCIES[key];
 
         if (_.isNil(deps))
             return;
 
         _.forEach(_.castArray(deps), ({groupId, artifactId, version, jar, link}) => {
-            this.addDependency(acc, groupId || 'org.apache.ignite', artifactId, storedVer || this._extractVersion(igniteVer, version) || dfltVer, jar, link);
+            this.addDependency(acc, groupId || artifactGrp, artifactId, storedVer || this._extractVersion(igniteVer, version) || dfltVer, jar, link);
         });
     }
 
@@ -77,8 +77,8 @@ export default class IgniteMavenGenerator {
         sb.endBlock('</resource>');
     }
 
-    artifactSection(sb, cluster, targetVer) {
-        this.addProperty(sb, 'groupId', 'org.apache.ignite');
+    artifactSection(sb, artifactGrp, cluster, targetVer) {
+        this.addProperty(sb, 'groupId', artifactGrp);
         this.addProperty(sb, 'artifactId', this.escapeId(cluster.name) + '-project');
         this.addProperty(sb, 'version', targetVer.ignite);
     }
@@ -155,31 +155,32 @@ export default class IgniteMavenGenerator {
     /**
      * Add dependency for specified store factory if not exist.
      *
+     * @param artifactGrp Artifact group ID.
      * @param deps Already added dependencies.
      * @param storeFactory Store factory to add dependency.
      * @param igniteVer Ignite version.
      */
-    storeFactoryDependency(deps, storeFactory, igniteVer) {
+    storeFactoryDependency(artifactGrp, deps, storeFactory, igniteVer) {
         if (storeFactory.dialect && (!storeFactory.connectVia || storeFactory.connectVia === 'DataSource'))
-            this.pickDependency(deps, storeFactory.dialect, null, igniteVer, storeFactory.implementationVersion);
+            this.pickDependency(deps, storeFactory.dialect, artifactGrp, null, igniteVer, storeFactory.implementationVersion);
     }
 
-    collectDependencies(cluster, targetVer) {
+    collectDependencies(artifactGrp, cluster, targetVer) {
         const igniteVer = targetVer.ignite;
 
         const deps = [];
         const storeDeps = [];
 
-        this.addDependency(deps, 'org.apache.ignite', 'ignite-core', igniteVer);
+        this.addDependency(deps, artifactGrp, 'ignite-core', igniteVer);
 
-        this.addDependency(deps, 'org.apache.ignite', 'ignite-spring', igniteVer);
-        this.addDependency(deps, 'org.apache.ignite', 'ignite-indexing', igniteVer);
-        this.addDependency(deps, 'org.apache.ignite', 'ignite-rest-http', igniteVer);
+        this.addDependency(deps, artifactGrp, 'ignite-spring', igniteVer);
+        this.addDependency(deps, artifactGrp, 'ignite-indexing', igniteVer);
+        this.addDependency(deps, artifactGrp, 'ignite-rest-http', igniteVer);
 
         if (_.get(cluster, 'deploymentSpi.kind') === 'URI')
-            this.addDependency(deps, 'org.apache.ignite', 'ignite-urideploy', igniteVer);
+            this.addDependency(deps, artifactGrp, 'ignite-urideploy', igniteVer);
 
-        this.pickDependency(deps, cluster.discovery.kind, igniteVer);
+        this.pickDependency(deps, cluster.discovery.kind, artifactGrp, igniteVer);
 
         const caches = cluster.caches;
 
@@ -187,35 +188,35 @@ export default class IgniteMavenGenerator {
 
         _.forEach(caches, (cache) => {
             if (cache.cacheStoreFactory && cache.cacheStoreFactory.kind)
-                this.storeFactoryDependency(storeDeps, cache.cacheStoreFactory[cache.cacheStoreFactory.kind], igniteVer);
+                this.storeFactoryDependency(artifactGrp, storeDeps, cache.cacheStoreFactory[cache.cacheStoreFactory.kind], igniteVer);
 
             if (_.get(cache, 'nodeFilter.kind') === 'Exclude')
-                this.addDependency(deps, 'org.apache.ignite', 'ignite-extdata-p2p', igniteVer);
+                this.addDependency(deps, artifactGrp, 'ignite-extdata-p2p', igniteVer);
         });
 
         if (cluster.discovery.kind === 'Jdbc') {
             const store = cluster.discovery.Jdbc;
 
             if (store.dataSourceBean && store.dialect)
-                this.storeFactoryDependency(storeDeps, cluster.discovery.Jdbc, igniteVer);
+                this.storeFactoryDependency(artifactGrp, storeDeps, cluster.discovery.Jdbc, igniteVer);
         }
 
         _.forEach(cluster.checkpointSpi, (spi) => {
             if (spi.kind === 'S3')
-                this.pickDependency(deps, spi.kind, igniteVer);
+                this.pickDependency(deps, spi.kind, artifactGrp, igniteVer);
             else if (spi.kind === 'JDBC')
-                this.storeFactoryDependency(storeDeps, spi.JDBC, igniteVer);
+                this.storeFactoryDependency(artifactGrp, storeDeps, spi.JDBC, igniteVer);
         });
 
         if (_.get(cluster, 'hadoopConfiguration.mapReducePlanner.kind') === 'Weighted' ||
             _.find(cluster.igfss, (igfs) => igfs.secondaryFileSystemEnabled))
-            this.addDependency(deps, 'org.apache.ignite', 'ignite-hadoop', igniteVer);
+            this.addDependency(deps, artifactGrp, 'ignite-hadoop', igniteVer);
 
         if (_.find(caches, blobStoreFactory))
-            this.addDependency(deps, 'org.apache.ignite', 'ignite-hibernate', igniteVer);
+            this.addDependency(deps, artifactGrp, 'ignite-hibernate', igniteVer);
 
         if (cluster.logger && cluster.logger.kind)
-            this.pickDependency(deps, cluster.logger.kind, igniteVer);
+            this.pickDependency(deps, cluster.logger.kind, artifactGrp, igniteVer);
 
         return _.uniqWith(deps.concat(ArtifactVersionChecker.latestVersions(storeDeps)), _.isEqual);
     }
@@ -230,6 +231,10 @@ export default class IgniteMavenGenerator {
     generate(cluster, targetVer) {
         const sb = new StringBuilder();
 
+        const artifactGrp = versionService.since(targetVer.ignite, '8.7.3')
+            ? 'org.gridgain'
+            : 'org.apache.ignite';
+
         sb.append('<?xml version="1.0" encoding="UTF-8"?>');
 
         sb.emptyLine();
@@ -244,17 +249,17 @@ export default class IgniteMavenGenerator {
 
         sb.emptyLine();
 
-        this.artifactSection(sb, cluster, targetVer);
+        this.artifactSection(sb, artifactGrp, cluster, targetVer);
 
         sb.emptyLine();
 
-        const deps = this.collectDependencies(cluster, targetVer);
+        const deps = this.collectDependencies(artifactGrp, cluster, targetVer);
 
         this.dependenciesSection(sb, deps);
 
         sb.emptyLine();
 
-        this.buildSection(sb, ['org.apache.ignite']);
+        this.buildSection(sb, [artifactGrp]);
 
         sb.endBlock('</project>');
 


[ignite] 27/31: GG-17467: Log finish rebuilding all indexes

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch gg-19225
in repository https://gitbox.apache.org/repos/asf/ignite.git

commit 3cb1c9a391b5c57544f87d2d7f980278175b05df
Author: denis-chudov <dc...@gridgain.com>
AuthorDate: Tue Jun 4 13:20:04 2019 +0300

    GG-17467: Log finish rebuilding all indexes
    
    (cherry picked from bfc03896fc656e9a51f0efcecdf2158aea71d0ee)
---
 .../GridCacheDatabaseSharedManager.java            |  11 +
 .../internal/util/GridCountDownCallback.java       | 113 +++++++++++
 .../persistence/CleanupRestoredCachesSlowTest.java |  66 +-----
 .../internal/util/GridCountDownCallbackTest.java   |  70 +++++++
 .../testframework/CallbackExecutorLogListener.java |  54 +++++
 .../testframework/MessageOrderLogListener.java     | 225 +++++++++++++++++++++
 .../testframework/MessageOrderLogListenerTest.java |  99 +++++++++
 .../ignite/testsuites/IgniteBasicTestSuite.java    |  11 +-
 .../ignite/testsuites/IgniteUtilSelfTestSuite.java |   9 +-
 .../persistence/RebuildIndexLogMessageTest.java    | 210 +++++++++++++++++++
 .../IgniteCacheWithIndexingTestSuite.java          |   9 +-
 11 files changed, 811 insertions(+), 66 deletions(-)

diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheDatabaseSharedManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheDatabaseSharedManager.java
index bf56c29..9a926d2 100755
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheDatabaseSharedManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheDatabaseSharedManager.java
@@ -144,6 +144,7 @@ import org.apache.ignite.internal.processors.cache.persistence.wal.FileWALPointe
 import org.apache.ignite.internal.processors.cache.persistence.wal.crc.IgniteDataIntegrityViolationException;
 import org.apache.ignite.internal.processors.port.GridPortRecord;
 import org.apache.ignite.internal.processors.query.GridQueryProcessor;
+import org.apache.ignite.internal.util.GridCountDownCallback;
 import org.apache.ignite.internal.util.GridMultiCollectionWrapper;
 import org.apache.ignite.internal.util.GridReadOnlyArrayView;
 import org.apache.ignite.internal.util.IgniteUtils;
@@ -1445,6 +1446,12 @@ public class GridCacheDatabaseSharedManager extends IgniteCacheDatabaseSharedMan
         GridQueryProcessor qryProc = cctx.kernalContext().query();
 
         if (qryProc.moduleEnabled()) {
+            GridCountDownCallback rebuildIndexesCompleteCntr = new GridCountDownCallback(
+                cctx.cacheContexts().size(),
+                () -> log().info("Indexes rebuilding completed for all caches."),
+                1  //need at least 1 index rebuilded to print message about rebuilding completion
+            );
+
             for (final GridCacheContext cacheCtx : (Collection<GridCacheContext>)cctx.cacheContexts()) {
                 if (cacheCtx.startTopologyVersion().equals(fut.initialVersion())) {
                     final int cacheId = cacheCtx.cacheId();
@@ -1470,6 +1477,8 @@ public class GridCacheDatabaseSharedManager extends IgniteCacheDatabaseSharedMan
                                     log().info("Finished indexes rebuilding for cache [name=" + ccfg.getName()
                                         + ", grpName=" + ccfg.getGroupName() + ']');
                                 }
+
+                                rebuildIndexesCompleteCntr.countDown(true);
                             }
                         });
                     }
@@ -1478,6 +1487,8 @@ public class GridCacheDatabaseSharedManager extends IgniteCacheDatabaseSharedMan
                             idxRebuildFuts.remove(cacheId, usrFut);
 
                             usrFut.onDone();
+
+                            rebuildIndexesCompleteCntr.countDown(false);
                         }
                     }
                 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/GridCountDownCallback.java b/modules/core/src/main/java/org/apache/ignite/internal/util/GridCountDownCallback.java
new file mode 100644
index 0000000..15ce491
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/GridCountDownCallback.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ignite.internal.util;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Allows to execute callback when a set of operations will be completed. Also has an execution counter,
+ * which allows to block callback execution in case if it is below given threshold. By default, threshold
+ * is 0 and nothing blocks callback execution.
+ *
+ * <p>
+ * <b>Sample usage:</b>:
+ * <pre>{@code
+ *     GridCountDownCallback countDownCb = new GridCountDownCallback(
+ *         n,                     //internal counter is initiated with n
+ *         () -> doSomething()    //callback
+ *     );
+ *
+ *     //each call of countDown() decrements internal counter
+ *     //doSomething() will be executed after counter reaches 0
+ *     for (int i = 0; i < n; i++)
+ *         new Thread(() -> countDownCb.countDown()).start();
+ * }</pre>
+ *
+ * <p>
+ * <b>Usage with execution threshold:</b>:
+ * <pre>{@code
+ *     GridCountDownCallback countDownCb = new GridCountDownCallback(
+ *         n,                     //internal counter is initiated with n
+ *         () -> doSomething(),   //callback
+ *         n/2                    //execution threshold is initiated with n/2
+ *     );
+ *
+ *     //a half of calls of countDown() increase execution counter, so it reaches threshold and callback executes.
+ *     //doSomething() will be executed after n threads will perform countDown()
+ *     for (int i = 0; i < n; i++)
+ *         new Thread(() -> countDownCb.countDown(n % 2 == 0)).start();
+ * }</pre>
+ */
+public class GridCountDownCallback {
+    /** */
+    private final AtomicInteger cntr;
+
+    /** */
+    private final int executionThreshold;
+
+    /** */
+    private final AtomicInteger executionCntr = new AtomicInteger(0);
+
+    /** */
+    private final Runnable cb;
+
+    /**
+     * Constructor.
+     *
+     * @param initCnt count of invocations of {@link #countDown}.
+     * @param cb callback which will be executed after <code>initialCount</code>
+     * invocations of {@link #countDown}.
+     * @param executionThreshold minimal count of really performed operations to execute callback.
+     */
+    public GridCountDownCallback(int initCnt, Runnable cb, int executionThreshold) {
+        cntr = new AtomicInteger(initCnt);
+
+        this.executionThreshold = executionThreshold;
+
+        this.cb = cb;
+    }
+
+    /**
+     * Constructor. Execution threshold is set to 0.
+     *
+     * @param initCnt count of invocations of {@link #countDown}.
+     * @param cb callback which will be executed after <code>initialCount</code>
+     * invocations of {@link #countDown}.
+     */
+    public GridCountDownCallback(int initCnt, Runnable cb) {
+        this(initCnt, cb, 0);
+    }
+
+    /**
+     * Decrements the internal counter. If counter becomes 0, callback will be executed.
+     *
+     * @param doIncreaseExecutionCounter whether to increase execution counter
+     */
+    public void countDown(boolean doIncreaseExecutionCounter) {
+        if (doIncreaseExecutionCounter)
+            executionCntr.incrementAndGet();
+
+        if (cntr.decrementAndGet() == 0 && executionCntr.get() >= executionThreshold)
+            cb.run();
+    }
+
+    /**
+     * Decrements the internal counter. If counter becomes 0, callback will be executed.
+     */
+    public void countDown() {
+        countDown(true);
+    }
+}
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/CleanupRestoredCachesSlowTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/CleanupRestoredCachesSlowTest.java
index 8cc2ddb..944293e 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/CleanupRestoredCachesSlowTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/CleanupRestoredCachesSlowTest.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
@@ -19,10 +19,6 @@ import java.io.File;
 import java.io.IOException;
 import java.io.Serializable;
 import java.nio.file.OpenOption;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.LinkedHashSet;
-import java.util.List;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
 import org.apache.ignite.Ignite;
@@ -42,6 +38,7 @@ import org.apache.ignite.internal.processors.cache.persistence.file.FilePageStor
 import org.apache.ignite.logger.NullLogger;
 import org.apache.ignite.testframework.ListeningTestLogger;
 import org.apache.ignite.testframework.LogListener;
+import org.apache.ignite.testframework.MessageOrderLogListener;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
 import org.junit.Test;
 
@@ -108,60 +105,13 @@ public class CleanupRestoredCachesSlowTest extends GridCommonAbstractTest implem
         }
     }
 
-    /**
-     * Checks the order of the messages in the log.
-     */
-    private static class MessageOrderLogListener extends LogListener {
-        /** */
-        private final LinkedHashSet<String> matchedMessages = new LinkedHashSet<>();
-
-        /** */
-        private final List<String> matchesList;
-
-        /** */
-        private final boolean doAddDuplicates;
-
-        /** */
-        MessageOrderLogListener(List<String> matchesList, boolean doAddDuplicates) {
-            this.matchesList = matchesList;
-
-            this.doAddDuplicates = doAddDuplicates;
-        }
-
-        /** {@inheritDoc} */
-        @Override public boolean check() {
-            List<String> list = new ArrayList<>(matchedMessages);
-
-            return list.equals(matchesList);
-        }
-
-        /** {@inheritDoc} */
-        @Override public void reset() {
-            matchedMessages.clear();
-        }
-
-        /** {@inheritDoc} */
-        @Override public void accept(String s) {
-            for (String match : matchesList)
-                if (s.matches(match)) {
-                    if (doAddDuplicates || !matchedMessages.contains(match))
-                        matchedMessages.add(match);
-
-                    break;
-                }
-        }
-    }
-
     /** */
     private static final String CACHE_NAME = "myCache";
 
     /** */
     private final LogListener logLsnr = new MessageOrderLogListener(
-        Arrays.asList(
-            "Cache stores cleanup started asynchronously",
-            "Cleanup cache stores .*? cleanFiles=true\\]"
-        ),
-        false
+        "Cache stores cleanup started asynchronously",
+        "Cleanup cache stores .*? cleanFiles=true\\]"
     );
 
     /** {@inheritDoc} */
@@ -193,6 +143,8 @@ public class CleanupRestoredCachesSlowTest extends GridCommonAbstractTest implem
 
     /** {@inheritDoc} */
     @Override protected void beforeTest() throws Exception {
+        super.beforeTest();
+
         cleanPersistenceDir();
     }
 
@@ -201,6 +153,8 @@ public class CleanupRestoredCachesSlowTest extends GridCommonAbstractTest implem
         stopAllGrids();
 
         cleanPersistenceDir();
+
+        super.afterTest();
     }
 
     /**
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/util/GridCountDownCallbackTest.java b/modules/core/src/test/java/org/apache/ignite/internal/util/GridCountDownCallbackTest.java
new file mode 100644
index 0000000..f5485d7
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/util/GridCountDownCallbackTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ignite.internal.util;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import org.junit.Test;
+
+import static org.junit.Assert.assertTrue;
+
+/**
+ *
+ */
+public class GridCountDownCallbackTest {
+    /** */
+    @Test
+    public void testCountDownCallback() throws InterruptedException {
+        AtomicInteger cntr = new AtomicInteger(0);
+        AtomicInteger performedCntr = new AtomicInteger(0);
+
+        AtomicBoolean res = new AtomicBoolean();
+
+        int countsTillCb = 30;
+
+        GridCountDownCallback cb = new GridCountDownCallback(
+            countsTillCb,
+            () -> res.set(cntr.get() == countsTillCb && performedCntr.get() == countsTillCb / 5),
+            0
+        );
+
+        ExecutorService es = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
+
+        for (int i = 1; i < 100; i++) {
+            final int fi = i;
+
+            es.submit(() -> {
+                synchronized (es) {
+                    cntr.incrementAndGet();
+
+                    if (fi % 5 == 0)
+                        performedCntr.incrementAndGet();
+
+                    cb.countDown(fi % 5 == 0);
+                }
+            });
+        }
+
+        es.shutdown();
+
+        es.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
+
+        assertTrue(res.get());
+    }
+}
diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/CallbackExecutorLogListener.java b/modules/core/src/test/java/org/apache/ignite/testframework/CallbackExecutorLogListener.java
new file mode 100644
index 0000000..c7e78c9
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/testframework/CallbackExecutorLogListener.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.testframework;
+
+/**
+ * Allows to listen a log and run the callback when the message that matches the regexp is detected.
+ */
+public class CallbackExecutorLogListener extends LogListener {
+    /** */
+    private final String expectedMessage;
+
+    /** */
+    private final Runnable cb;
+
+    /**
+     * Default constructor.
+     *
+     * @param expectedMessage regexp for message that triggers the callback
+     * @param cb callback
+     */
+    public CallbackExecutorLogListener(String expectedMessage, Runnable cb) {
+        this.expectedMessage = expectedMessage;
+        this.cb = cb;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean check() {
+        return true;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void reset() {
+        /* No-op */
+    }
+
+    /** {@inheritDoc} */
+    @Override public void accept(String s) {
+        if (s.matches(expectedMessage))
+            cb.run();
+    }
+}
diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/MessageOrderLogListener.java b/modules/core/src/test/java/org/apache/ignite/testframework/MessageOrderLogListener.java
new file mode 100644
index 0000000..45d8b27
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/testframework/MessageOrderLogListener.java
@@ -0,0 +1,225 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.testframework;
+
+import java.util.Iterator;
+import org.apache.ignite.internal.util.GridConcurrentLinkedHashSet;
+
+/**
+ * This log listener allows to check the order or presence of messages in log. Messages are matched via regexps.
+ * Also allows to unify various messages into groups to check messages only within group.
+ * Groups can be ordered or non-ordered. In non-ordered groups, message order will not be checked, only
+ * will be checked the presence of given messages.
+ * <p>
+ * Message groups can also be unified into higher-level groups, that can also be ordered or non-ordered and in general
+ * work like message groups.
+ */
+public class MessageOrderLogListener extends LogListener {
+    /** */
+    private final MessageGroup matchesGrp;
+
+    /**
+     * Constructor accepting array of messages.
+     *
+     * @param messages array of messages that will be unified into ordered group.
+     */
+    public MessageOrderLogListener(String... messages) {
+        this(new MessageGroup(true) {{
+            for (String m : messages)
+                add(m);
+        }});
+    }
+
+    /**
+     * Constructor accepting message group
+     *
+     * @param matchesGrp group
+     */
+    public MessageOrderLogListener(MessageGroup matchesGrp) {
+        this.matchesGrp = matchesGrp;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean check() {
+        return matchesGrp.check();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void reset() {
+        matchesGrp.reset();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void accept(String s) {
+        matchesGrp.accept(s);
+    }
+
+    /**
+     * Allows to unify messages into groups and groups into higher-level groups.
+     */
+    public static class MessageGroup extends LogListener {
+        /** */
+        private final boolean ordered;
+
+        /** */
+        private final String containedStr;
+
+        /** */
+        private final GridConcurrentLinkedHashSet<MessageGroup> groups;
+
+        /** */
+        private final GridConcurrentLinkedHashSet<MessageGroup> matched = new GridConcurrentLinkedHashSet<>();
+
+        /** */
+        private volatile boolean checked;
+
+        /** */
+        private volatile String actualStr;
+
+        /** */
+        private volatile int lastAcceptedIdx;
+
+        /**
+         * Default constructor.
+         *
+         * @param ordered whether to check order of messages in this group.
+         */
+        public MessageGroup(boolean ordered) {
+            this(ordered, null);
+        }
+
+        /** */
+        private MessageGroup(boolean ordered, String s) {
+            this.ordered = ordered;
+
+            containedStr = s;
+
+            groups = s == null ? new GridConcurrentLinkedHashSet<>() : null;
+        }
+
+        /**
+         * Adds a message regexp to group.
+         *
+         * @param s message regexp
+         * @return this for chaining
+         */
+        public MessageGroup add(String s) {
+            return add(new MessageGroup(false, s));
+        }
+
+        /**
+         * Adds another message group to this group.
+         *
+         * @param grp group
+         * @return this for chaining
+         */
+        public MessageGroup add(MessageGroup grp) {
+            groups.add(grp);
+
+            return this;
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean check() {
+            if (checked)
+                return true;
+
+            if (groups != null) {
+                for (MessageGroup group : groups) {
+                    if (!matched.contains(group) || !group.check())
+                        return false;
+                }
+
+                return true;
+            }
+
+            return false;
+        }
+
+        /** {@inheritDoc} */
+        @Override public void reset() {
+            checked = false;
+
+            actualStr = null;
+
+            lastAcceptedIdx = 0;
+
+            if (groups != null) {
+                for (MessageGroup group : groups)
+                    group.reset();
+            }
+
+            for (Iterator<MessageGroup> iter = matched.iterator(); iter.hasNext();) {
+                iter.next();
+
+                iter.remove();
+            }
+        }
+
+        /** {@inheritDoc} */
+        @Override public void accept(String s) {
+            internalAccept(s);
+        }
+
+        /**
+         * Tries to accept given string. If fails, tries to accept it using internal message groups.
+         *
+         * @param s message
+         * @return whether accepted
+         */
+        private boolean internalAccept(String s) {
+            if (checked)
+                return false;
+            else if (containedStr != null && s.matches(containedStr)) {
+                checked = true;
+
+                actualStr = s;
+
+                return true;
+            }
+            else {
+                if (groups != null) {
+                    int i = 0;
+
+                    for (MessageGroup group : groups) {
+                        if (i < lastAcceptedIdx && ordered) {
+                            i++;
+
+                            continue;
+                        }
+
+                        if (group.internalAccept(s)) {
+                            matched.add(group);
+
+                            lastAcceptedIdx = i;
+
+                            return true;
+                        }
+
+                        i++;
+                    }
+                }
+
+                return false;
+            }
+        }
+
+        /** */
+        public String getActualStr() {
+            return actualStr;
+        }
+    }
+}
diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/MessageOrderLogListenerTest.java b/modules/core/src/test/java/org/apache/ignite/testframework/MessageOrderLogListenerTest.java
new file mode 100644
index 0000000..8b90289
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/testframework/MessageOrderLogListenerTest.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.testframework;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Tests for {@link MessageOrderLogListener}
+ */
+public class MessageOrderLogListenerTest {
+    /** */
+    @Test
+    public void testMessageOrderLogListener() {
+        MessageOrderLogListener lsnr = new MessageOrderLogListener("a", "b");
+
+        lsnr.accept("a");
+        lsnr.accept("b");
+
+        assertTrue(lsnr.check());
+
+        lsnr.reset();
+
+        lsnr.accept("b");
+        lsnr.accept("a");
+
+        assertFalse(lsnr.check());
+
+        lsnr.reset();
+
+        lsnr.accept("b");
+        lsnr.accept("a");
+        lsnr.accept("b");
+
+        assertFalse(lsnr.check());
+
+        lsnr = new MessageOrderLogListener(new MessageOrderLogListener.MessageGroup(true)
+            .add(new MessageOrderLogListener.MessageGroup(false).add("a").add("b"))
+            .add(new MessageOrderLogListener.MessageGroup(true).add("c").add("d"))
+        );
+
+        lsnr.accept("b");
+        lsnr.accept("a");
+        lsnr.accept("c");
+        lsnr.accept("d");
+
+        assertTrue(lsnr.check());
+
+        lsnr.reset();
+
+        lsnr.accept("b");
+        lsnr.accept("a");
+        lsnr.accept("d");
+        lsnr.accept("c");
+
+        assertFalse(lsnr.check());
+
+        lsnr.reset();
+
+        lsnr.accept("b");
+        lsnr.accept("c");
+        lsnr.accept("a");
+        lsnr.accept("d");
+
+        assertFalse(lsnr.check());
+
+        lsnr = new MessageOrderLogListener(new MessageOrderLogListener.MessageGroup(true)
+            .add(
+                new MessageOrderLogListener.MessageGroup(false)
+                    .add(new MessageOrderLogListener.MessageGroup(true).add("a").add("b"))
+                    .add(new MessageOrderLogListener.MessageGroup(true).add("c").add("d"))
+            )
+            .add("e")
+        );
+
+        lsnr.accept("c");
+        lsnr.accept("d");
+        lsnr.accept("a");
+        lsnr.accept("b");
+        lsnr.accept("e");
+
+        assertTrue(lsnr.check());
+    }
+}
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicTestSuite.java
index 1ba0e6e..3d1ae50 100644
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicTestSuite.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicTestSuite.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
@@ -92,6 +92,7 @@ import org.apache.ignite.plugin.PluginNodeValidationTest;
 import org.apache.ignite.plugin.security.SecurityPermissionSetBuilderTest;
 import org.apache.ignite.spi.GridSpiLocalHostInjectionTest;
 import org.apache.ignite.startup.properties.NotStringSystemPropertyTest;
+import org.apache.ignite.testframework.MessageOrderLogListenerTest;
 import org.apache.ignite.testframework.GridTestUtils;
 import org.apache.ignite.testframework.test.ConfigVariationsTestSuiteBuilderTest;
 import org.apache.ignite.testframework.test.ListeningTestLoggerTest;
@@ -230,6 +231,8 @@ public class IgniteBasicTestSuite {
 
         suite.addTest(new JUnit4TestAdapter(RebalanceWithDifferentThreadPoolSizeTest.class));
 
+        suite.addTest(new JUnit4TestAdapter(MessageOrderLogListenerTest.class));
+
         suite.addTest(new JUnit4TestAdapter(ListeningTestLoggerTest.class));
 
         suite.addTest(new JUnit4TestAdapter(PluginNodeValidationTest.class));
@@ -238,4 +241,4 @@ public class IgniteBasicTestSuite {
 
         return suite;
     }
-}
\ No newline at end of file
+}
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteUtilSelfTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteUtilSelfTestSuite.java
index 0ac60e8..2b0295c 100644
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteUtilSelfTestSuite.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteUtilSelfTestSuite.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
@@ -24,6 +24,7 @@ import org.apache.ignite.internal.commandline.CommandHandlerParsingTest;
 import org.apache.ignite.internal.pagemem.impl.PageIdUtilsSelfTest;
 import org.apache.ignite.internal.processors.cache.GridCacheUtilsSelfTest;
 import org.apache.ignite.internal.util.GridArraysSelfTest;
+import org.apache.ignite.internal.util.GridCountDownCallbackTest;
 import org.apache.ignite.internal.util.IgniteDevOnlyLogTest;
 import org.apache.ignite.internal.util.IgniteExceptionRegistrySelfTest;
 import org.apache.ignite.internal.util.IgniteUtilsSelfTest;
@@ -144,6 +145,8 @@ public class IgniteUtilSelfTestSuite {
         // control.sh
         suite.addTest(new JUnit4TestAdapter(CommandHandlerParsingTest.class));
 
+        suite.addTest(new JUnit4TestAdapter(GridCountDownCallbackTest.class));
+
         return suite;
     }
 }
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/persistence/RebuildIndexLogMessageTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/persistence/RebuildIndexLogMessageTest.java
new file mode 100644
index 0000000..c37a7a2
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/persistence/RebuildIndexLogMessageTest.java
@@ -0,0 +1,210 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.persistence;
+
+import java.io.File;
+import java.io.Serializable;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.affinity.rendezvous.RendezvousAffinityFunction;
+import org.apache.ignite.cache.query.annotations.QuerySqlField;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.DataRegionConfiguration;
+import org.apache.ignite.configuration.DataStorageConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.processors.cache.IgniteInternalCache;
+import org.apache.ignite.internal.processors.cache.persistence.file.FilePageStoreManager;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.testframework.CallbackExecutorLogListener;
+import org.apache.ignite.testframework.ListeningTestLogger;
+import org.apache.ignite.testframework.LogListener;
+import org.apache.ignite.testframework.MessageOrderLogListener;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.junit.Test;
+
+/**
+ *
+ */
+public class RebuildIndexLogMessageTest extends GridCommonAbstractTest implements Serializable {
+    /** */
+    private static final String CACHE_NAME_A = "testCacheA";
+
+    /** */
+    private static final String CACHE_NAME_B = "testCacheB";
+
+    /** */
+    private final CountDownLatch checkLatch = new CountDownLatch(1);
+
+    /** */
+    private final LogListener logLsnr = new MessageOrderLogListener(
+        new MessageOrderLogListener.MessageGroup(true)
+            //message group for all caches
+            .add(
+                new MessageOrderLogListener.MessageGroup(false)
+                    .add(
+                        //message group for testCacheA
+                        new MessageOrderLogListener.MessageGroup(true)
+                            .add("Started indexes rebuilding for cache \\[name=testCacheA.*")
+                            .add("((Finished indexes rebuilding)|(Failed to rebuild indexes)) for cache " +
+                                "\\[name=testCacheA.*")
+                    )
+                    .add(
+                        //message group for testCacheB
+                        new MessageOrderLogListener.MessageGroup(true)
+                            .add("Started indexes rebuilding for cache \\[name=testCacheB.*")
+                            .add("((Finished indexes rebuilding)|(Failed to rebuild indexes)) for cache " +
+                                "\\[name=testCacheB.*")
+                    )
+            )
+            //message that appears after rebuilding is completed for all caches
+            .add("Indexes rebuilding completed for all caches.")
+    );
+
+    /** */
+    private final LogListener latchLsnr =
+        new CallbackExecutorLogListener("Indexes rebuilding completed for all caches.", checkLatch::countDown);
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
+        ListeningTestLogger testLog =
+            new ListeningTestLogger(false, super.getConfiguration(igniteInstanceName).getGridLogger());
+
+        testLog.registerListener(logLsnr);
+        testLog.registerListener(latchLsnr);
+
+        return super.getConfiguration(igniteInstanceName)
+            .setGridLogger(testLog)
+            .setDataStorageConfiguration(
+                new DataStorageConfiguration()
+                    .setDefaultDataRegionConfiguration(
+                        new DataRegionConfiguration()
+                            .setPersistenceEnabled(true)
+                    )
+            )
+            .setCacheConfiguration(
+                new CacheConfiguration<>()
+                    .setName(CACHE_NAME_A)
+                    .setBackups(0)
+                    .setIndexedTypes(Integer.class, Person.class)
+                    .setAffinity(new RendezvousAffinityFunction(false, 8)),
+                new CacheConfiguration<>()
+                    .setName(CACHE_NAME_B)
+                    .setBackups(0)
+                    .setIndexedTypes(Integer.class, Person.class)
+                    .setAffinity(new RendezvousAffinityFunction(false, 8))
+            );
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTest() throws Exception {
+        super.beforeTest();
+
+        cleanPersistenceDir();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        stopAllGrids();
+
+        cleanPersistenceDir();
+
+        super.afterTest();
+    }
+
+    /** */
+    @Test
+    public void testRebuildIndexLogMessage() throws Exception {
+        IgniteEx ignite = startGrids(1);
+
+        String gridName = ignite.name();
+
+        ignite.cluster().active(true);
+
+        IgniteCache<Integer, Person> cacheA = ignite.getOrCreateCache(CACHE_NAME_A);
+        IgniteCache<Integer, Person> cacheB = ignite.getOrCreateCache(CACHE_NAME_B);
+
+        IgniteInternalCache<Integer, Person> cacheAEx = ignite.cachex(CACHE_NAME_A);
+        IgniteInternalCache<Integer, Person> cacheBEx = ignite.cachex(CACHE_NAME_B);
+
+        for (int i = 0; i < 100; i++)
+            cacheA.put(i, new Person(i, i));
+
+        for (int i = 0; i < 100; i++)
+            cacheB.put(i, new Person(i, i));
+
+        forceCheckpoint();
+
+        File cacheAWorkDir = ((FilePageStoreManager)cacheAEx.context().shared().pageStore())
+            .cacheWorkDir(cacheAEx.configuration());
+        File cacheBWorkDir = ((FilePageStoreManager)cacheBEx.context().shared().pageStore())
+            .cacheWorkDir(cacheBEx.configuration());
+
+        File idxPathA = cacheAWorkDir.toPath().resolve("index.bin").toFile();
+        File idxPathB = cacheBWorkDir.toPath().resolve("index.bin").toFile();
+
+        stopAllGrids();
+
+        assertTrue(U.delete(idxPathA));
+        assertTrue(U.delete(idxPathB));
+
+        ignite = startGrid(getConfiguration(gridName));
+
+        ignite.cluster().active(true);
+
+        cacheA = ignite.getOrCreateCache(CACHE_NAME_A);
+        cacheB = ignite.getOrCreateCache(CACHE_NAME_B);
+
+        cacheA.put(1000, new Person(1000, 1));
+        cacheB.put(1000, new Person(1000, 1));
+
+        checkLatch.await(60, TimeUnit.SECONDS);
+
+        if (checkLatch.getCount() > 0)
+            throw new TimeoutException("Test timed out: cannot detect log message about completion of indexes rebuilding");
+
+        assertTrue(logLsnr.check());
+    }
+
+    /** */
+    private static class Person implements Serializable {
+        /** */
+        @QuerySqlField(index = true)
+        private int id;
+
+        /** */
+        @QuerySqlField(index = true)
+        private int age;
+
+        /**
+         * @param id Id.
+         * @param age Age.
+         */
+        Person(int id, int age) {
+            this.id = id;
+            this.age = age;
+        }
+
+        /**
+         * @return Age/
+         */
+        public int age() {
+            return age;
+        }
+    }
+}
diff --git a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheWithIndexingTestSuite.java b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheWithIndexingTestSuite.java
index a4ddd97..a63b173 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheWithIndexingTestSuite.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheWithIndexingTestSuite.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
@@ -37,6 +37,7 @@ import org.apache.ignite.internal.processors.cache.IgniteCacheConfigurationPrimi
 import org.apache.ignite.internal.processors.cache.IgniteCacheGroupsSqlTest;
 import org.apache.ignite.internal.processors.cache.IgniteCacheStarvationOnRebalanceTest;
 import org.apache.ignite.internal.processors.cache.IgniteClientReconnectQueriesTest;
+import org.apache.ignite.internal.processors.cache.persistence.RebuildIndexLogMessageTest;
 import org.apache.ignite.internal.processors.cache.ttl.CacheTtlAtomicLocalSelfTest;
 import org.apache.ignite.internal.processors.cache.ttl.CacheTtlAtomicPartitionedSelfTest;
 import org.apache.ignite.internal.processors.cache.ttl.CacheTtlTransactionalLocalSelfTest;
@@ -95,6 +96,8 @@ public class IgniteCacheWithIndexingTestSuite {
 
         suite.addTest(new JUnit4TestAdapter(ClusterReadOnlyModeSqlTest.class));
 
+        suite.addTest(new JUnit4TestAdapter(RebuildIndexLogMessageTest.class));
+
         return suite;
     }
 }


[ignite] 22/31: GG-19187 Web Console: Fixed selection time units on "Refresh rate" popover.

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch gg-19225
in repository https://gitbox.apache.org/repos/asf/ignite.git

commit 04564b88defe8811903ac65f448e467b908cc5b3
Author: Alexey Kuznetsov <ak...@apache.org>
AuthorDate: Sun Jun 2 00:26:46 2019 +0700

    GG-19187 Web Console: Fixed selection time units on "Refresh rate" popover.
    
    (cherry picked from commit 6502b6fbe3bfbe057a918a3160f8a76046eefb7b)
---
 .../components/page-queries/components/queries-notebook/template.tpl.pug | 1 -
 1 file changed, 1 deletion(-)

diff --git a/modules/web-console/frontend/app/components/page-queries/components/queries-notebook/template.tpl.pug b/modules/web-console/frontend/app/components/page-queries/components/queries-notebook/template.tpl.pug
index ea7108b..f2d85d47 100644
--- a/modules/web-console/frontend/app/components/page-queries/components/queries-notebook/template.tpl.pug
+++ b/modules/web-console/frontend/app/components/page-queries/components/queries-notebook/template.tpl.pug
@@ -101,7 +101,6 @@ mixin query-settings
                 bs-popover
                 data-template-url='{{ $ctrl.paragraphRateTemplateUrl }}'
                 data-placement='bottom-right'
-                data-auto-close='1'
                 data-trigger='click'
             )
                 .btn-ignite(


[ignite] 13/31: GG-19159 GridVersionSelfTest#testVersions hangs

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch gg-19225
in repository https://gitbox.apache.org/repos/asf/ignite.git

commit 7bb8f94f9bae4b9b231024ef07367135f95097db
Author: Eduard Shangareev <es...@gridgain.com>
AuthorDate: Fri May 31 03:17:35 2019 +0300

    GG-19159 GridVersionSelfTest#testVersions hangs
---
 .../ignite/internal/processors/cluster/HttpIgniteUpdatesChecker.java | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cluster/HttpIgniteUpdatesChecker.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cluster/HttpIgniteUpdatesChecker.java
index 6ba65f0..730f9f2 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cluster/HttpIgniteUpdatesChecker.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cluster/HttpIgniteUpdatesChecker.java
@@ -55,9 +55,10 @@ public class HttpIgniteUpdatesChecker {
         conn.setDoOutput(true);
         conn.setRequestProperty("Accept-Charset", charset);
         conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=" + charset);
+        conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.95 Safari/537.11");
 
-        conn.setConnectTimeout(3000);
-        conn.setReadTimeout(3000);
+        conn.setConnectTimeout(5000);
+        conn.setReadTimeout(5000);
 
         try (OutputStream os = conn.getOutputStream()) {
             os.write(updateReq.getBytes(charset));


[ignite] 03/31: GG-18877 additional heartbeat to prevent FailureProcessor from treating tcp-comm-worker as blocked

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch gg-19225
in repository https://gitbox.apache.org/repos/asf/ignite.git

commit 4cc49e4a1f30e6c64d9aac22c81db7ce7794422b
Author: Sergey Chugunov <se...@gmail.com>
AuthorDate: Wed May 29 18:34:40 2019 +0300

    GG-18877 additional heartbeat to prevent FailureProcessor from treating tcp-comm-worker as blocked
    
    Signed-off-by: Dmitriy Govorukhin <dm...@gmail.com>
    
    (cherry-picked from commit #8905c3f)
---
 .../client/suite/IgniteClientTestSuite.java        |   3 +
 .../spi/communication/tcp/TcpCommunicationSpi.java |   5 +
 .../ignite/internal/IgniteClientFailuresTest.java  | 160 +++++++++++++++++++++
 3 files changed, 168 insertions(+)

diff --git a/modules/clients/src/test/java/org/apache/ignite/internal/client/suite/IgniteClientTestSuite.java b/modules/clients/src/test/java/org/apache/ignite/internal/client/suite/IgniteClientTestSuite.java
index e0c3249..075e61c 100644
--- a/modules/clients/src/test/java/org/apache/ignite/internal/client/suite/IgniteClientTestSuite.java
+++ b/modules/clients/src/test/java/org/apache/ignite/internal/client/suite/IgniteClientTestSuite.java
@@ -18,6 +18,7 @@ package org.apache.ignite.internal.client.suite;
 
 import junit.framework.JUnit4TestAdapter;
 import junit.framework.TestSuite;
+import org.apache.ignite.internal.IgniteClientFailuresTest;
 import org.apache.ignite.internal.TaskEventSubjectIdSelfTest;
 import org.apache.ignite.internal.client.ClientDefaultCacheSelfTest;
 import org.apache.ignite.internal.client.ClientReconnectionSelfTest;
@@ -171,6 +172,8 @@ public class IgniteClientTestSuite extends TestSuite {
         // SSL params.
             suite.addTest(new JUnit4TestAdapter(ClientSslParametersTest.class));
 
+            suite.addTest(new JUnit4TestAdapter(IgniteClientFailuresTest.class));
+
         return suite;
     }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/spi/communication/tcp/TcpCommunicationSpi.java b/modules/core/src/main/java/org/apache/ignite/spi/communication/tcp/TcpCommunicationSpi.java
index 0776a5d..2a9fb9a 100755
--- a/modules/core/src/main/java/org/apache/ignite/spi/communication/tcp/TcpCommunicationSpi.java
+++ b/modules/core/src/main/java/org/apache/ignite/spi/communication/tcp/TcpCommunicationSpi.java
@@ -3551,6 +3551,11 @@ public class TcpCommunicationSpi extends IgniteSpiAdapter implements Communicati
                         break;
                     }
                 }
+
+                CommunicationWorker commWorker0 = commWorker;
+
+                if (commWorker0 != null && commWorker0.runner() == Thread.currentThread())
+                    commWorker0.updateHeartbeat();
             }
 
             if (client != null)
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/IgniteClientFailuresTest.java b/modules/core/src/test/java/org/apache/ignite/internal/IgniteClientFailuresTest.java
new file mode 100644
index 0000000..82522ae
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/IgniteClientFailuresTest.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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;
+
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.cluster.IgniteClusterEx;
+import org.apache.ignite.internal.managers.GridManagerAdapter;
+import org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi;
+import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
+import org.apache.ignite.testframework.GridStringLogger;
+import org.apache.ignite.testframework.GridTestUtils;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.apache.ignite.testframework.junits.logger.GridTestLog4jLogger;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ *
+ */
+public class IgniteClientFailuresTest extends GridCommonAbstractTest {
+    /** */
+    private boolean clientMode;
+
+    /** */
+    private GridStringLogger inMemoryLog;
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
+
+        cfg.setClientMode(clientMode);
+
+        if (!clientMode) {
+            cfg.setClientFailureDetectionTimeout(10_000);
+
+            cfg.setSystemWorkerBlockedTimeout(5_000);
+
+            cfg.setGridLogger(inMemoryLog);
+        }
+
+        return cfg;
+    }
+
+    /** */
+    @Before
+    public void setupClientFailuresTest() {
+        stopAllGrids();
+    }
+
+    /** */
+    @After
+    public void tearDownClientFailuresTest() {
+        stopAllGrids();
+    }
+
+    /**
+     * Test verifies that FailureProcessor doesn't treat tcp-comm-worker thread as blocked when
+     * the thread handles situation of failed client node and thus doesn't print full thread dump into logs.
+     *
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testNoMessagesFromFailureProcessor() throws Exception {
+        inMemoryLog = new GridStringLogger(false, new GridTestLog4jLogger());
+
+        inMemoryLog.logLength(1024 * 1024);
+
+        IgniteEx srv = startGrid(0);
+
+        clientMode = true;
+
+        IgniteEx client00 = startGrid("client00");
+
+        client00.getOrCreateCache(new CacheConfiguration<>("cache0"));
+
+        breakClient(client00);
+
+        boolean waitRes = GridTestUtils.waitForCondition(() -> {
+            IgniteClusterEx cl = srv.cluster();
+
+            return (cl.topology(cl.topologyVersion()).size() == 1);
+        }, 30_000);
+
+        assertTrue(waitRes);
+
+        assertFalse(inMemoryLog.toString().contains("name=tcp-comm-worker"));
+    }
+
+    /**
+     * Test verifies that when client node failed but not yet cleaned up from topology (because {@link IgniteConfiguration#clientFailureDetectionTimeout} has not been reached yet)
+     * it doesn't affect new client connected from the same address.
+     *
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testFailedClientLeavesTopologyAfterTimeout() throws Exception {
+        IgniteEx srv0 = startGrid(0);
+
+        clientMode = true;
+
+        IgniteEx client00 = startGrid("client00");
+
+        Thread.sleep(5_000);
+
+        client00.getOrCreateCache(new CacheConfiguration<>("cache0"));
+
+        breakClient(client00);
+
+        final IgniteClusterEx cl = srv0.cluster();
+
+        assertEquals(2, cl.topology(cl.topologyVersion()).size());
+
+        IgniteEx client01 = startGrid("client01");
+
+        assertEquals(3, cl.topology(cl.topologyVersion()).size());
+
+        boolean waitRes = GridTestUtils.waitForCondition(() -> (cl.topology(cl.topologyVersion()).size() == 2),
+            20_000);
+
+        checkCacheOperations(client01.cache("cache0"));
+
+        assertTrue(waitRes);
+    }
+
+    /** */
+    private void checkCacheOperations(IgniteCache cache) {
+        for (int i = 0; i < 100; i++)
+            cache.put(i, i);
+
+        for (int i = 0; i < 100; i++)
+            assertEquals(i, cache.get(i));
+    }
+
+    /** */
+    private void breakClient(IgniteEx client) {
+        Object discoSpi = ((Object[])GridTestUtils.getFieldValue(client.context().discovery(), GridManagerAdapter.class, "spis"))[0];
+
+        Object commSpi = ((Object[])GridTestUtils.getFieldValue(client.context().io(), GridManagerAdapter.class, "spis"))[0];
+
+        ((TcpCommunicationSpi)commSpi).simulateNodeFailure();
+
+        ((TcpDiscoverySpi)discoSpi).simulateNodeFailure();
+    }
+}


[ignite] 05/31: GG-12665 Use UTC timezone in build date.

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch gg-19225
in repository https://gitbox.apache.org/repos/asf/ignite.git

commit 629c37acc6f9ee250d6c02708405859c40129b5a
Author: ibessonov <be...@gmail.com>
AuthorDate: Thu May 30 10:06:11 2019 +0300

    GG-12665 Use UTC timezone in build date.
    
    (cherry picked from commit 519dfd3142f6e7667ec33c53000da57744054eec)
---
 .../java/org/apache/ignite/internal/IgniteVersionUtils.java    | 10 +++++++++-
 .../main/java/org/apache/ignite/lang/IgniteProductVersion.java |  4 ++--
 2 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/modules/core/src/main/java/org/apache/ignite/internal/IgniteVersionUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/IgniteVersionUtils.java
index c950eac..e015686 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/IgniteVersionUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/IgniteVersionUtils.java
@@ -18,6 +18,7 @@ package org.apache.ignite.internal;
 
 import java.text.SimpleDateFormat;
 import java.util.Date;
+import java.util.TimeZone;
 import org.apache.ignite.lang.IgniteProductVersion;
 
 /**
@@ -30,6 +31,9 @@ public class IgniteVersionUtils {
     /** Ignite version. */
     public static final IgniteProductVersion VER;
 
+    /** UTC build date formatter. */
+    public static final SimpleDateFormat BUILD_TSTAMP_DATE_FORMATTER;
+
     /** Formatted build date. */
     public static final String BUILD_TSTAMP_STR;
 
@@ -66,7 +70,11 @@ public class IgniteVersionUtils {
         BUILD_TSTAMP = !BUILD_TSTAMP_FROM_PROPERTY.isEmpty() && Long.parseLong(BUILD_TSTAMP_FROM_PROPERTY) != 0
             ? Long.parseLong(BUILD_TSTAMP_FROM_PROPERTY) : System.currentTimeMillis() / 1000;
 
-        BUILD_TSTAMP_STR = new SimpleDateFormat("yyyyMMdd").format(new Date(BUILD_TSTAMP * 1000));
+        BUILD_TSTAMP_DATE_FORMATTER = new SimpleDateFormat("yyyyMMdd");
+
+        BUILD_TSTAMP_DATE_FORMATTER.setTimeZone(TimeZone.getTimeZone("UTC"));
+
+        BUILD_TSTAMP_STR = BUILD_TSTAMP_DATE_FORMATTER.format(new Date(BUILD_TSTAMP * 1000));
 
         COPYRIGHT = BUILD_TSTAMP_STR.substring(0, 4) + " Copyright(C) Apache Software Foundation";
 
diff --git a/modules/core/src/main/java/org/apache/ignite/lang/IgniteProductVersion.java b/modules/core/src/main/java/org/apache/ignite/lang/IgniteProductVersion.java
index f50647a..cc27550 100644
--- a/modules/core/src/main/java/org/apache/ignite/lang/IgniteProductVersion.java
+++ b/modules/core/src/main/java/org/apache/ignite/lang/IgniteProductVersion.java
@@ -20,11 +20,11 @@ import java.io.Externalizable;
 import java.io.IOException;
 import java.io.ObjectInput;
 import java.io.ObjectOutput;
-import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.internal.IgniteVersionUtils;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.jetbrains.annotations.NotNull;
 
@@ -258,7 +258,7 @@ public class IgniteProductVersion implements Comparable<IgniteProductVersion>, E
 
     /** {@inheritDoc} */
     @Override public String toString() {
-        String revTsStr = new SimpleDateFormat("yyyyMMdd").format(new Date(revTs * 1000));
+        String revTsStr = IgniteVersionUtils.BUILD_TSTAMP_DATE_FORMATTER.format(new Date(revTs * 1000));
 
         String hash = U.byteArray2HexString(revHash).toLowerCase();
 


[ignite] 29/31: GG-19221 [GG-18667]-[IGNITE-11750] Implement locked pages info dump for long-running B+Tree operations

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch gg-19225
in repository https://gitbox.apache.org/repos/asf/ignite.git

commit 76289ae047f2ab53c7f3f8ec5a4702d0f948eab2
Author: Dmitriy Govorukhin <dm...@gmail.com>
AuthorDate: Wed Jun 5 13:27:00 2019 +0300

    GG-19221 [GG-18667]-[IGNITE-11750] Implement locked pages info dump for long-running B+Tree operations
---
 .../JmhPageLockTrackerBenchmark.java               | 143 ++++
 .../stack/LockTrackerNoBarrier.java                |  65 ++
 .../benchmarks/jmh/tree/BPlusTreeBenchmark.java    |  15 +-
 .../org/apache/ignite/IgniteSystemProperties.java  |  33 +
 .../ignite/internal/commandline/CommandList.java   |  10 +-
 .../commandline/diagnostic/DiagnosticCommand.java  | 114 ++++
 .../diagnostic/DiagnosticSubCommand.java           |  73 ++
 .../commandline/diagnostic/PageLocksCommand.java   | 210 ++++++
 .../processors/cache/CacheDiagnosticManager.java   | 134 ++++
 .../processors/cache/GridCacheProcessor.java       |  11 +-
 .../processors/cache/GridCacheSharedContext.java   |  25 +-
 .../cache/IgniteCacheOffheapManager.java           |   5 -
 .../cache/IgniteCacheOffheapManagerImpl.java       |  37 +-
 .../processors/cache/mvcc/txlog/TxLog.java         |  37 +-
 .../processors/cache/mvcc/txlog/TxLogTree.java     |  30 +-
 .../cache/persistence/DataStructure.java           | 113 ++--
 .../cache/persistence/GridCacheOffheapManager.java |  93 ++-
 .../IgniteCacheDatabaseSharedManager.java          |  50 +-
 .../cache/persistence/IndexStorageImpl.java        |  38 +-
 .../diagnostic/pagelocktracker/DumpProcessor.java  |  40 ++
 .../diagnostic/pagelocktracker/DumpSupported.java  |  42 ++
 .../diagnostic/pagelocktracker/InvalidContext.java |  38 ++
 .../pagelocktracker/LockTrackerFactory.java        | 114 ++++
 .../diagnostic/pagelocktracker/PageLockDump.java   |  32 +
 .../PageLockListenerIndexAdapter.java              |  69 ++
 .../pagelocktracker/PageLockTracker.java           | 365 ++++++++++
 .../pagelocktracker/PageLockTrackerMXBean.java     |  58 ++
 .../pagelocktracker/PageLockTrackerMXBeanImpl.java |  59 ++
 .../pagelocktracker/PageLockTrackerManager.java    | 270 ++++++++
 .../pagelocktracker/PageMetaInfoStore.java         |  89 +++
 .../pagelocktracker/SharedPageLockTracker.java     | 444 ++++++++++++
 .../pagelocktracker/ThreadPageLocksDumpLock.java   |  91 +++
 .../dumpprocessors/ToFileDumpProcessor.java        |  83 +++
 .../dumpprocessors/ToStringDumpProcessor.java      | 335 +++++++++
 .../diagnostic/pagelocktracker/log/LockLog.java    | 137 ++++
 .../pagelocktracker/log/PageLockLogSnapshot.java   | 138 ++++
 .../pagelocktracker/stack/LockStack.java           | 188 ++++++
 .../stack/PageLockStackSnapshot.java               |  79 +++
 .../store/HeapPageMetaInfoStore.java               | 162 +++++
 .../store/OffHeapPageMetaInfoStore.java            | 200 ++++++
 .../persistence/freelist/AbstractFreeList.java     |  13 +-
 .../{CacheFreeListImpl.java => CacheFreeList.java} |  33 +-
 .../cache/persistence/freelist/PagesList.java      |  12 +-
 .../cache/persistence/metastorage/MetaStorage.java |  51 +-
 .../persistence/metastorage/MetastorageTree.java   |  24 +-
 .../UpgradePendingTreeToPerPartitionTask.java      |   3 +-
 .../cache/persistence/tree/BPlusTree.java          |  22 +-
 .../persistence/tree/reuse/ReuseListImpl.java      |  24 +-
 .../wal/reader/IgniteWalIteratorFactory.java       |   2 +-
 .../processors/cache/tree/CacheDataTree.java       |  11 +-
 .../processors/cache/tree/PendingEntriesTree.java  |  13 +-
 .../processors/diagnostic/DiagnosticProcessor.java |   8 +
 .../visor/diagnostic/VisorPageLocksResult.java     |  82 +++
 .../visor/diagnostic/VisorPageLocksTask.java       | 141 ++++
 .../diagnostic/VisorPageLocksTrackerArgs.java      | 135 ++++
 .../main/resources/META-INF/classnames.properties  |   4 +
 .../db/wal/IgniteWalIteratorSwitchSegmentTest.java |   2 +
 .../db/wal/WalRecoveryTxLogicalRecordsTest.java    |   4 +-
 .../pagelocktracker/AbstractPageLockTest.java      |  56 ++
 .../PageLockTrackerMXBeanImplTest.java             |  80 +++
 .../PageLockTrackerManagerTest.java                | 218 ++++++
 .../pagelocktracker/PageLockTrackerTestSuit.java   |  43 ++
 .../pagelocktracker/SharedPageLockTrackerTest.java | 541 +++++++++++++++
 .../dumpprocessors/ToFileDumpProcessorTest.java    | 108 +++
 .../pagelocktracker/log/HeapArrayLockLogTest.java  |  29 +
 .../pagelocktracker/log/OffHeapLockLogTest.java    |  29 +
 .../pagelocktracker/log/PageLockLogTest.java       | 641 ++++++++++++++++++
 .../stack/HeapArrayLockStackTest.java              |  29 +
 .../stack/OffHeapLockStackTest.java                |  29 +
 .../pagelocktracker/stack/PageLockStackTest.java   | 751 +++++++++++++++++++++
 .../pagemem/BPlusTreePageMemoryImplTest.java       |   4 +-
 .../BPlusTreeReuseListPageMemoryImplTest.java      |   1 +
 .../pagemem/IndexStoragePageMemoryImplTest.java    |   4 +-
 .../pagemem/PageMemoryImplNoLoadTest.java          |   1 +
 .../persistence/pagemem/PageMemoryImplTest.java    |   1 +
 .../database/BPlusTreeReuseSelfTest.java           |  62 +-
 .../processors/database/BPlusTreeSelfTest.java     | 277 ++++----
 ...mplSelfTest.java => CacheFreeListSelfTest.java} |  22 +-
 .../processors/database/IndexStorageSelfTest.java  |   1 +
 .../loadtests/hashmap/GridCacheTestContext.java    |  10 +-
 .../ignite/testsuites/IgniteBasicTestSuite.java    |   4 +-
 .../ignite/testsuites/IgnitePdsTestSuite4.java     |  16 +
 .../apache/ignite/util/GridCommandHandlerTest.java |  52 +-
 .../processors/query/h2/IgniteH2Indexing.java      |   9 +-
 .../processors/query/h2/database/H2Tree.java       |  12 +-
 85 files changed, 7522 insertions(+), 361 deletions(-)

diff --git a/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/diagnostic/pagelocktracker/JmhPageLockTrackerBenchmark.java b/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/diagnostic/pagelocktracker/JmhPageLockTrackerBenchmark.java
new file mode 100644
index 0000000..41dd51d
--- /dev/null
+++ b/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/diagnostic/pagelocktracker/JmhPageLockTrackerBenchmark.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.benchmarks.jmh.diagnostic.pagelocktracker;
+
+import org.apache.ignite.internal.benchmarks.jmh.diagnostic.pagelocktracker.stack.LockTrackerNoBarrier;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.LockTrackerFactory;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageLockTracker;
+import org.apache.ignite.internal.processors.cache.persistence.tree.util.PageLockListener;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.Warmup;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+import static org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.LockTrackerFactory.HEAP_LOG;
+import static org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.LockTrackerFactory.HEAP_STACK;
+import static org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.LockTrackerFactory.OFF_HEAP_LOG;
+import static org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.LockTrackerFactory.OFF_HEAP_STACK;
+
+/**
+ * Benchmark PageLockTracker (factory LockTrackerFactory)
+ */
+public class JmhPageLockTrackerBenchmark {
+    /**
+     * @param args Params.
+     */
+    public static void main(String[] args) throws Exception {
+        Options opt = new OptionsBuilder()
+            .include(JmhPageLockTrackerBenchmark.class.getSimpleName())
+            .build();
+
+        new Runner(opt).run();
+    }
+
+    /** */
+    @State(Scope.Thread)
+    public static class ThreadLocalState {
+        PageLockListener pl;
+
+        @Param({"2", "4", "8", "16"})
+        int stackSize;
+
+        @Param({
+            "HeapArrayLockStack",
+            "HeapArrayLockLog",
+            "OffHeapLockStack",
+            "OffHeapLockLog"
+        })
+        String type;
+
+        @Param({"true", "false"})
+        boolean barrier;
+
+        int StructureId = 123;
+
+        @Setup
+        public void doSetup() {
+            pl = create(Thread.currentThread().getName(), type, barrier);
+        }
+    }
+
+    /**
+     *  Mesure cost for (beforelock -> lock -> unlock) operation.
+     */
+    @Benchmark
+    @BenchmarkMode(Mode.Throughput)
+    @Fork(1)
+    @Warmup(iterations = 10)
+    @Measurement(iterations = 10)
+    //@OutputTimeUnit(TimeUnit.MICROSECONDS)
+    public void lockUnlock(ThreadLocalState localState) {
+        PageLockListener pl = localState.pl;
+
+        for (int i = 0; i < localState.stackSize; i++) {
+            int pageId = i + 1;
+
+            pl.onBeforeReadLock(localState.StructureId, pageId, pageId);
+
+            pl.onReadLock(localState.StructureId, pageId, pageId, pageId);
+        }
+
+        for (int i = localState.stackSize; i > 0; i--) {
+            int pageId = i;
+
+            pl.onReadUnlock(localState.StructureId, pageId, pageId, pageId);
+        }
+    }
+
+    /**
+     * Factory method.
+     *
+     * @param name Lock tracer name.
+     * @param type Lock tracer type.
+     * @param barrier If {@code True} use real implementation,
+     * if {@code False} use implementation with safety dump barrier.
+     * @return Page lock tracker as PageLockListener.
+     */
+    private static PageLockListener create(String name, String type, boolean barrier) {
+        PageLockTracker tracker;
+
+        switch (type) {
+            case "HeapArrayLockStack":
+                tracker = LockTrackerFactory.create(HEAP_STACK, name);
+                break;
+            case "HeapArrayLockLog":
+                tracker = LockTrackerFactory.create(HEAP_LOG, name);
+                break;
+            case "OffHeapLockStack":
+                tracker = LockTrackerFactory.create(OFF_HEAP_STACK, name);
+                break;
+
+            case "OffHeapLockLog":
+                tracker = LockTrackerFactory.create(OFF_HEAP_LOG, name);
+                break;
+            default:
+                throw new IllegalArgumentException("type:" + type);
+        }
+
+        return barrier ? tracker : new LockTrackerNoBarrier(tracker);
+    }
+}
diff --git a/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/diagnostic/pagelocktracker/stack/LockTrackerNoBarrier.java b/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/diagnostic/pagelocktracker/stack/LockTrackerNoBarrier.java
new file mode 100644
index 0000000..dc3b3ff
--- /dev/null
+++ b/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/diagnostic/pagelocktracker/stack/LockTrackerNoBarrier.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.benchmarks.jmh.diagnostic.pagelocktracker.stack;
+
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageLockTracker;
+import org.apache.ignite.internal.processors.cache.persistence.tree.util.PageLockListener;
+
+/**
+ * Local without barrier syncronization on operation.
+ */
+public class LockTrackerNoBarrier implements PageLockListener {
+    /** */
+    private final PageLockTracker delegate;
+
+    /** */
+    public LockTrackerNoBarrier(
+        PageLockTracker delegate
+    ) {
+        this.delegate = delegate;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void onBeforeWriteLock(int cacheId, long pageId, long page) {
+        delegate.onBeforeWriteLock0(cacheId, pageId, page);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void onWriteLock(int cacheId, long pageId, long page, long pageAddr) {
+        delegate.onWriteLock0(cacheId, pageId, page, pageAddr);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void onWriteUnlock(int cacheId, long pageId, long page, long pageAddr) {
+        delegate.onWriteUnlock0(cacheId, pageId, page, pageAddr);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void onBeforeReadLock(int cacheId, long pageId, long page) {
+        delegate.onBeforeReadLock0(cacheId, pageId, page);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void onReadLock(int cacheId, long pageId, long page, long pageAddr) {
+        delegate.onReadLock0(cacheId, pageId, page, pageAddr);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void onReadUnlock(int cacheId, long pageId, long page, long pageAddr) {
+        delegate.onReadUnlock(cacheId, pageId, page, pageAddr);
+    }
+}
\ No newline at end of file
diff --git a/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/tree/BPlusTreeBenchmark.java b/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/tree/BPlusTreeBenchmark.java
index 6513c13..586b85c 100644
--- a/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/tree/BPlusTreeBenchmark.java
+++ b/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/tree/BPlusTreeBenchmark.java
@@ -174,8 +174,19 @@ public class BPlusTreeBenchmark extends JmhAbstractBenchmark {
          */
         TestTree(ReuseList reuseList, int cacheId, PageMemory pageMem, long metaPageId)
             throws IgniteCheckedException {
-            super("test", cacheId, pageMem, null, new AtomicLong(), metaPageId, reuseList,
-                new IOVersions<>(new LongInnerIO()), new IOVersions<>(new LongLeafIO()), null);
+            super(
+                "test",
+                cacheId,
+                pageMem,
+                null,
+                new AtomicLong(),
+                metaPageId,
+                reuseList,
+                new IOVersions<>(new LongInnerIO()),
+                new IOVersions<>(new LongLeafIO()),
+                null,
+                null
+            );
 
             PageIO.registerTest(latestInnerIO(), latestLeafIO());
 
diff --git a/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java b/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java
index 4e7b312..ee9eac9 100644
--- a/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java
+++ b/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java
@@ -1120,6 +1120,39 @@ public final class IgniteSystemProperties {
     public static final String IGNITE_TX_OWNER_DUMP_REQUESTS_ALLOWED = "IGNITE_TX_OWNER_DUMP_REQUESTS_ALLOWED";
 
     /**
+     * Page lock tracker type.
+     * -1 - Disable lock tracking.
+     *  1 - HEAP_STACK
+     *  2 - HEAP_LOG
+     *  3 - OFF_HEAP_STACK
+     *  4 - OFF_HEAP_LOG
+     *
+     * Default is 2 - HEAP_LOG.
+     */
+    public static final String IGNITE_PAGE_LOCK_TRACKER_TYPE = "IGNITE_PAGE_LOCK_TRACKER_TYPE";
+
+    /**
+     * Capacity in pages for storing in page lock tracker strucuture.
+     *
+     * Default is 512 pages.
+     */
+    public static final String IGNITE_PAGE_LOCK_TRACKER_CAPACITY = "IGNITE_PAGE_LOCK_TRACKER_CAPACITY";
+
+    /**
+     * Page lock tracker thread for checking hangs threads interval.
+     *
+     * Default is 60_000 ms.
+     */
+    public static final String IGNITE_PAGE_LOCK_TRACKER_CHECK_INTERVAL = "IGNITE_PAGE_LOCK_TRACKER_CHECK_INTERVAL";
+
+    /**
+     * Enables threads locks dumping on critical node failure.
+     *
+     * Default is {@code true}.
+     */
+    public static final String IGNITE_DUMP_PAGE_LOCK_ON_FAILURE = "IGNITE_DUMP_PAGE_LOCK_ON_FAILURE";
+
+    /**
      * Enforces singleton.
      */
     private IgniteSystemProperties() {
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommandList.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommandList.java
index d595e05..232b0f5 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommandList.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommandList.java
@@ -17,6 +17,7 @@
 package org.apache.ignite.internal.commandline;
 
 import org.apache.ignite.internal.commandline.cache.CacheCommands;
+import org.apache.ignite.internal.commandline.diagnostic.DiagnosticCommand;
 
 /**
  * High-level commands.
@@ -41,7 +42,10 @@ public enum CommandList {
     CACHE("--cache", new CacheCommands()),
 
     /** */
-    WAL("--wal", new WalCommands());
+    WAL("--wal", new WalCommands()),
+
+    /** */
+    DIAGNOSTIC("--diagnostic", new DiagnosticCommand());
 
     /** Private values copy so there's no need in cloning it every time. */
     private static final CommandList[] VALUES = CommandList.values();
@@ -89,8 +93,8 @@ public enum CommandList {
     }
 
     /** {@inheritDoc} */
-    @Override public String toString() { 
-        return text; 
+    @Override public String toString() {
+        return text;
     }
 
     /**
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/diagnostic/DiagnosticCommand.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/diagnostic/DiagnosticCommand.java
new file mode 100644
index 0000000..97e0218
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/diagnostic/DiagnosticCommand.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.commandline.diagnostic;
+
+import org.apache.ignite.internal.client.GridClientConfiguration;
+import org.apache.ignite.internal.commandline.Command;
+import org.apache.ignite.internal.commandline.CommandArgIterator;
+import org.apache.ignite.internal.commandline.CommandLogger;
+
+import static org.apache.ignite.internal.commandline.CommandHandler.UTILITY_NAME;
+import static org.apache.ignite.internal.commandline.CommandList.DIAGNOSTIC;
+import static org.apache.ignite.internal.commandline.CommandLogger.join;
+import static org.apache.ignite.internal.commandline.diagnostic.DiagnosticSubCommand.HELP;
+import static org.apache.ignite.internal.commandline.diagnostic.DiagnosticSubCommand.PAGE_LOCKS;
+
+/**
+ *
+ */
+public class DiagnosticCommand implements Command<DiagnosticSubCommand> {
+    /**
+     *
+     */
+    private DiagnosticSubCommand subcommand;
+
+    /**
+     *
+     */
+    private CommandLogger logger;
+
+    /** {@inheritDoc} */
+    @Override public Object execute(GridClientConfiguration clientCfg, CommandLogger logger) throws Exception {
+        this.logger = logger;
+
+        if (subcommand == HELP) {
+            printDiagnosticHelp();
+
+            return null;
+        }
+
+        Command command = subcommand.subcommand();
+
+        if (command == null)
+            throw new IllegalStateException("Unknown command " + subcommand);
+
+        return command.execute(clientCfg, logger);
+    }
+
+    /** {@inheritDoc} */
+    @Override public DiagnosticSubCommand arg() {
+        return subcommand;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void parseArguments(CommandArgIterator argIter) {
+        if (!argIter.hasNextSubArg()) {
+            subcommand = HELP;
+
+            return;
+        }
+
+        String str = argIter.nextArg("").toLowerCase();
+
+        DiagnosticSubCommand cmd = DiagnosticSubCommand.of(str);
+
+        if (cmd == null)
+            cmd = HELP;
+
+        switch (cmd) {
+            case HELP:
+                break;
+
+            case PAGE_LOCKS:
+                cmd.subcommand().parseArguments(argIter);
+
+                break;
+
+            default:
+                throw new IllegalArgumentException("Unknown diagnostic subcommand " + cmd);
+        }
+
+        if (argIter.hasNextSubArg())
+            throw new IllegalArgumentException("Unexpected argument of diagnostic subcommand: " + argIter.peekNextArg());
+
+        subcommand = cmd;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void printUsage(CommandLogger logger) {
+        logger.logWithIndent("View diagnostic information in a cluster. For more details type:");
+        logger.logWithIndent(join(" ", UTILITY_NAME, DIAGNOSTIC, HELP), 2);
+        logger.nl();
+    }
+
+    /**
+     *
+     */
+    private void printDiagnosticHelp() {
+        logger.log(join(" ", UTILITY_NAME, DIAGNOSTIC, PAGE_LOCKS + " - dump page locks info."));
+    }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/diagnostic/DiagnosticSubCommand.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/diagnostic/DiagnosticSubCommand.java
new file mode 100644
index 0000000..3fd1c03
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/diagnostic/DiagnosticSubCommand.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.commandline.diagnostic;
+
+import org.apache.ignite.internal.commandline.Command;
+
+/**
+ *
+ */
+public enum DiagnosticSubCommand {
+    /** */
+    HELP("help", null),
+
+    /** */
+    PAGE_LOCKS("pageLocks", new PageLocksCommand());
+
+    /** Diagnostic command name. */
+    private final String name;
+
+    /** Command instance for certain type. */
+    private final Command command;
+
+    /**
+     * @param name Command name.
+     * @param command Command handler.
+     */
+    DiagnosticSubCommand(
+        String name,
+        Command command
+    ) {
+        this.name = name;
+        this.command = command;
+    }
+
+    /**
+     * @return Subcommand realization.
+     */
+    public Command subcommand() {
+        return command;
+    }
+
+    /**
+     * @param text Command text.
+     * @return Command for the text.
+     */
+    public static DiagnosticSubCommand of(String text) {
+        for (DiagnosticSubCommand cmd : DiagnosticSubCommand.values()) {
+            if (cmd.name.equalsIgnoreCase(text))
+                return cmd;
+        }
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return name;
+    }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/diagnostic/PageLocksCommand.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/diagnostic/PageLocksCommand.java
new file mode 100644
index 0000000..c110c98
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/diagnostic/PageLocksCommand.java
@@ -0,0 +1,210 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.commandline.diagnostic;
+
+import java.io.File;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.internal.client.GridClient;
+import org.apache.ignite.internal.client.GridClientConfiguration;
+import org.apache.ignite.internal.commandline.Command;
+import org.apache.ignite.internal.commandline.CommandArgIterator;
+import org.apache.ignite.internal.commandline.CommandLogger;
+import org.apache.ignite.internal.commandline.TaskExecutor;
+import org.apache.ignite.internal.visor.diagnostic.VisorPageLocksResult;
+import org.apache.ignite.internal.visor.diagnostic.VisorPageLocksTask;
+import org.apache.ignite.internal.visor.diagnostic.VisorPageLocksTrackerArgs;
+
+import static org.apache.ignite.internal.commandline.CommandHandler.UTILITY_NAME;
+import static org.apache.ignite.internal.commandline.CommandList.DIAGNOSTIC;
+import static org.apache.ignite.internal.commandline.diagnostic.DiagnosticSubCommand.PAGE_LOCKS;
+
+/**
+ *
+ */
+public class PageLocksCommand implements Command<PageLocksCommand.Args> {
+    /**
+     *
+     */
+    public static final String DUMP = "dump";
+    /**
+     *
+     */
+    public static final String DUMP_LOG = "dump_log";
+
+    /**
+     *
+     */
+    private Args args;
+
+    /**
+     *
+     */
+    private CommandLogger logger;
+
+    /**
+     *
+     */
+    private boolean help;
+
+    /** {@inheritDoc} */
+    @Override public Object execute(GridClientConfiguration clientCfg, CommandLogger logger) throws Exception {
+        this.logger = logger;
+
+        if (help) {
+            help = false;
+
+            printUsage(logger);
+
+            return null;
+        }
+
+        Set<String> nodeIds = args.nodeIds;
+
+        try (GridClient client = Command.startClient(clientCfg)) {
+            if (args.allNodes) {
+                client.compute().nodes().forEach(n -> {
+                    nodeIds.add(String.valueOf(n.consistentId()));
+                    nodeIds.add(n.nodeId().toString());
+                });
+            }
+        }
+
+        VisorPageLocksTrackerArgs taskArg = new VisorPageLocksTrackerArgs(args.op, args.type, args.filePath, nodeIds);
+
+        Map<ClusterNode, VisorPageLocksResult> res;
+
+        try (GridClient client = Command.startClient(clientCfg)) {
+            res = TaskExecutor.executeTask(
+                client,
+                VisorPageLocksTask.class,
+                taskArg,
+                clientCfg
+            );
+        }
+
+        printResult(res);
+
+        return res;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Args arg() {
+        return args;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void parseArguments(CommandArgIterator argIter) {
+        if (argIter.hasNextSubArg()) {
+            String cmd = argIter.nextArg("").toLowerCase();
+
+            if (DUMP.equals(cmd) || DUMP_LOG.equals(cmd)) {
+                boolean allNodes = false;
+                String filePath = null;
+
+                Set<String> nodeIds = new TreeSet<>();
+
+                while (argIter.hasNextArg()){
+                    String nextArg = argIter.nextArg("").toLowerCase();
+
+                    if ("--all".equals(nextArg))
+                        allNodes = true;
+                    else if ("--nodes".equals(nextArg)) {
+                        while (argIter.hasNextArg()){
+                            nextArg = argIter.nextArg("").toLowerCase();
+
+                            nodeIds.add(nextArg);
+                        }
+                    }
+                    else {
+                        if (new File(nextArg).isDirectory())
+                            filePath = nextArg;
+                    }
+                }
+
+                args = new Args(DUMP, cmd, filePath, allNodes, nodeIds);
+            }
+            else
+                help = true;
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public void printUsage(CommandLogger logger) {
+        logger.log("View pages locks state information on the node or nodes.");
+        logger.log(CommandLogger.join(" ",
+            UTILITY_NAME, DIAGNOSTIC, PAGE_LOCKS, DUMP,
+            "[--path path_to_directory] [--all|--nodes nodeId1,nodeId2,..|--nodes consistentId1,consistentId2,..]",
+            "// Save page locks dump to file generated in IGNITE_HOME/work directory."));
+        logger.log(CommandLogger.join(" ",
+            UTILITY_NAME, DIAGNOSTIC, PAGE_LOCKS, DUMP_LOG,
+            "[--all|--nodes nodeId1,nodeId2,..|--nodes consistentId1,consistentId2,..]",
+            "// Pring page locks dump to console on the node or nodes."));
+        logger.nl();
+    }
+
+    /**
+     * @param res Result.
+     */
+    private void printResult(Map<ClusterNode, VisorPageLocksResult> res) {
+        res.forEach((n, res0) -> {
+            logger.log(n.id() + " (" + n.consistentId() + ") " + res0.result());
+        });
+    }
+
+    /**
+     *
+     */
+    public static class Args {
+        /**
+         *
+         */
+        private final String op;
+        /**
+         *
+         */
+        private final String type;
+        /**
+         *
+         */
+        private final String filePath;
+        /**
+         *
+         */
+        private final boolean allNodes;
+        /**
+         *
+         */
+        private final Set<String> nodeIds;
+
+        /**
+         * @param op Operation.
+         * @param type Type.
+         * @param filePath File path.
+         * @param nodeIds Node ids.
+         */
+        public Args(String op, String type, String filePath, boolean allNodes, Set<String> nodeIds) {
+            this.op = op;
+            this.type = type;
+            this.filePath = filePath;
+            this.allNodes = allNodes;
+            this.nodeIds = nodeIds;
+        }
+    }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheDiagnosticManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheDiagnosticManager.java
new file mode 100644
index 0000000..ec271fb
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheDiagnosticManager.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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 javax.management.InstanceNotFoundException;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageLockTrackerMXBean;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageLockTrackerManager;
+import org.apache.ignite.internal.util.typedef.internal.U;
+
+/**
+ * Component for manage all cache diagnostic functionality.
+ */
+public class CacheDiagnosticManager extends GridCacheSharedManagerAdapter {
+    /** Diagnostic mxbeans group name. */
+    public static final String MBEAN_GROUP = "Diagnostic";
+
+    /** Page lock tracker manager */
+    private  PageLockTrackerManager pageLockTrackerManager;
+
+    /** {@inheritDoc} */
+    @Override protected void start0() throws IgniteCheckedException {
+        super.start0();
+
+        String name = cctx.kernalContext().pdsFolderResolver().resolveFolders().consistentId().toString();
+
+        pageLockTrackerManager = new PageLockTrackerManager(log, name);
+
+        pageLockTrackerManager.start();
+
+        registerMetricsMBean(
+            cctx.gridConfig(),
+            MBEAN_GROUP,
+            PageLockTrackerMXBean.MBEAN_NAME,
+            pageLockTrackerManager.mxBean(),
+            PageLockTrackerMXBean.class
+        );
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void stop0(boolean cancel) {
+        super.stop0(cancel);
+
+        unregisterMetricsMBean(cctx.gridConfig(), MBEAN_GROUP, PageLockTrackerMXBean.MBEAN_NAME);
+
+        pageLockTrackerManager.stop();
+    }
+
+    /**
+     * Getter.
+     *
+     * @return Page lock tracker mananger.
+     */
+    public PageLockTrackerManager pageLockTracker() {
+        return pageLockTrackerManager;
+    }
+
+    /**
+     * @param cfg Ignite configuration.
+     * @param groupName Name of group.
+     * @param mbeanName Metrics MBean name.
+     * @param impl Metrics implementation.
+     * @param clazz Metrics class type.
+     */
+    protected <T> void registerMetricsMBean(
+        IgniteConfiguration cfg,
+        String groupName,
+        String mbeanName,
+        T impl,
+        Class<T> clazz
+    ) {
+        if (U.IGNITE_MBEANS_DISABLED)
+            return;
+
+        try {
+            U.registerMBean(
+                cfg.getMBeanServer(),
+                cfg.getIgniteInstanceName(),
+                groupName,
+                mbeanName,
+                impl,
+                clazz);
+        }
+        catch (Throwable e) {
+            U.error(log, "Failed to register MBean with name: " + mbeanName, e);
+        }
+    }
+
+    /**
+     * @param cfg Ignite configuration.
+     * @param groupName Name of group.
+     * @param name Name of MBean.
+     */
+    protected void unregisterMetricsMBean(
+        IgniteConfiguration cfg,
+        String groupName,
+        String name
+    ) {
+        if (U.IGNITE_MBEANS_DISABLED)
+            return;
+
+        assert cfg != null;
+
+        try {
+            cfg.getMBeanServer().unregisterMBean(
+                U.makeMBeanName(
+                    cfg.getIgniteInstanceName(),
+                    groupName,
+                    name
+                ));
+        }
+        catch (InstanceNotFoundException ignored) {
+            // We tried to unregister a non-existing MBean, not a big deal.
+        }
+        catch (Throwable e) {
+            U.error(log, "Failed to unregister MBean for memory metrics: " + name, e);
+        }
+    }
+}
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 167cdcc..8c3c871 100644
--- 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
@@ -3340,8 +3340,10 @@ public class GridCacheProcessor extends GridProcessorAdapter {
      * @throws IgniteCheckedException If failed.
      */
     @SuppressWarnings("unchecked")
-    private GridCacheSharedContext createSharedContext(GridKernalContext kernalCtx,
-        Collection<CacheStoreSessionListener> storeSesLsnrs) throws IgniteCheckedException {
+    private GridCacheSharedContext createSharedContext(
+        GridKernalContext kernalCtx,
+        Collection<CacheStoreSessionListener> storeSesLsnrs
+    ) throws IgniteCheckedException {
         IgniteTxManager tm = new IgniteTxManager();
         GridCacheMvccManager mvccMgr = new GridCacheMvccManager();
         GridCacheVersionManager verMgr = new GridCacheVersionManager();
@@ -3392,6 +3394,8 @@ public class GridCacheProcessor extends GridProcessorAdapter {
 
         DeadlockDetectionManager deadlockDetectionMgr = new DeadlockDetectionManager();
 
+        CacheDiagnosticManager diagnosticMgr = new CacheDiagnosticManager();
+
         return new GridCacheSharedContext(
             kernalCtx,
             tm,
@@ -3411,7 +3415,8 @@ public class GridCacheProcessor extends GridProcessorAdapter {
             jta,
             storeSesLsnrs,
             mvccCachingMgr,
-            deadlockDetectionMgr
+            deadlockDetectionMgr,
+            diagnosticMgr
         );
     }
 
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheSharedContext.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheSharedContext.java
index d130fad..ba9dc9a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheSharedContext.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheSharedContext.java
@@ -142,6 +142,9 @@ public class GridCacheSharedContext<K, V> {
     /** Tx metrics. */
     private final TransactionMetricsAdapter txMetrics;
 
+    /** Cache diagnostic manager. */
+    private CacheDiagnosticManager diagnosticMgr;
+
     /** Store session listeners. */
     private Collection<CacheStoreSessionListener> storeSesLsnrs;
 
@@ -221,7 +224,8 @@ public class GridCacheSharedContext<K, V> {
         CacheJtaManagerAdapter jtaMgr,
         Collection<CacheStoreSessionListener> storeSesLsnrs,
         MvccCachingManager mvccCachingMgr,
-        DeadlockDetectionManager deadlockDetectionMgr
+        DeadlockDetectionManager deadlockDetectionMgr,
+        CacheDiagnosticManager diagnosticMgr
     ) {
         this.kernalCtx = kernalCtx;
 
@@ -243,7 +247,8 @@ public class GridCacheSharedContext<K, V> {
             ttlMgr,
             evictMgr,
             mvccCachingMgr,
-            deadlockDetectionMgr
+            deadlockDetectionMgr,
+            diagnosticMgr
         );
 
         this.storeSesLsnrs = storeSesLsnrs;
@@ -411,7 +416,9 @@ public class GridCacheSharedContext<K, V> {
             ttlMgr,
             evictMgr,
             mvccCachingMgr,
-            deadlockDetectionMgr);
+            deadlockDetectionMgr,
+            diagnosticMgr
+        );
 
         this.mgrs = mgrs;
 
@@ -458,7 +465,10 @@ public class GridCacheSharedContext<K, V> {
         GridCacheSharedTtlCleanupManager ttlMgr,
         PartitionsEvictManager evictMgr,
         MvccCachingManager mvccCachingMgr,
-        DeadlockDetectionManager deadlockDetectionMgr) {
+        DeadlockDetectionManager deadlockDetectionMgr,
+        CacheDiagnosticManager diagnosticMgr
+    ) {
+        this.diagnosticMgr = add(mgrs, diagnosticMgr);
         this.mvccMgr = add(mgrs, mvccMgr);
         this.verMgr = add(mgrs, verMgr);
         this.txMgr = add(mgrs, txMgr);
@@ -829,6 +839,13 @@ public class GridCacheSharedContext<K, V> {
     }
 
     /**
+     * @return Diagnostic manager.
+     */
+    public CacheDiagnosticManager diagnostic(){
+        return diagnosticMgr;
+    }
+
+    /**
      * @return Deadlock detection manager.
      */
     public DeadlockDetectionManager deadlockDetectionMgr() {
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManager.java
index f8fe509..90a9370 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManager.java
@@ -593,11 +593,6 @@ public interface IgniteCacheOffheapManager {
         int partId();
 
         /**
-         * @return Store name.
-         */
-        String name();
-
-        /**
          * @param size Size to init.
          * @param updCntr Update counter to init.
          * @param cacheSizes Cache sizes if store belongs to group containing multiple caches.
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java
index 9592c1e..201fdc4 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java
@@ -67,6 +67,7 @@ import org.apache.ignite.internal.processors.cache.persistence.tree.io.DataPageI
 import org.apache.ignite.internal.processors.cache.persistence.tree.io.PageIO;
 import org.apache.ignite.internal.processors.cache.persistence.tree.reuse.ReuseList;
 import org.apache.ignite.internal.processors.cache.persistence.tree.util.PageHandler;
+import org.apache.ignite.internal.processors.cache.persistence.tree.util.PageLockListener;
 import org.apache.ignite.internal.processors.cache.query.GridCacheQueryManager;
 import org.apache.ignite.internal.processors.cache.tree.CacheDataRowStore;
 import org.apache.ignite.internal.processors.cache.tree.CacheDataTree;
@@ -205,17 +206,21 @@ public class IgniteCacheOffheapManagerImpl implements IgniteCacheOffheapManager
         assert !cctx.group().persistenceEnabled();
 
         if (cctx.affinityNode() && cctx.ttl().eagerTtlEnabled() && pendingEntries == null) {
-            String name = "PendingEntries";
+            String pendingEntriesTreeName = cctx.name() + "##PendingEntries";
 
             long rootPage = allocateForTree();
 
+            PageLockListener lsnr = ctx.diagnostic().pageLockTracker().createPageLockTracker(pendingEntriesTreeName);
+
             pendingEntries = new PendingEntriesTree(
                 grp,
-                name,
+                pendingEntriesTreeName,
                 grp.dataRegion().pageMemory(),
                 rootPage,
                 grp.reuseList(),
-                true);
+                true,
+                lsnr
+            );
         }
     }
 
@@ -1210,23 +1215,26 @@ public class IgniteCacheOffheapManagerImpl implements IgniteCacheOffheapManager
      * @return Cache data store.
      * @throws IgniteCheckedException If failed.
      */
-    protected CacheDataStore createCacheDataStore0(int p)
-        throws IgniteCheckedException {
+    protected CacheDataStore createCacheDataStore0(int p) throws IgniteCheckedException {
         final long rootPage = allocateForTree();
 
         CacheDataRowStore rowStore = new CacheDataRowStore(grp, grp.freeList(), p);
 
-        String idxName = treeName(p);
+        String dataTreeName = grp.cacheOrGroupName() + "-" + treeName(p);
+
+        PageLockListener lsnr = ctx.diagnostic().pageLockTracker().createPageLockTracker(dataTreeName);
 
         CacheDataTree dataTree = new CacheDataTree(
             grp,
-            idxName,
+            dataTreeName,
             grp.reuseList(),
             rowStore,
             rootPage,
-            true);
+            true,
+            lsnr
+        );
 
-        return new CacheDataStoreImpl(p, idxName, rowStore, dataTree);
+        return new CacheDataStoreImpl(p, rowStore, dataTree);
     }
 
     /** {@inheritDoc} */
@@ -1369,9 +1377,6 @@ public class IgniteCacheOffheapManagerImpl implements IgniteCacheOffheapManager
         /** */
         private final int partId;
 
-        /** Tree name. */
-        private String name;
-
         /** */
         private final CacheDataRowStore rowStore;
 
@@ -1398,18 +1403,15 @@ public class IgniteCacheOffheapManagerImpl implements IgniteCacheOffheapManager
 
         /**
          * @param partId Partition number.
-         * @param name Name.
          * @param rowStore Row store.
          * @param dataTree Data tree.
          */
         public CacheDataStoreImpl(
             int partId,
-            String name,
             CacheDataRowStore rowStore,
             CacheDataTree dataTree
         ) {
             this.partId = partId;
-            this.name = name;
             this.rowStore = rowStore;
             this.dataTree = dataTree;
         }
@@ -1538,11 +1540,6 @@ public class IgniteCacheOffheapManagerImpl implements IgniteCacheOffheapManager
             return pCntr.finalizeUpdateCounters();
         }
 
-        /** {@inheritDoc} */
-        @Override public String name() {
-            return name;
-        }
-
         /**
          * @param cctx Cache context.
          * @param oldRow Old row.
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/mvcc/txlog/TxLog.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/mvcc/txlog/TxLog.java
index 238f7d0..041edfe 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/mvcc/txlog/TxLog.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/mvcc/txlog/TxLog.java
@@ -29,6 +29,7 @@ import org.apache.ignite.internal.pagemem.PageIdUtils;
 import org.apache.ignite.internal.pagemem.PageMemory;
 import org.apache.ignite.internal.pagemem.wal.IgniteWriteAheadLogManager;
 import org.apache.ignite.internal.pagemem.wal.record.delta.MetaPageInitRecord;
+import org.apache.ignite.internal.processors.cache.CacheDiagnosticManager;
 import org.apache.ignite.internal.processors.cache.mvcc.MvccUtils;
 import org.apache.ignite.internal.processors.cache.persistence.DbCheckpointListener;
 import org.apache.ignite.internal.processors.cache.persistence.GridCacheDatabaseSharedManager;
@@ -41,6 +42,7 @@ import org.apache.ignite.internal.processors.cache.persistence.tree.io.PageMetaI
 import org.apache.ignite.internal.processors.cache.persistence.tree.reuse.ReuseList;
 import org.apache.ignite.internal.processors.cache.persistence.tree.reuse.ReuseListImpl;
 import org.apache.ignite.internal.processors.cache.persistence.tree.util.PageHandler;
+import org.apache.ignite.internal.processors.cache.persistence.tree.util.PageLockListener;
 import org.apache.ignite.internal.util.IgniteTree;
 import org.apache.ignite.internal.util.typedef.internal.CU;
 import org.apache.ignite.internal.util.typedef.internal.U;
@@ -91,7 +93,16 @@ public class TxLog implements DbCheckpointListener {
      * @throws IgniteCheckedException If failed.
      */
     private void init(GridKernalContext ctx) throws IgniteCheckedException {
+        String txLogName = TX_LOG_CACHE_NAME + "##Tree";
+
+        CacheDiagnosticManager diagnosticMgr = ctx.cache().context().diagnostic();
+
+        PageLockListener txLogLockLsnr = diagnosticMgr.pageLockTracker().createPageLockTracker(txLogName);
+
         if (CU.isPersistenceEnabled(ctx.config())) {
+            String txLogReuseListName = TX_LOG_CACHE_NAME + "##ReuseList";
+            PageLockListener txLogReuseListLockLsnr = diagnosticMgr.pageLockTracker().createPageLockTracker(txLogReuseListName);
+
             mgr.checkpointReadLock();
 
             try {
@@ -164,9 +175,20 @@ public class TxLog implements DbCheckpointListener {
                     pageMemory,
                     wal,
                     reuseListRoot,
-                    isNew);
+                    isNew,
+                    txLogReuseListLockLsnr
+                );
 
-                tree = new TxLogTree(pageMemory, wal, treeRoot, reuseList, ctx.failure(), isNew);
+                tree = new TxLogTree(
+                    TX_LOG_CACHE_NAME,
+                    pageMemory,
+                    wal,
+                    treeRoot,
+                    reuseList,
+                    ctx.failure(),
+                    isNew,
+                    txLogLockLsnr
+                );
 
                 ((GridCacheDatabaseSharedManager)mgr).addCheckpointListener(this);
             }
@@ -183,7 +205,16 @@ public class TxLog implements DbCheckpointListener {
             if ((treeRoot = reuseList1.takeRecycledPage()) == 0L)
                 treeRoot = pageMemory.allocatePage(TX_LOG_CACHE_ID, INDEX_PARTITION, FLAG_IDX);
 
-            tree = new TxLogTree(pageMemory, null, treeRoot, reuseList1, ctx.failure(), true);
+            tree = new TxLogTree(
+                txLogName,
+                pageMemory,
+                null,
+                treeRoot,
+                reuseList1,
+                ctx.failure(),
+                true,
+                txLogLockLsnr
+            );
         }
     }
 
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/mvcc/txlog/TxLogTree.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/mvcc/txlog/TxLogTree.java
index 6c939d3..c3025fd 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/mvcc/txlog/TxLogTree.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/mvcc/txlog/TxLogTree.java
@@ -23,6 +23,7 @@ import org.apache.ignite.internal.pagemem.wal.IgniteWriteAheadLogManager;
 import org.apache.ignite.internal.processors.cache.persistence.tree.BPlusTree;
 import org.apache.ignite.internal.processors.cache.persistence.tree.io.BPlusIO;
 import org.apache.ignite.internal.processors.cache.persistence.tree.reuse.ReuseList;
+import org.apache.ignite.internal.processors.cache.persistence.tree.util.PageLockListener;
 import org.apache.ignite.internal.processors.failure.FailureProcessor;
 
 /**
@@ -38,12 +39,29 @@ public class TxLogTree extends BPlusTree<TxKey, TxRow> {
      * @param initNew {@code True} if new tree should be created.
      * @throws IgniteCheckedException If fails.
      */
-    public TxLogTree(PageMemory pageMem,
-        IgniteWriteAheadLogManager wal, long metaPageId,
-        ReuseList reuseList, FailureProcessor failureProcessor,
-        boolean initNew) throws IgniteCheckedException {
-        super(TxLog.TX_LOG_CACHE_NAME, TxLog.TX_LOG_CACHE_ID, pageMem, wal, new AtomicLong(), metaPageId,
-            reuseList, TxLogInnerIO.VERSIONS, TxLogLeafIO.VERSIONS, failureProcessor);
+    public TxLogTree(
+        String name,
+        PageMemory pageMem,
+        IgniteWriteAheadLogManager wal,
+        long metaPageId,
+        ReuseList reuseList,
+        FailureProcessor failureProcessor,
+        boolean initNew,
+        PageLockListener lockLsnr
+    ) throws IgniteCheckedException {
+        super(
+            TxLog.TX_LOG_CACHE_NAME,
+            TxLog.TX_LOG_CACHE_ID,
+            pageMem,
+            wal,
+            new AtomicLong(),
+            metaPageId,
+            reuseList,
+            TxLogInnerIO.VERSIONS,
+            TxLogLeafIO.VERSIONS,
+            failureProcessor,
+            lockLsnr
+        );
 
         initTree(initNew);
     }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/DataStructure.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/DataStructure.java
index 56842b3..944c27f 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/DataStructure.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/DataStructure.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
@@ -41,7 +41,7 @@ import static org.apache.ignite.internal.pagemem.PageIdUtils.MAX_ITEMID_NUM;
 /**
  * Base class for all the data structures based on {@link PageMemory}.
  */
-public abstract class DataStructure implements PageLockListener {
+public abstract class DataStructure {
     /** For tests. */
     public static Random rnd;
 
@@ -55,6 +55,9 @@ public abstract class DataStructure implements PageLockListener {
     protected final IgniteWriteAheadLogManager wal;
 
     /** */
+    protected final PageLockListener lockLsnr;
+
+    /** */
     protected ReuseList reuseList;
 
     /**
@@ -65,13 +68,15 @@ public abstract class DataStructure implements PageLockListener {
     public DataStructure(
         int cacheId,
         PageMemory pageMem,
-        IgniteWriteAheadLogManager wal
+        IgniteWriteAheadLogManager wal,
+        PageLockListener lockLsnr
     ) {
         assert pageMem != null;
 
         this.grpId = cacheId;
         this.pageMem = pageMem;
         this.wal = wal;
+        this.lockLsnr = lockLsnr == null ? NOOP_LSNR : lockLsnr;
     }
 
     /**
@@ -145,7 +150,7 @@ public abstract class DataStructure implements PageLockListener {
 
     /**
      * @param pageId Page ID.
-     * @param page  Page pointer.
+     * @param page Page pointer.
      */
     protected final void releasePage(long pageId, long page) {
         pageMem.releasePage(grpId, pageId, page);
@@ -157,7 +162,7 @@ public abstract class DataStructure implements PageLockListener {
      * @return Page address or {@code 0} if failed to lock due to recycling.
      */
     protected final long tryWriteLock(long pageId, long page) {
-        return PageHandler.writeLock(pageMem, grpId, pageId, page, this, true);
+        return PageHandler.writeLock(pageMem, grpId, pageId, page, lockLsnr, true);
     }
 
     /**
@@ -166,13 +171,12 @@ public abstract class DataStructure implements PageLockListener {
      * @return Page address.
      */
     protected final long writeLock(long pageId, long page) {
-        return PageHandler.writeLock(pageMem, grpId, pageId, page, this, false);
+        return PageHandler.writeLock(pageMem, grpId, pageId, page, lockLsnr, false);
     }
 
     /**
-     * <p>
-     * Note: Default WAL record policy will be used.
-     * </p>
+     * <p> Note: Default WAL record policy will be used. </p>
+     *
      * @param pageId Page ID
      * @param page Page pointer.
      * @param pageAddr Page address.
@@ -188,27 +192,27 @@ public abstract class DataStructure implements PageLockListener {
      * @return Page address.
      */
     protected final long readLock(long pageId, long page) {
-        return PageHandler.readLock(pageMem, grpId, pageId, page, this);
+        return PageHandler.readLock(pageMem, grpId, pageId, page, lockLsnr);
     }
 
     /**
      * @param pageId Page ID
      * @param page Page pointer.
-     * @param pageAddr  Page address.
+     * @param pageAddr Page address.
      */
     protected final void readUnlock(long pageId, long page, long pageAddr) {
-        PageHandler.readUnlock(pageMem, grpId, pageId, page, pageAddr, this);
+        PageHandler.readUnlock(pageMem, grpId, pageId, page, pageAddr, lockLsnr);
     }
 
     /**
      * @param pageId Page ID
      * @param page Page pointer.
-     * @param pageAddr  Page address.
+     * @param pageAddr Page address.
      * @param walPlc Full page WAL record policy.
      * @param dirty Dirty flag.
      */
     protected final void writeUnlock(long pageId, long page, long pageAddr, Boolean walPlc, boolean dirty) {
-        PageHandler.writeUnlock(pageMem, grpId, pageId, page, pageAddr, this, walPlc, dirty);
+        PageHandler.writeUnlock(pageMem, grpId, pageId, page, pageAddr, lockLsnr, walPlc, dirty);
     }
 
     /**
@@ -233,8 +237,10 @@ public abstract class DataStructure implements PageLockListener {
         long pageId,
         PageHandler<?, R> h,
         int intArg,
-        R lockFailed) throws IgniteCheckedException {
-        return PageHandler.writePage(pageMem, grpId, pageId, this, h, null, null, null, null, intArg, lockFailed);
+        R lockFailed
+    ) throws IgniteCheckedException {
+        return PageHandler.writePage(pageMem, grpId, pageId, lockLsnr, h,
+            null, null, null, null, intArg, lockFailed);
     }
 
     /**
@@ -251,8 +257,10 @@ public abstract class DataStructure implements PageLockListener {
         PageHandler<X, R> h,
         X arg,
         int intArg,
-        R lockFailed) throws IgniteCheckedException {
-        return PageHandler.writePage(pageMem, grpId, pageId, this, h, null, null, null, arg, intArg, lockFailed);
+        R lockFailed
+    ) throws IgniteCheckedException {
+        return PageHandler.writePage(pageMem, grpId, pageId, lockLsnr, h,
+            null, null, null, arg, intArg, lockFailed);
     }
 
     /**
@@ -271,8 +279,10 @@ public abstract class DataStructure implements PageLockListener {
         PageHandler<X, R> h,
         X arg,
         int intArg,
-        R lockFailed) throws IgniteCheckedException {
-        return PageHandler.writePage(pageMem, grpId, pageId, page, this, h, null, null, null, arg, intArg, lockFailed);
+        R lockFailed
+    ) throws IgniteCheckedException {
+        return PageHandler.writePage(pageMem, grpId, pageId, page, lockLsnr, h,
+            null, null, null, arg, intArg, lockFailed);
     }
 
     /**
@@ -291,8 +301,10 @@ public abstract class DataStructure implements PageLockListener {
         PageIO init,
         X arg,
         int intArg,
-        R lockFailed) throws IgniteCheckedException {
-        return PageHandler.writePage(pageMem, grpId, pageId, this, h, init, wal, null, arg, intArg, lockFailed);
+        R lockFailed
+    ) throws IgniteCheckedException {
+        return PageHandler.writePage(pageMem, grpId, pageId, lockLsnr, h,
+            init, wal, null, arg, intArg, lockFailed);
     }
 
     /**
@@ -309,8 +321,10 @@ public abstract class DataStructure implements PageLockListener {
         PageHandler<X, R> h,
         X arg,
         int intArg,
-        R lockFailed) throws IgniteCheckedException {
-        return PageHandler.readPage(pageMem, grpId, pageId, this, h, arg, intArg, lockFailed);
+        R lockFailed
+    ) throws IgniteCheckedException {
+        return PageHandler.readPage(pageMem, grpId, pageId, lockLsnr,
+            h, arg, intArg, lockFailed);
     }
 
     /**
@@ -329,8 +343,10 @@ public abstract class DataStructure implements PageLockListener {
         PageHandler<X, R> h,
         X arg,
         int intArg,
-        R lockFailed) throws IgniteCheckedException {
-        return PageHandler.readPage(pageMem, grpId, pageId, page, this, h, arg, intArg, lockFailed);
+        R lockFailed
+    ) throws IgniteCheckedException {
+        return PageHandler.readPage(pageMem, grpId, pageId, page, lockLsnr, h,
+            arg, intArg, lockFailed);
     }
 
     /**
@@ -339,7 +355,7 @@ public abstract class DataStructure implements PageLockListener {
      * @throws IgniteCheckedException if failed.
      */
     protected final void init(long pageId, PageIO init) throws IgniteCheckedException {
-        PageHandler.initPage(pageMem, grpId, pageId, init, wal, this);
+        PageHandler.initPage(pageMem, grpId, pageId, init, wal, lockLsnr);
     }
 
     /**
@@ -392,27 +408,30 @@ public abstract class DataStructure implements PageLockListener {
         return pageMem.realPageSize(grpId);
     }
 
-    @Override public void onBeforeWriteLock(int cacheId, long pageId, long page) {
-        // No-op.
-    }
+    /** No-op page lock listener. */
+    public static final PageLockListener NOOP_LSNR = new PageLockListener() {
+        @Override public void onBeforeWriteLock(int cacheId, long pageId, long page) {
+            // No-op.
+        }
 
-    @Override public void onWriteLock(int cacheId, long pageId, long page, long pageAddr) {
-        // No-op.
-    }
+        @Override public void onWriteLock(int cacheId, long pageId, long page, long pageAddr) {
+            // No-op.
+        }
 
-    @Override public void onWriteUnlock(int cacheId, long pageId, long page, long pageAddr) {
-        // No-op.
-    }
+        @Override public void onWriteUnlock(int cacheId, long pageId, long page, long pageAddr) {
+            // No-op.
+        }
 
-    @Override public void onBeforeReadLock(int cacheId, long pageId, long page) {
-        // No-op.
-    }
+        @Override public void onBeforeReadLock(int cacheId, long pageId, long page) {
+            // No-op.
+        }
 
-    @Override public void onReadLock(int cacheId, long pageId, long page, long pageAddr) {
-        // No-op.
-    }
+        @Override public void onReadLock(int cacheId, long pageId, long page, long pageAddr) {
+            // No-op.
+        }
 
-    @Override public void onReadUnlock(int cacheId, long pageId, long page, long pageAddr) {
-        // No-op.
-    }
+        @Override public void onReadUnlock(int cacheId, long pageId, long page, long pageAddr) {
+            // No-op.
+        }
+    };
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheOffheapManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheOffheapManager.java
index 23650ef..4dd24ba 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheOffheapManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheOffheapManager.java
@@ -49,6 +49,7 @@ import org.apache.ignite.internal.pagemem.wal.record.delta.MetaPageInitRecord;
 import org.apache.ignite.internal.pagemem.wal.record.delta.MetaPageUpdatePartitionDataRecord;
 import org.apache.ignite.internal.pagemem.wal.record.delta.PartitionDestroyRecord;
 import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
+import org.apache.ignite.internal.processors.cache.CacheDiagnosticManager;
 import org.apache.ignite.internal.processors.cache.CacheEntryPredicate;
 import org.apache.ignite.internal.processors.cache.CacheGroupContext;
 import org.apache.ignite.internal.processors.cache.CacheObject;
@@ -64,7 +65,7 @@ import org.apache.ignite.internal.processors.cache.distributed.dht.topology.Grid
 import org.apache.ignite.internal.processors.cache.distributed.dht.topology.GridDhtPartitionState;
 import org.apache.ignite.internal.processors.cache.mvcc.MvccSnapshot;
 import org.apache.ignite.internal.processors.cache.mvcc.MvccVersion;
-import org.apache.ignite.internal.processors.cache.persistence.freelist.CacheFreeListImpl;
+import org.apache.ignite.internal.processors.cache.persistence.freelist.CacheFreeList;
 import org.apache.ignite.internal.processors.cache.persistence.migration.UpgradePendingTreeToPerPartitionTask;
 import org.apache.ignite.internal.processors.cache.persistence.pagemem.PageMemoryEx;
 import org.apache.ignite.internal.processors.cache.persistence.partstate.GroupPartitionId;
@@ -126,18 +127,27 @@ public class GridCacheOffheapManager extends IgniteCacheOffheapManagerImpl imple
 
         Metas metas = getOrAllocateCacheMetas();
 
+        CacheDiagnosticManager diagnosticMgr = ctx.diagnostic();
+
+        String reuseListName = grp.cacheOrGroupName() + "##ReuseList";
+        String indexStorageTreeName = grp.cacheOrGroupName() + "##IndexStorageTree";
+
         RootPage reuseListRoot = metas.reuseListRoot;
 
-        reuseList = new ReuseListImpl(grp.groupId(),
+        reuseList = new ReuseListImpl(
+            grp.groupId(),
             grp.cacheOrGroupName(),
             grp.dataRegion().pageMemory(),
             ctx.wal(),
             reuseListRoot.pageId().pageId(),
-            reuseListRoot.isAllocated());
+            reuseListRoot.isAllocated(),
+            diagnosticMgr.pageLockTracker().createPageLockTracker(reuseListName)
+        );
 
         RootPage metastoreRoot = metas.treeRoot;
 
-        indexStorage = new IndexStorageImpl(grp.dataRegion().pageMemory(),
+        indexStorage = new IndexStorageImpl(
+            grp.dataRegion().pageMemory(),
             ctx.wal(),
             globalRemoveId(),
             grp.groupId(),
@@ -147,7 +157,9 @@ public class GridCacheOffheapManager extends IgniteCacheOffheapManagerImpl imple
             reuseList,
             metastoreRoot.pageId().pageId(),
             metastoreRoot.isAllocated(),
-            ctx.kernalContext().failure());
+            ctx.kernalContext().failure(),
+            diagnosticMgr.pageLockTracker().createPageLockTracker(indexStorageTreeName)
+        );
 
         ((GridCacheDatabaseSharedManager)ctx.database()).addCheckpointListener(this);
     }
@@ -264,7 +276,7 @@ public class GridCacheOffheapManager extends IgniteCacheOffheapManagerImpl imple
         RowStore rowStore0 = store.rowStore();
 
         if (rowStore0 != null) {
-            ((CacheFreeListImpl)rowStore0.freeList()).saveMetadata();
+            ((CacheFreeList)rowStore0.freeList()).saveMetadata();
 
             long updCntr = store.updateCounter();
             long size = store.fullSize();
@@ -1023,7 +1035,7 @@ public class GridCacheOffheapManager extends IgniteCacheOffheapManagerImpl imple
         for (CacheDataStore store : partDataStores.values()) {
             assert store instanceof GridCacheDataStore;
 
-            CacheFreeListImpl freeList = ((GridCacheDataStore)store).freeList;
+            CacheFreeList freeList = ((GridCacheDataStore)store).freeList;
 
             if (freeList == null)
                 continue;
@@ -1045,7 +1057,7 @@ public class GridCacheOffheapManager extends IgniteCacheOffheapManagerImpl imple
         for (CacheDataStore store : partDataStores.values()) {
             assert store instanceof GridCacheDataStore;
 
-            CacheFreeListImpl freeList = ((GridCacheDataStore)store).freeList;
+            CacheFreeList freeList = ((GridCacheDataStore)store).freeList;
 
             if (freeList == null)
                 continue;
@@ -1463,10 +1475,7 @@ public class GridCacheOffheapManager extends IgniteCacheOffheapManagerImpl imple
         private final int partId;
 
         /** */
-        private String name;
-
-        /** */
-        private volatile CacheFreeListImpl freeList;
+        private volatile CacheFreeList freeList;
 
         /** */
         private PendingEntriesTree pendingTree;
@@ -1502,8 +1511,34 @@ public class GridCacheOffheapManager extends IgniteCacheOffheapManagerImpl imple
         private GridCacheDataStore(int partId, boolean exists) {
             this.partId = partId;
             this.exists = exists;
+        }
 
-            name = treeName(partId);
+        /**
+         * @return Name of free pages list.
+         */
+        private String freeListName() {
+            return grp.cacheOrGroupName() + "-" + partId;
+        }
+
+        /**
+         * @return Name of partition meta store.
+         */
+        private String partitionMetaStoreName() {
+            return grp.cacheOrGroupName() + "-partstore-" + partId;
+        }
+
+        /**
+         * @return Name of data tree.
+         */
+        private String dataTreeName() {
+            return grp.cacheOrGroupName() + "-" + treeName(partId);
+        }
+
+        /**
+         * @return Name of pending entires tree.
+         */
+        private String pendingEntriesTreeName() {
+            return grp.cacheOrGroupName() + "-" +"PendingEntries-" + partId;
         }
 
         /**
@@ -1538,17 +1573,21 @@ public class GridCacheOffheapManager extends IgniteCacheOffheapManagerImpl imple
                             ", metas=" + metas + ']');
                     }
 
+                    String freeListName = freeListName();
+
                     RootPage reuseRoot = metas.reuseListRoot;
 
-                    freeList = new CacheFreeListImpl(
+                    freeList = new CacheFreeList(
                         grp.groupId(),
-                        grp.cacheOrGroupName() + "-" + partId,
+                        freeListName,
                         grp.dataRegion().memoryMetrics(),
                         grp.dataRegion(),
                         null,
                         ctx.wal(),
                         reuseRoot.pageId().pageId(),
-                        reuseRoot.isAllocated()) {
+                        reuseRoot.isAllocated(),
+                        ctx.diagnostic().pageLockTracker().createPageLockTracker(freeListName)
+                    ) {
                         /** {@inheritDoc} */
                         @Override protected long allocatePageNoReuse() throws IgniteCheckedException {
                             assert grp.shared().database().checkpointLockIsHeldByThread();
@@ -1556,6 +1595,7 @@ public class GridCacheOffheapManager extends IgniteCacheOffheapManagerImpl imple
                             return pageMem.allocatePage(grpId, partId, PageIdAllocator.FLAG_DATA);
                         }
                     };
+                    String dataTreeName = dataTreeName();
 
                     CacheDataRowStore rowStore = new CacheDataRowStore(grp, freeList, partId);
 
@@ -1563,11 +1603,13 @@ public class GridCacheOffheapManager extends IgniteCacheOffheapManagerImpl imple
 
                     CacheDataTree dataTree = new CacheDataTree(
                         grp,
-                        name,
+                        dataTreeName,
                         freeList,
                         rowStore,
                         treeRoot.pageId().pageId(),
-                        treeRoot.isAllocated()) {
+                        treeRoot.isAllocated(),
+                        ctx.diagnostic().pageLockTracker().createPageLockTracker(dataTreeName)
+                    ) {
                         /** {@inheritDoc} */
                         @Override protected long allocatePageNoReuse() throws IgniteCheckedException {
                             assert grp.shared().database().checkpointLockIsHeldByThread();
@@ -1576,15 +1618,19 @@ public class GridCacheOffheapManager extends IgniteCacheOffheapManagerImpl imple
                         }
                     };
 
+                    String pendingEntriesTreeName = pendingEntriesTreeName();
+
                     RootPage pendingTreeRoot = metas.pendingTreeRoot;
 
                     final PendingEntriesTree pendingTree0 = new PendingEntriesTree(
                         grp,
-                        "PendingEntries-" + partId,
+                        pendingEntriesTreeName,
                         grp.dataRegion().pageMemory(),
                         pendingTreeRoot.pageId().pageId(),
                         freeList,
-                        pendingTreeRoot.isAllocated()) {
+                        pendingTreeRoot.isAllocated(),
+                        ctx.diagnostic().pageLockTracker().createPageLockTracker(pendingEntriesTreeName)
+                    ) {
                         /** {@inheritDoc} */
                         @Override protected long allocatePageNoReuse() throws IgniteCheckedException {
                             assert grp.shared().database().checkpointLockIsHeldByThread();
@@ -1595,7 +1641,7 @@ public class GridCacheOffheapManager extends IgniteCacheOffheapManagerImpl imple
 
                     PageMemoryEx pageMem = (PageMemoryEx)grp.dataRegion().pageMemory();
 
-                    delegate0 = new CacheDataStoreImpl(partId, name, rowStore, dataTree) {
+                    delegate0 = new CacheDataStoreImpl(partId, rowStore, dataTree) {
                         /** {@inheritDoc} */
                         @Override public PendingEntriesTree pendingTree() {
                             return pendingTree0;
@@ -1802,11 +1848,6 @@ public class GridCacheOffheapManager extends IgniteCacheOffheapManagerImpl imple
         }
 
         /** {@inheritDoc} */
-        @Override public String name() {
-            return name;
-        }
-
-        /** {@inheritDoc} */
         @Override public RowStore rowStore() {
             CacheDataStore delegate0 = delegate;
 
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IgniteCacheDatabaseSharedManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IgniteCacheDatabaseSharedManager.java
index 704255e..1efe385 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IgniteCacheDatabaseSharedManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IgniteCacheDatabaseSharedManager.java
@@ -58,11 +58,12 @@ import org.apache.ignite.internal.processors.cache.persistence.evict.PageEvictio
 import org.apache.ignite.internal.processors.cache.persistence.evict.Random2LruPageEvictionTracker;
 import org.apache.ignite.internal.processors.cache.persistence.evict.RandomLruPageEvictionTracker;
 import org.apache.ignite.internal.processors.cache.persistence.filename.PdsFolderSettings;
-import org.apache.ignite.internal.processors.cache.persistence.freelist.CacheFreeListImpl;
+import org.apache.ignite.internal.processors.cache.persistence.freelist.CacheFreeList;
 import org.apache.ignite.internal.processors.cache.persistence.freelist.FreeList;
 import org.apache.ignite.internal.processors.cache.persistence.metastorage.MetaStorage;
 import org.apache.ignite.internal.processors.cache.persistence.metastorage.MetastorageLifecycleListener;
 import org.apache.ignite.internal.processors.cache.persistence.tree.reuse.ReuseList;
+import org.apache.ignite.internal.processors.cache.persistence.tree.util.PageLockListener;
 import org.apache.ignite.internal.processors.cluster.IgniteChangeGlobalStateSupport;
 import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.internal.CU;
@@ -118,10 +119,10 @@ public class IgniteCacheDatabaseSharedManager extends GridCacheSharedManagerAdap
     protected DataRegion dfltDataRegion;
 
     /** */
-    protected Map<String, CacheFreeListImpl> freeListMap;
+    protected Map<String, CacheFreeList> freeListMap;
 
     /** */
-    private CacheFreeListImpl dfltFreeList;
+    private CacheFreeList dfltFreeList;
 
     /** Page size from memory configuration, may be set only for fake(standalone) IgniteCacheDataBaseSharedManager */
     private int pageSize;
@@ -244,18 +245,25 @@ public class IgniteCacheDatabaseSharedManager extends GridCacheSharedManagerAdap
         for (DataRegion memPlc : dataRegionMap.values()) {
             DataRegionConfiguration memPlcCfg = memPlc.config();
 
-            DataRegionMetricsImpl memMetrics = (DataRegionMetricsImpl) memMetricsMap.get(memPlcCfg.getName());
+            DataRegionMetricsImpl memMetrics = (DataRegionMetricsImpl)memMetricsMap.get(memPlcCfg.getName());
 
             boolean persistenceEnabled = memPlcCfg.isPersistenceEnabled();
 
-            CacheFreeListImpl freeList = new CacheFreeListImpl(0,
-                    cctx.igniteInstanceName(),
-                    memMetrics,
-                    memPlc,
-                    null,
-                    persistenceEnabled ? cctx.wal() : null,
-                    0L,
-                    true);
+            String freeListName = memPlcCfg.getName() + "##FreeList";
+
+            PageLockListener lsnr = cctx.diagnostic().pageLockTracker().createPageLockTracker(freeListName);
+
+            CacheFreeList freeList = new CacheFreeList(
+                0,
+                freeListName,
+                memMetrics,
+                memPlc,
+                null,
+                persistenceEnabled ? cctx.wal() : null,
+                0L,
+                true,
+                lsnr
+            );
 
             freeListMap.put(memPlcCfg.getName(), freeList);
         }
@@ -382,11 +390,11 @@ public class IgniteCacheDatabaseSharedManager extends GridCacheSharedManagerAdap
         final String dataRegName = dataRegCfg.getName();
 
         return new IgniteOutClosure<Long>() {
-            private CacheFreeListImpl freeList;
+            private CacheFreeList freeList;
 
             @Override public Long apply() {
                 if (freeList == null) {
-                    CacheFreeListImpl freeList0 = freeListMap.get(dataRegName);
+                    CacheFreeList freeList0 = freeListMap.get(dataRegName);
 
                     if (freeList0 == null)
                         return 0L;
@@ -409,9 +417,9 @@ public class IgniteCacheDatabaseSharedManager extends GridCacheSharedManagerAdap
         final String dataRegName = dataRegCfg.getName();
 
         return new DataRegionMetricsProvider() {
-            private CacheFreeListImpl freeList;
+            private CacheFreeList freeList;
 
-            private CacheFreeListImpl getFreeList() {
+            private CacheFreeList getFreeList() {
                 if (freeList == null)
                     freeList = freeListMap.get(dataRegName);
 
@@ -419,13 +427,13 @@ public class IgniteCacheDatabaseSharedManager extends GridCacheSharedManagerAdap
             }
 
             @Override public long partiallyFilledPagesFreeSpace() {
-                CacheFreeListImpl freeList0 = getFreeList();
+                CacheFreeList freeList0 = getFreeList();
 
                 return freeList0 == null ? 0L : freeList0.freeSpace();
             }
 
             @Override public long emptyDataPages() {
-                CacheFreeListImpl freeList0 = getFreeList();
+                CacheFreeList freeList0 = getFreeList();
 
                 return freeList0 == null ? 0L : freeList0.emptyDataPages();
             }
@@ -698,7 +706,7 @@ public class IgniteCacheDatabaseSharedManager extends GridCacheSharedManagerAdap
      */
     public void dumpStatistics(IgniteLogger log) {
         if (freeListMap != null) {
-            for (CacheFreeListImpl freeList : freeListMap.values())
+            for (CacheFreeList freeList : freeListMap.values())
                 freeList.dumpStatistics(log);
         }
     }
@@ -991,12 +999,12 @@ public class IgniteCacheDatabaseSharedManager extends GridCacheSharedManagerAdap
 
         int sysPageSize = pageMem.systemPageSize();
 
-        CacheFreeListImpl freeListImpl = freeListMap.get(plcCfg.getName());
+        CacheFreeList freeList = freeListMap.get(plcCfg.getName());
 
         for (;;) {
             long allocatedPagesCnt = pageMem.loadedPages();
 
-            int emptyDataPagesCnt = freeListImpl.emptyDataPages();
+            int emptyDataPagesCnt = freeList.emptyDataPages();
 
             boolean shouldEvict = allocatedPagesCnt > (memorySize / sysPageSize * plcCfg.getEvictionThreshold()) &&
                 emptyDataPagesCnt < plcCfg.getEmptyPagesPoolSize();
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IndexStorageImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IndexStorageImpl.java
index 4a27140..9415a01 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IndexStorageImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IndexStorageImpl.java
@@ -33,6 +33,7 @@ import org.apache.ignite.internal.processors.cache.persistence.tree.io.BPlusLeaf
 import org.apache.ignite.internal.processors.cache.persistence.tree.io.IOVersions;
 import org.apache.ignite.internal.processors.cache.persistence.tree.reuse.ReuseList;
 import org.apache.ignite.internal.processors.cache.persistence.tree.util.PageHandler;
+import org.apache.ignite.internal.processors.cache.persistence.tree.util.PageLockListener;
 import org.apache.ignite.internal.processors.failure.FailureProcessor;
 import org.apache.ignite.internal.util.lang.GridCursor;
 import org.apache.ignite.internal.util.typedef.internal.U;
@@ -87,7 +88,8 @@ public class IndexStorageImpl implements IndexStorage {
         final ReuseList reuseList,
         final long rootPageId,
         final boolean initNew,
-        final FailureProcessor failureProcessor
+        final FailureProcessor failureProcessor,
+        final PageLockListener lockLsnr
     ) {
         try {
             this.pageMem = pageMem;
@@ -97,8 +99,21 @@ public class IndexStorageImpl implements IndexStorage {
             this.allocSpace = allocSpace;
             this.reuseList = reuseList;
 
-            metaTree = new MetaTree(grpId, allocPartId, allocSpace, pageMem, wal, globalRmvId, rootPageId,
-                reuseList, MetaStoreInnerIO.VERSIONS, MetaStoreLeafIO.VERSIONS, initNew, failureProcessor);
+            metaTree = new MetaTree(
+                grpId,
+                allocPartId,
+                allocSpace,
+                pageMem,
+                wal,
+                globalRmvId,
+                rootPageId,
+                reuseList,
+                MetaStoreInnerIO.VERSIONS,
+                MetaStoreLeafIO.VERSIONS,
+                initNew,
+                failureProcessor,
+                lockLsnr
+            );
         }
         catch (IgniteCheckedException e) {
             throw new IgniteException(e);
@@ -237,9 +252,22 @@ public class IndexStorageImpl implements IndexStorage {
             final IOVersions<? extends BPlusInnerIO<IndexItem>> innerIos,
             final IOVersions<? extends BPlusLeafIO<IndexItem>> leafIos,
             final boolean initNew,
-            @Nullable FailureProcessor failureProcessor
+            @Nullable FailureProcessor failureProcessor,
+            @Nullable PageLockListener lockLsnr
         ) throws IgniteCheckedException {
-            super(treeName("meta", "Meta"), cacheId, pageMem, wal, globalRmvId, metaPageId, reuseList, innerIos, leafIos, failureProcessor);
+            super(
+                treeName("meta", "Meta"),
+                cacheId,
+                pageMem,
+                wal,
+                globalRmvId,
+                metaPageId,
+                reuseList,
+                innerIos,
+                leafIos,
+                failureProcessor,
+                lockLsnr
+            );
 
             this.allocPartId = allocPartId;
             this.allocSpace = allocSpace;
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/DumpProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/DumpProcessor.java
new file mode 100644
index 0000000..8600d34
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/DumpProcessor.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.persistence.diagnostic.pagelocktracker;
+
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.log.PageLockLogSnapshot;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.stack.PageLockStackSnapshot;
+
+/**
+ * Dump processor.
+ */
+public interface DumpProcessor {
+    /**
+     * @param snapshot Process lock log snapshot.
+     */
+    void processDump(PageLockLogSnapshot snapshot);
+
+    /**
+     * @param snapshot Process lock stack snapshot.
+     */
+    void processDump(PageLockStackSnapshot snapshot);
+
+    /**
+     * @param snapshot Process lock thread dump snapshot.
+     */
+    void processDump(ThreadPageLocksDumpLock snapshot);
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/DumpSupported.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/DumpSupported.java
new file mode 100644
index 0000000..814c2c3
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/DumpSupported.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.persistence.diagnostic.pagelocktracker;
+
+import org.apache.ignite.lang.IgniteFuture;
+
+/**
+ * Interface for all page lock tracker entries which support dumping.
+ */
+public interface DumpSupported<T extends PageLockDump> {
+    /** */
+    boolean acquireSafePoint();
+
+    /** */
+    boolean releaseSafePoint();
+
+    /**
+     * Create dump.
+     */
+    T dump();
+
+    /**
+     * Create dump async.
+     *
+     * @return Ignite future.
+     */
+    IgniteFuture<T> dumpSync();
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/InvalidContext.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/InvalidContext.java
new file mode 100644
index 0000000..b27ca40
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/InvalidContext.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.persistence.diagnostic.pagelocktracker;
+
+/**
+ * Failure context if any invariant is not satisfied.
+ */
+public class InvalidContext<T extends PageLockDump> {
+    /** */
+    public final String msg;
+    /** */
+    public final T dump;
+
+    /** */
+    public InvalidContext(String msg, T dump) {
+        this.msg = msg;
+        this.dump = dump;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return "Error: " + msg + "\n" + dump.toString();
+    }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/LockTrackerFactory.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/LockTrackerFactory.java
new file mode 100644
index 0000000..ffcc5a4
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/LockTrackerFactory.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.persistence.diagnostic.pagelocktracker;
+
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageLockTrackerManager.MemoryCalculator;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.log.LockLog;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.stack.LockStack;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.store.HeapPageMetaInfoStore;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.store.OffHeapPageMetaInfoStore;
+
+import static java.lang.String.valueOf;
+import static org.apache.ignite.IgniteSystemProperties.IGNITE_PAGE_LOCK_TRACKER_CAPACITY;
+import static org.apache.ignite.IgniteSystemProperties.IGNITE_PAGE_LOCK_TRACKER_TYPE;
+import static org.apache.ignite.IgniteSystemProperties.getInteger;
+
+/**
+ * Page lock tracker factory.
+ *
+ * 1 - HEAP_STACK
+ * 2 - HEAP_LOG
+ * 3 - OFF_HEAP_STACK
+ * 4 - OFF_HEAP_LOG
+ */
+public final class LockTrackerFactory {
+    /**
+     *
+     */
+    public static final int HEAP_STACK = 1;
+    /**
+     *
+     */
+    public static final int HEAP_LOG = 2;
+    /**
+     *
+     */
+    public static final int OFF_HEAP_STACK = 3;
+    /**
+     *
+     */
+    public static final int OFF_HEAP_LOG = 4;
+
+    /**
+     *
+     */
+    public static volatile int DEFAULT_CAPACITY = getInteger(IGNITE_PAGE_LOCK_TRACKER_CAPACITY, 512);
+    /**
+     *
+     */
+    public static volatile int DEFAULT_TYPE = getInteger(IGNITE_PAGE_LOCK_TRACKER_TYPE, HEAP_LOG);
+
+    /**
+     * @param name Page lock tracker name.
+     */
+    public static PageLockTracker<? extends PageLockDump> create(String name) {
+        return create(DEFAULT_TYPE, name);
+    }
+
+    /**
+     * @param name Page lock tracker name.
+     * @param type Page lock tracker type.
+     */
+    public static PageLockTracker<? extends PageLockDump> create(int type, String name) {
+        return create(type, name, DEFAULT_CAPACITY);
+    }
+
+    /**
+     * @param name Page lock tracker name.
+     * @param type Page lock tracker type.
+     * @param size Page lock tracker size (capacity).
+     */
+    public static PageLockTracker<? extends PageLockDump> create(int type, String name, int size) {
+        return create(type, size, name, new MemoryCalculator());
+    }
+
+    /**
+     * @param name Page lock tracker name.
+     * @param type Page lock tracker type.
+     * @param size Page lock tracker size (capacity).
+     */
+    public static PageLockTracker<? extends PageLockDump> create(
+        int type,
+        int size,
+        String name,
+        MemoryCalculator memCalc
+    ) {
+        switch (type) {
+            case HEAP_STACK:
+                return new LockStack(name, new HeapPageMetaInfoStore(size, memCalc), memCalc);
+            case HEAP_LOG:
+                return new LockLog(name, new HeapPageMetaInfoStore(size, memCalc), memCalc);
+            case OFF_HEAP_STACK:
+                return new LockStack(name, new OffHeapPageMetaInfoStore(size, memCalc), memCalc);
+            case OFF_HEAP_LOG:
+                return new LockLog(name, new OffHeapPageMetaInfoStore(size, memCalc), memCalc);
+
+            default:
+                throw new IllegalArgumentException(valueOf(type));
+        }
+    }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/PageLockDump.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/PageLockDump.java
new file mode 100644
index 0000000..e5f2856
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/PageLockDump.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.persistence.diagnostic.pagelocktracker;
+
+/**
+ * Interface for page lock tracker structures dump.
+ */
+public interface PageLockDump {
+    /**
+     * @param dumpProcessort Apply dump processor.
+     */
+    void apply(DumpProcessor dumpProcessort);
+
+    /**
+     * @return Dump creation time.
+     */
+    long time();
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/PageLockListenerIndexAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/PageLockListenerIndexAdapter.java
new file mode 100644
index 0000000..5f0d4d0
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/PageLockListenerIndexAdapter.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.persistence.diagnostic.pagelocktracker;
+
+import org.apache.ignite.internal.processors.cache.persistence.tree.util.PageLockListener;
+
+/**
+ * Page lock listener adapter with Id.
+ */
+public class PageLockListenerIndexAdapter implements PageLockListener {
+    /** Adapter id. */
+    private final int id;
+
+    /** Real listener. */
+    private final PageLockListener delegate;
+
+    /**
+     * @param id Adapter id.
+     * @param delegate Real listener.
+     */
+    public PageLockListenerIndexAdapter(int id, PageLockListener delegate) {
+        this.id = id;
+        this.delegate = delegate;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void onBeforeWriteLock(int cacheId, long pageId, long page) {
+        delegate.onBeforeWriteLock(id, pageId, page);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void onWriteLock(int cacheId, long pageId, long page, long pageAddr) {
+        delegate.onWriteLock(id, pageId, page, pageAddr);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void onWriteUnlock(int cacheId, long pageId, long page, long pageAddr) {
+        delegate.onWriteUnlock(id, pageId, page, pageAddr);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void onBeforeReadLock(int cacheId, long pageId, long page) {
+        delegate.onBeforeReadLock(id, pageId, page);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void onReadLock(int cacheId, long pageId, long page, long pageAddr) {
+        delegate.onReadLock(id, pageId, page, pageAddr);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void onReadUnlock(int cacheId, long pageId, long page, long pageAddr) {
+        delegate.onReadUnlock(id, pageId, page, pageAddr);
+    }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/PageLockTracker.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/PageLockTracker.java
new file mode 100644
index 0000000..8517340
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/PageLockTracker.java
@@ -0,0 +1,365 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.persistence.diagnostic.pagelocktracker;
+
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageLockTrackerManager.MemoryCalculator;
+import org.apache.ignite.internal.processors.cache.persistence.tree.util.PageLockListener;
+import org.apache.ignite.lang.IgniteFuture;
+
+import static org.apache.ignite.internal.pagemem.PageIdUtils.flag;
+import static org.apache.ignite.internal.pagemem.PageIdUtils.pageIndex;
+import static org.apache.ignite.internal.pagemem.PageIdUtils.partId;
+import static org.apache.ignite.internal.util.IgniteUtils.hexInt;
+import static org.apache.ignite.internal.util.IgniteUtils.hexLong;
+
+/**
+ * Abstract page lock tracker.
+ */
+public abstract class PageLockTracker<T extends PageLockDump> implements PageLockListener, DumpSupported<T> {
+    /** */
+    private static final long OVERHEAD_SIZE = 16 + 8 + 8 + 4 + 4 + 4 + 8 + 8 + 4 + 4 + 8;
+    /** */
+    public static final int OP_OFFSET = 16;
+    /** */
+    public static final int LOCK_IDX_MASK = 0xFFFF0000;
+    /** */
+    public static final int LOCK_OP_MASK = 0x000000000000FF;
+
+    /** Page read lock operation id. */
+    public static final int READ_LOCK = 1;
+    /** Page read unlock operation id. */
+    public static final int READ_UNLOCK = 2;
+    /** Page write lock operation id. */
+    public static final int WRITE_LOCK = 3;
+    /** Page write unlock operation id. */
+    public static final int WRITE_UNLOCK = 4;
+    /** Page read before lock operation id. */
+    public static final int BEFORE_READ_LOCK = 5;
+    /** Page write before lock operation id. */
+    public static final int BEFORE_WRITE_LOCK = 6;
+
+    /** */
+    protected final String name;
+    /** */
+    protected final PageMetaInfoStore pages;
+    /** Counter for track lock/unlock operations. */
+    protected int heldLockCnt;
+    /** */
+    protected int nextOp;
+    /** */
+    protected int nextOpStructureId;
+    /** */
+    protected long nextOpPageId;
+    /** */
+    private long opCntr;
+    /** */
+    private volatile boolean dump;
+    /** */
+    private volatile boolean locked;
+    /** */
+    private volatile InvalidContext<T> invalidCtx;
+
+    /**
+     *
+     */
+    protected PageLockTracker(String name, PageMetaInfoStore pages, MemoryCalculator memCalc) {
+        this.name = name;
+        this.pages = pages;
+
+        memCalc.onHeapAllocated(OVERHEAD_SIZE);
+    }
+
+    /** */
+    public void onBeforeWriteLock0(int structureId, long pageId, long page) {
+        this.nextOp = BEFORE_WRITE_LOCK;
+        this.nextOpStructureId = structureId;
+        this.nextOpPageId = pageId;
+    }
+
+    /** */
+    public void onBeforeReadLock0(int structureId, long pageId, long page) {
+        this.nextOp = BEFORE_READ_LOCK;
+        this.nextOpStructureId = structureId;
+        this.nextOpPageId = pageId;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void onBeforeWriteLock(int structureId, long pageId, long page) {
+        if (isInvalid())
+            return;
+
+        lock();
+
+        try {
+            onBeforeWriteLock0(structureId, pageId, page);
+        }
+        finally {
+            unLock();
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public void onWriteLock(int structureId, long pageId, long page, long pageAddr) {
+        if (checkFailedLock(pageAddr) || isInvalid())
+            return;
+
+        lock();
+
+        try {
+            onWriteLock0(structureId, pageId, page, pageAddr);
+        }
+        finally {
+            unLock();
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public void onWriteUnlock(int structureId, long pageId, long page, long pageAddr) {
+        if (isInvalid())
+            return;
+
+        lock();
+
+        try {
+            onWriteUnlock0(structureId, pageId, page, pageAddr);
+        }
+        finally {
+            unLock();
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public void onBeforeReadLock(int structureId, long pageId, long page) {
+        if (isInvalid())
+            return;
+
+        lock();
+
+        try {
+            onBeforeReadLock0(structureId, pageId, page);
+        }
+        finally {
+            unLock();
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public void onReadLock(int structureId, long pageId, long page, long pageAddr) {
+        if (checkFailedLock(pageAddr) ||isInvalid())
+            return;
+
+        lock();
+
+        try {
+            onReadLock0(structureId, pageId, page, pageAddr);
+        }
+        finally {
+            unLock();
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public void onReadUnlock(int structureId, long pageId, long page, long pageAddr) {
+        if (isInvalid())
+            return;
+
+        lock();
+
+        try {
+            onReadUnlock0(structureId, pageId, page, pageAddr);
+        }
+        finally {
+            unLock();
+        }
+    }
+
+    /** */
+    public abstract void onWriteLock0(int structureId, long pageId, long page, long pageAddr);
+
+    /** */
+    public abstract void onWriteUnlock0(int structureId, long pageId, long page, long pageAddr);
+
+    /** */
+    public abstract void onReadLock0(int structureId, long pageId, long page, long pageAddr);
+
+    /** */
+    public abstract void onReadUnlock0(int structureId, long pageId, long page, long pageAddr);
+
+    /** */
+    public boolean isInvalid() {
+        return invalidCtx != null;
+    }
+
+    /** */
+    private boolean checkFailedLock(long pageAddr){
+        if (pageAddr == 0) {
+            this.nextOp = 0;
+            this.nextOpStructureId = 0;
+            this.nextOpPageId = 0;
+
+            return true;
+        }
+
+        return false;
+    }
+
+    /** */
+    public InvalidContext<T> invalidContext() {
+        return invalidCtx;
+    }
+
+    /** */
+    protected void free(){
+        pages.free();
+    }
+
+    /** */
+    protected void invalid(String msg) {
+        T dump = snapshot();
+
+        invalidCtx = new InvalidContext<>(msg, dump);
+    }
+
+    /** */
+    private void lock() {
+        while (!lock0()) {
+            // Busy wait.
+        }
+    }
+
+    /** */
+    private boolean lock0() {
+        awaitDump();
+
+        locked = true;
+        if (dump) {
+            locked = false;
+
+            return false;
+        }
+
+        return true;
+    }
+
+    /** */
+    private void unLock() {
+        opCntr++;
+
+        locked = false;
+    }
+
+    /** */
+    private void awaitDump() {
+        while (dump) {
+            // Busy wait.
+        }
+    }
+
+    /** */
+    private void awaitLocks() {
+        while (locked) {
+            // Busy wait.
+        }
+    }
+
+    /**
+     * @return Number of locks operations.
+     */
+    public long operationsCounter(){
+        // Read  volatile for thread safety.
+        boolean locked = this.locked;
+
+        return opCntr;
+    }
+
+    /**
+     *
+     */
+    public int heldLocksNumber() {
+        // Read  volatile for thread safety.
+        boolean locked = this.locked;
+
+        return heldLockCnt;
+    }
+
+    /** */
+    protected boolean validateOperation(int structureId, long pageId, int op) {
+        if (nextOpStructureId == 0 || nextOp == 0 || nextOpPageId == 0)
+            return true;
+
+        if ((op == READ_LOCK && nextOp != BEFORE_READ_LOCK) ||
+            (op == WRITE_LOCK && nextOp != BEFORE_WRITE_LOCK) ||
+            (structureId != nextOpStructureId) ||
+            (pageId != nextOpPageId)) {
+
+            invalid("Unepected operation: " +
+                "exp=" + argsToString(nextOpStructureId, nextOpPageId, nextOp) + "," +
+                "actl=" + argsToString(structureId, pageId, op)
+            );
+
+            return false;
+        }
+
+        return true;
+    }
+
+    /** */
+    protected abstract T snapshot();
+
+    /** {@inheritDoc} */
+    @Override public synchronized boolean acquireSafePoint() {
+        return dump ? false : (dump = true);
+
+    }
+
+    /** {@inheritDoc} */
+    @Override public synchronized boolean releaseSafePoint() {
+        return !dump ? false : !(dump = false);
+    }
+
+    /** {@inheritDoc} */
+    @Override public synchronized T dump() {
+        boolean needRelease = acquireSafePoint();
+
+        awaitLocks();
+
+        T dump0 = snapshot();
+
+        if (needRelease)
+            releaseSafePoint();
+
+        return dump0;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteFuture<T> dumpSync() {
+        throw new UnsupportedOperationException();
+    }
+
+    /** */
+    public static String argsToString(int structureId, long pageId, int flags) {
+        return "[structureId=" + structureId + ", pageId" + pageIdToString(pageId) + "]";
+    }
+
+    /** */
+    public static String pageIdToString(long pageId) {
+        return "pageId=" + pageId
+            + " [pageIdHex=" + hexLong(pageId)
+            + ", partId=" + partId(pageId) + ", pageIdx=" + pageIndex(pageId)
+            + ", flags=" + hexInt(flag(pageId)) + "]";
+    }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/PageLockTrackerMXBean.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/PageLockTrackerMXBean.java
new file mode 100644
index 0000000..d9ed7d6
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/PageLockTrackerMXBean.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.persistence.diagnostic.pagelocktracker;
+
+import org.apache.ignite.mxbean.MXBeanDescription;
+
+/**
+ * This interface defines JMX managment interface for page lock tracking.
+ */
+@MXBeanDescription("MBean that provides access to page lock tracking.")
+public interface PageLockTrackerMXBean {
+    /** */
+    public static final String MBEAN_NAME = "PageLockTracker";
+    /**
+     * Take page locks dump.
+     *
+     * @return String representation of page locks dump.
+     */
+    @MXBeanDescription("Take page locks dump.")
+    String dumpLocks();
+
+    /**
+     * Take page locks dump and print it to console.
+     */
+    @MXBeanDescription("Take page locks dump and print it to console.")
+    void dumpLocksToLog();
+
+    /**
+     * Take page locks dump and save to file.
+     *
+     * @return Absolute file path.
+     */
+    @MXBeanDescription("Take page locks dump and save to file.")
+    String dumpLocksToFile();
+
+    /**
+     * Take page locks dump and save to file for specific path.
+     *
+     * @param path Path to save file.
+     * @return Absolute file path.
+     */
+    @MXBeanDescription("Take page locks dump and save to file for specific path.")
+    String dumpLocksToFile(String path);
+}
\ No newline at end of file
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/PageLockTrackerMXBeanImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/PageLockTrackerMXBeanImpl.java
new file mode 100644
index 0000000..db91457
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/PageLockTrackerMXBeanImpl.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.persistence.diagnostic.pagelocktracker;
+
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageLockTrackerManager.MemoryCalculator;
+
+/**
+ * Implementation of {@link PageLockTrackerMXBean}.
+ */
+public class PageLockTrackerMXBeanImpl implements PageLockTrackerMXBean {
+    /** */
+    private static final long OVERHEAD_SIZE = 16 + 8;
+
+    /** Page lock tracker manager */
+    private final PageLockTrackerManager mgr;
+
+    /**
+     * @param mgr Page lock tracker manager.
+     */
+    public PageLockTrackerMXBeanImpl(PageLockTrackerManager mgr, MemoryCalculator memoryCalculator) {
+        this.mgr = mgr;
+
+        memoryCalculator.onHeapAllocated(OVERHEAD_SIZE);
+    }
+
+    /** {@inheritDoc} */
+    @Override public String dumpLocks() {
+        return mgr.dumpLocks();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void dumpLocksToLog() {
+        mgr.dumpLocksToLog();
+    }
+
+    /** {@inheritDoc} */
+    @Override public String dumpLocksToFile() {
+        return mgr.dumpLocksToFile();
+    }
+
+    /** {@inheritDoc} */
+    @Override public String dumpLocksToFile(String path) {
+        return mgr.dumpLocksToFile(path);
+    }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/PageLockTrackerManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/PageLockTrackerManager.java
new file mode 100644
index 0000000..c48d38c
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/PageLockTrackerManager.java
@@ -0,0 +1,270 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.persistence.diagnostic.pagelocktracker;
+
+import java.io.File;
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.atomic.AtomicLong;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.internal.processors.cache.persistence.DataStructure;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.SharedPageLockTracker.State;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.dumpprocessors.ToFileDumpProcessor;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.dumpprocessors.ToStringDumpProcessor;
+import org.apache.ignite.internal.processors.cache.persistence.tree.util.PageLockListener;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.lifecycle.LifecycleAware;
+import org.jetbrains.annotations.NotNull;
+
+import static org.apache.ignite.IgniteSystemProperties.IGNITE_PAGE_LOCK_TRACKER_TYPE;
+import static org.apache.ignite.IgniteSystemProperties.getInteger;
+import static org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.LockTrackerFactory.HEAP_LOG;
+
+/**
+ * Page lock manager.
+ */
+public class PageLockTrackerManager implements LifecycleAware {
+    /** */
+    private static final long OVERHEAD_SIZE = 16 + 8  + 8 + 8 + 8;
+
+    /** */
+    private final MemoryCalculator memoryCalculator = new MemoryCalculator();
+
+    /** MXbean */
+    private final PageLockTrackerMXBean mxBean;
+
+    /** */
+    private final SharedPageLockTracker sharedPageLockTracker;
+
+    /** */
+    private final IgniteLogger log;
+
+    /** */
+    private Set<State> threads;
+
+    /** */
+    private final String managerNameId;
+
+    /** */
+    private final boolean trackingEnable;
+
+
+    /**
+     * Default constructor.
+     */
+    public PageLockTrackerManager(IgniteLogger log) {
+        this(log, "mgr_" + UUID.randomUUID().toString());
+    }
+
+    /**
+     * Default constructor.
+     */
+    public PageLockTrackerManager(IgniteLogger log, String managerNameId) {
+        this.trackingEnable = !(getInteger(IGNITE_PAGE_LOCK_TRACKER_TYPE, HEAP_LOG) == -1);
+        this.managerNameId = managerNameId;
+        this.mxBean = new PageLockTrackerMXBeanImpl(this, memoryCalculator);
+        this.sharedPageLockTracker = new SharedPageLockTracker(this::onHangThreads, memoryCalculator);
+        this.log = log;
+
+        memoryCalculator.onHeapAllocated(OVERHEAD_SIZE);
+    }
+
+    /**
+     * @param threads Hang threads.
+     */
+    private void onHangThreads(@NotNull Set<State> threads) {
+        assert threads != null;
+
+        // Processe only one for same list thread state.
+        // Protection of spam.
+        if (!threads.equals(this.threads)) {
+            this.threads = threads;
+
+            ThreadPageLocksDumpLock dump = sharedPageLockTracker.dump();
+
+            StringBuilder sb = new StringBuilder();
+
+            threads.forEach(s -> {
+                Thread th = s.thread;
+                sb.append("(")
+                    .append(th.getName())
+                    .append("-")
+                    .append(th.getId())
+                    .append(", ")
+                    .append(th.getState())
+                    .append(")");
+
+            });
+
+            log.warning("Threads hanged: [" + sb + "]");
+            // If some thread is hangs
+            // Print to log.
+            log.warning(ToStringDumpProcessor.toStringDump(dump));
+
+            try {
+                // Write dump to file.
+                ToFileDumpProcessor.toFileDump(dump, new File(U.defaultWorkDirectory()), managerNameId);
+            }
+            catch (IgniteCheckedException e) {
+                log.warning("Faile to save locks dump file.", e);
+            }
+        }
+    }
+
+    /**
+     * @param name Lock tracker name.
+     * @return Instance of {@link PageLockListener} for tracking lock/unlock operations.
+     */
+    public PageLockListener createPageLockTracker(String name) {
+        if (!trackingEnable)
+            return DataStructure.NOOP_LSNR;
+
+        return sharedPageLockTracker.registrateStructure(name);
+    }
+
+    /**
+     * Take page locks dump.
+     *
+     * @return String representation of page locks dump.
+     */
+    public String dumpLocks() {
+        ThreadPageLocksDumpLock dump = sharedPageLockTracker.dump();
+
+        return ToStringDumpProcessor.toStringDump(dump);
+    }
+
+    /**
+     * Take page locks dump and print it to console.
+     */
+    public void dumpLocksToLog() {
+        log.warning(dumpLocks());
+    }
+
+    /**
+     * Take page locks dump and save to file.
+     *
+     * @return Absolute file path.
+     */
+    public String dumpLocksToFile() {
+        ThreadPageLocksDumpLock dump = sharedPageLockTracker.dump();
+
+        try {
+            return ToFileDumpProcessor.toFileDump(dump, new File(U.defaultWorkDirectory()), managerNameId);
+        }
+        catch (IgniteCheckedException e) {
+            throw U.convertException(e);
+        }
+    }
+
+    /**
+     * Take page locks dump and save to file for specific path.
+     *
+     * @param path Path to save file.
+     * @return Absolute file path.
+     */
+    public String dumpLocksToFile(String path) {
+        ThreadPageLocksDumpLock dump = sharedPageLockTracker.dump();
+
+        try {
+            return ToFileDumpProcessor.toFileDump(dump, new File(path), managerNameId);
+        }
+        catch (IgniteCheckedException e) {
+            throw U.convertException(e);
+        }
+    }
+
+    /**
+     * Getter.
+     *
+     * @return PageLockTrackerMXBean object.
+     */
+    public PageLockTrackerMXBean mxBean() {
+        return mxBean;
+    }
+
+    /**
+     * @return Total heap overhead in bytes.
+     */
+    public long getHeapOverhead() {
+        return memoryCalculator.heapUsed.get();
+    }
+
+    /**
+     * @return Total offheap overhead in bytes.
+     */
+    public long getOffHeapOverhead() {
+        return memoryCalculator.offHeapUsed.get();
+    }
+
+    /**
+     * @return Total overhead in bytes.
+     */
+    public long getTotalOverhead() {
+        return getHeapOverhead() + getOffHeapOverhead();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void start() throws IgniteException {
+        sharedPageLockTracker.start();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void stop() throws IgniteException {
+        sharedPageLockTracker.stop();
+    }
+
+    /**
+     *
+     */
+   public static class MemoryCalculator {
+        /** */
+        private final AtomicLong heapUsed = new AtomicLong();
+        /** */
+        private final AtomicLong offHeapUsed = new AtomicLong();
+
+        /** */
+        MemoryCalculator(){
+            onHeapAllocated(16 + (8 + 16) * 2);
+        }
+
+        /** */
+        public void onHeapAllocated(long bytes) {
+            assert bytes >= 0;
+
+            heapUsed.getAndAdd(bytes);
+        }
+
+        /** */
+        public void onOffHeapAllocated(long bytes) {
+            assert bytes >= 0;
+
+            offHeapUsed.getAndAdd(bytes);
+        }
+
+        /** */
+        public void onHeapFree(long bytes) {
+            heapUsed.getAndAdd(-bytes);
+        }
+
+        /** */
+        public void onOffHeapFree(long bytes) {
+            offHeapUsed.getAndAdd(-bytes);
+        }
+    }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/PageMetaInfoStore.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/PageMetaInfoStore.java
new file mode 100644
index 0000000..4272f94
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/PageMetaInfoStore.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.persistence.diagnostic.pagelocktracker;
+
+/**
+ *
+ */
+public interface PageMetaInfoStore {
+    /**
+     * @return Capacity.
+     */
+    int capacity();
+
+    /**
+     * @return True if empty.
+     */
+    boolean isEmpty();
+
+    /**
+     * Add page to store.
+     *
+     * @param itemIdx Index of page in store.
+     * @param op Page operation.
+     * @param structureId Data structure id.
+     * @param pageId Page id.
+     * @param pageAddrHeader Page header addres.
+     * @param pageAddr Page addres.
+     */
+    void add(int itemIdx, int op, int structureId, long pageId, long pageAddrHeader, long pageAddr);
+
+    /**
+     * Remove page from store by index.
+     */
+    void remove(int itemIdx);
+
+    /**
+     * @param itemIdx Index of page in store.
+     * @return Page operation.
+     */
+    int getOperation(int itemIdx);
+
+    /**
+     * @param itemIdx Index of page in store.
+     * @return Data structure id.
+     */
+    int getStructureId(int itemIdx);
+
+    /**
+     * @param itemIdx Index of page in store.
+     * @return Page id.
+     */
+    long getPageId(int itemIdx);
+
+    /**
+     * @param itemIdx Index of page in store.
+     * @return Page header address.
+     */
+    long getPageAddrHeader(int itemIdx);
+
+    /**
+     * @param itemIdx Index of page in store.
+     * @return Page address.
+     */
+    long getPageAddr(int itemIdx);
+
+    /**
+     * @return Copy of current store state.
+     */
+    PageMetaInfoStore copy();
+
+    /**
+     * Free resource.
+     */
+    void free();
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/SharedPageLockTracker.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/SharedPageLockTracker.java
new file mode 100644
index 0000000..dfda39ee
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/SharedPageLockTracker.java
@@ -0,0 +1,444 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.persistence.diagnostic.pagelocktracker;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.IgniteInterruptedException;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageLockTrackerManager.MemoryCalculator;
+import org.apache.ignite.internal.processors.cache.persistence.tree.util.PageLockListener;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.lang.IgniteFuture;
+import org.apache.ignite.lifecycle.LifecycleAware;
+
+import static org.apache.ignite.IgniteSystemProperties.IGNITE_PAGE_LOCK_TRACKER_CHECK_INTERVAL;
+import static org.apache.ignite.IgniteSystemProperties.getInteger;
+import static org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.LockTrackerFactory.DEFAULT_CAPACITY;
+import static org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.LockTrackerFactory.DEFAULT_TYPE;
+
+//TODO Fast local get thread local.
+//TODO Dynamic enable/disable tracing.
+//TODO Collect page content to dump. AG
+/**
+ *
+ */
+public class SharedPageLockTracker implements LifecycleAware, PageLockListener, DumpSupported<ThreadPageLocksDumpLock> {
+    /**
+     *
+     */
+    private static final long OVERHEAD_SIZE = 16 + (8 * 8) + (4 * 3);
+
+    /**
+     *
+     */
+    private final MemoryCalculator memCalc;
+
+    /**
+     *
+     */
+    public final int threadLimits;
+    /**
+     *
+     */
+    public final int timeOutWorkerInterval;
+    /**
+     *
+     */
+    private final Map<Long, PageLockTracker<? extends PageLockDump>> threadStacks = new HashMap<>();
+    /**
+     *
+     */
+    private final Map<Long, Thread> threadIdToThreadRef = new HashMap<>();
+    /**
+     *
+     */
+    private final Map<String, Integer> structureNameToId = new HashMap<>();
+    /** Thread for clean terminated threads from map. */
+    private final TimeOutWorker timeOutWorker = new TimeOutWorker();
+    /**
+     *
+     */
+    private Map<Long, SharedPageLockTracker.State> prevThreadsState = new HashMap<>();
+    /**
+     *
+     */
+    private int idGen;
+    /**
+     *
+     */
+    private final Consumer<Set<SharedPageLockTracker.State>> hangThreadsCallBack;
+    /**
+     *
+     */
+    private final ThreadLocal<PageLockTracker> lockTracker = ThreadLocal.withInitial(this::createTracker);
+
+    /**
+     *
+     */
+    public SharedPageLockTracker() {
+        this((ids) -> {
+        }, new MemoryCalculator());
+    }
+
+    /**
+     *
+     */
+    public SharedPageLockTracker(Consumer<Set<State>> hangThreadsCallBack, MemoryCalculator memCalc) {
+        this(
+            1000,
+            getInteger(IGNITE_PAGE_LOCK_TRACKER_CHECK_INTERVAL, 60_000),
+            hangThreadsCallBack,
+            memCalc
+        );
+    }
+
+    /**
+     *
+     */
+    public SharedPageLockTracker(
+        int threadLimits,
+        int timeOutWorkerInterval,
+        Consumer<Set<SharedPageLockTracker.State>> hangThreadsCallBack,
+        MemoryCalculator memCalc
+    ) {
+        this.threadLimits = threadLimits;
+        this.timeOutWorkerInterval = timeOutWorkerInterval;
+        this.hangThreadsCallBack = hangThreadsCallBack;
+        this.memCalc = memCalc;
+
+        this.memCalc.onHeapAllocated(OVERHEAD_SIZE);
+    }
+
+    /**
+     * Factory method for creating thread local {@link PageLockTracker}.
+     *
+     * @return PageLockTracer instance.
+     */
+    private PageLockTracker createTracker() {
+        Thread thread = Thread.currentThread();
+
+        String name = "name=" + thread.getName();
+        long threadId = thread.getId();
+
+        PageLockTracker<? extends PageLockDump> tracker = LockTrackerFactory.create(
+            DEFAULT_TYPE, DEFAULT_CAPACITY, name, memCalc
+        );
+
+        synchronized (this) {
+            threadStacks.put(threadId, tracker);
+
+            threadIdToThreadRef.put(threadId, thread);
+
+            memCalc.onHeapAllocated(((8 + 16 + 8) + 8) * 2);
+
+            if (threadIdToThreadRef.size() > threadLimits)
+                cleanTerminatedThreads();
+        }
+
+        return tracker;
+    }
+
+    /**
+     *
+     */
+    public synchronized PageLockListener registrateStructure(String structureName) {
+        Integer id = structureNameToId.get(structureName);
+
+        if (id == null) {
+            structureNameToId.put(structureName, id = (++idGen));
+
+            // Size for new (K,V) pair.
+            memCalc.onHeapAllocated((structureName.getBytes().length + 16) + (8 + 16 + 4));
+        }
+
+        // Size for PageLockListenerIndexAdapter object.
+        memCalc.onHeapAllocated(16 + 4 + 8);
+
+        return new PageLockListenerIndexAdapter(id, this);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void onBeforeWriteLock(int structureId, long pageId, long page) {
+        lockTracker.get().onBeforeWriteLock(structureId, pageId, page);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void onWriteLock(int structureId, long pageId, long page, long pageAddr) {
+        lockTracker.get().onWriteLock(structureId, pageId, page, pageAddr);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void onWriteUnlock(int structureId, long pageId, long page, long pageAddr) {
+        lockTracker.get().onWriteUnlock(structureId, pageId, page, pageAddr);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void onBeforeReadLock(int structureId, long pageId, long page) {
+        lockTracker.get().onBeforeReadLock(structureId, pageId, page);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void onReadLock(int structureId, long pageId, long page, long pageAddr) {
+        lockTracker.get().onReadLock(structureId, pageId, page, pageAddr);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void onReadUnlock(int structureId, long pageId, long page, long pageAddr) {
+        lockTracker.get().onReadUnlock(structureId, pageId, page, pageAddr);
+    }
+
+    /** {@inheritDoc} */
+    @Override public synchronized ThreadPageLocksDumpLock dump() {
+        Collection<PageLockTracker<? extends PageLockDump>> trackers = threadStacks.values();
+        List<ThreadPageLocksDumpLock.ThreadState> threadStates = new ArrayList<>(threadStacks.size());
+
+        for (PageLockTracker tracker : trackers) {
+            boolean acquired = tracker.acquireSafePoint();
+
+            //TODO
+            assert acquired;
+        }
+
+        for (Map.Entry<Long, PageLockTracker<? extends PageLockDump>> entry : threadStacks.entrySet()) {
+            Long threadId = entry.getKey();
+            Thread thread = threadIdToThreadRef.get(threadId);
+
+            PageLockTracker<? extends PageLockDump> tracker = entry.getValue();
+
+            try {
+                PageLockDump pageLockDump = tracker.dump();
+
+                threadStates.add(
+                    new ThreadPageLocksDumpLock.ThreadState(
+                        threadId,
+                        thread.getName(),
+                        thread.getState(),
+                        pageLockDump,
+                        tracker.isInvalid() ? tracker.invalidContext() : null
+                    )
+                );
+            }
+            finally {
+                tracker.releaseSafePoint();
+            }
+        }
+
+        Map<Integer, String> idToStructureName0 =
+            Collections.unmodifiableMap(
+                structureNameToId.entrySet().stream()
+                    .collect(Collectors.toMap(
+                        Map.Entry::getValue,
+                        Map.Entry::getKey
+                    ))
+            );
+
+        List<ThreadPageLocksDumpLock.ThreadState> threadStates0 =
+            Collections.unmodifiableList(threadStates);
+
+        // Get first thread dump time or current time is threadStates is empty.
+        long time = !threadStates.isEmpty() ? threadStates.get(0).pageLockDump.time() : System.currentTimeMillis();
+
+        return new ThreadPageLocksDumpLock(time, idToStructureName0, threadStates0);
+    }
+
+    /**
+     *
+     */
+    private synchronized void cleanTerminatedThreads() {
+        Iterator<Map.Entry<Long, Thread>> it = threadIdToThreadRef.entrySet().iterator();
+
+        while (it.hasNext()) {
+            Map.Entry<Long, Thread> entry = it.next();
+
+            long threadId = entry.getKey();
+            Thread thread = entry.getValue();
+
+            if (thread.getState() == Thread.State.TERMINATED) {
+                PageLockTracker tracker = threadStacks.remove(threadId);
+
+                if (tracker != null) {
+                    memCalc.onHeapFree((8 + 16 + 8) + 8);
+
+                    tracker.free();
+                }
+
+                it.remove();
+
+                memCalc.onHeapFree((8 + 16 + 8) + 8);
+            }
+        }
+    }
+
+    /**
+     *
+     */
+    private synchronized Map<Long, State> getThreadOperationState() {
+        return threadStacks.entrySet().stream().collect(Collectors.toMap(
+            Map.Entry::getKey,
+            e -> {
+                PageLockTracker<? extends PageLockDump> lt = e.getValue();
+
+                return new State(lt.operationsCounter(), lt.heldLocksNumber(), threadIdToThreadRef.get(e.getKey()));
+            }
+        ));
+    }
+
+    /**
+     *
+     */
+    private synchronized Set<State> hangThreads() {
+        Set<State> hangsThreads = new HashSet<>();
+
+        Map<Long, SharedPageLockTracker.State> currentThreadsOperationState = getThreadOperationState();
+
+        prevThreadsState.forEach((threadId, prevState) -> {
+            State state = currentThreadsOperationState.get(threadId);
+
+            if (state == null)
+                return;
+
+            boolean threadHoldedLocks = state.heldLockCnt != 0;
+
+            // If thread holds a lock and does not change state it may be hanged.
+            if (prevState.equals(state) && threadHoldedLocks)
+                hangsThreads.add(state);
+        });
+
+        prevThreadsState = currentThreadsOperationState;
+
+        return hangsThreads;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void start() throws IgniteException {
+        timeOutWorker.setDaemon(true);
+
+        timeOutWorker.start();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void stop() throws IgniteException {
+        timeOutWorker.interrupt();
+
+        try {
+            timeOutWorker.join();
+        }
+        catch (InterruptedException e) {
+            Thread.currentThread().interrupt();
+
+            throw new IgniteInterruptedException(e);
+        }
+    }
+
+    /**
+     *
+     */
+    private class TimeOutWorker extends Thread {
+        /**
+         *
+         */
+        @Override public void run() {
+            try {
+                while (!Thread.currentThread().isInterrupted()) {
+                    sleep(timeOutWorkerInterval);
+
+                    cleanTerminatedThreads();
+
+                    if (hangThreadsCallBack != null) {
+                        Set<SharedPageLockTracker.State> threadIds = hangThreads();
+
+                        if (!F.isEmpty(threadIds))
+                            hangThreadsCallBack.accept(threadIds);
+                    }
+                }
+            }
+            catch (InterruptedException e) {
+                // No-op.
+            }
+        }
+    }
+
+    /**
+     *
+     */
+    public static class State {
+        /**
+         *
+         */
+        final long threadOpCnt;
+        /**
+         *
+         */
+        final long heldLockCnt;
+        /**
+         *
+         */
+        final Thread thread;
+
+        /**
+         *
+         */
+        private State(long threadOpCnt, long heldLockCnt, Thread thread) {
+            this.threadOpCnt = threadOpCnt;
+            this.heldLockCnt = heldLockCnt;
+            this.thread = thread;
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean equals(Object o) {
+            if (this == o)
+                return true;
+            if (o == null || getClass() != o.getClass())
+                return false;
+            State state = (State)o;
+            return threadOpCnt == state.threadOpCnt &&
+                heldLockCnt == state.heldLockCnt &&
+                Objects.equals(thread, state.thread);
+        }
+
+        /** {@inheritDoc} */
+        @Override public int hashCode() {
+            return Objects.hash(threadOpCnt, heldLockCnt, thread);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteFuture<ThreadPageLocksDumpLock> dumpSync() {
+        throw new UnsupportedOperationException();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean acquireSafePoint() {
+        throw new UnsupportedOperationException();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean releaseSafePoint() {
+        throw new UnsupportedOperationException();
+    }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/ThreadPageLocksDumpLock.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/ThreadPageLocksDumpLock.java
new file mode 100644
index 0000000..9228c9e
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/ThreadPageLocksDumpLock.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.persistence.diagnostic.pagelocktracker;
+
+import java.util.List;
+import java.util.Map;
+
+import static org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.dumpprocessors.ToStringDumpProcessor.toStringDump;
+
+/**
+ *
+ */
+public class ThreadPageLocksDumpLock implements PageLockDump {
+    /** */
+    public final long time;
+
+    /** */
+    public final Map<Integer, String> structureIdToStrcutureName;
+
+    /** */
+    public final List<ThreadState> threadStates;
+
+    /** */
+    public ThreadPageLocksDumpLock(
+        long time,
+        Map<Integer, String> structureIdToStrcutureName,
+        List<ThreadState> threadStates
+    ) {
+        this.time = time;
+        this.structureIdToStrcutureName = structureIdToStrcutureName;
+        this.threadStates = threadStates;
+    }
+
+    /** */
+    public static class ThreadState {
+        /** */
+        public final long threadId;
+        /** */
+        public final String threadName;
+        /** */
+        public final Thread.State state;
+        /** */
+        public final PageLockDump pageLockDump;
+        /** */
+        public final InvalidContext<? extends PageLockDump> invalidContext;
+
+        /** */
+        public ThreadState(
+            long threadId,
+            String threadName,
+            Thread.State state,
+            PageLockDump pageLockDump,
+            InvalidContext<? extends PageLockDump> invalidContext
+        ) {
+            this.threadId = threadId;
+            this.threadName = threadName;
+            this.state = state;
+            this.pageLockDump = pageLockDump;
+            this.invalidContext = invalidContext;
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public void apply(DumpProcessor dumpProcessor) {
+        dumpProcessor.processDump(this);
+    }
+
+    /** {@inheritDoc} */
+    @Override public long time() {
+        return time;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return toStringDump(this);
+    }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/dumpprocessors/ToFileDumpProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/dumpprocessors/ToFileDumpProcessor.java
new file mode 100644
index 0000000..60bb590
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/dumpprocessors/ToFileDumpProcessor.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.persistence.diagnostic.pagelocktracker.dumpprocessors;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageLockDump;
+
+import static java.nio.channels.FileChannel.open;
+import static java.nio.file.StandardOpenOption.CREATE_NEW;
+import static java.nio.file.StandardOpenOption.WRITE;
+
+/**
+ *
+ */
+public class ToFileDumpProcessor {
+    /** Date format. */
+    public static final SimpleDateFormat DATE_FMT = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss_SSS");
+
+    /** File name prefix. */
+    public static final String PREFIX_NAME = "page_lock_dump_";
+
+    /**
+     * @param pageLockDump Dump.
+     * @param dir Directory to save.
+     */
+    public static String toFileDump(PageLockDump pageLockDump, File dir, String name) throws IgniteCheckedException {
+        try {
+           if (!dir.exists())
+               dir.mkdirs();
+
+            File file = new File(dir, PREFIX_NAME + name + "_" + DATE_FMT.format(new Date(pageLockDump.time())));
+
+            return saveToFile(ToStringDumpProcessor.toStringDump(pageLockDump), file);
+        }
+        catch (IOException e) {
+            throw new IgniteCheckedException(e);
+        }
+    }
+
+    /**
+     * @param dump Dump.
+     * @param file File to save.
+     */
+    private static String saveToFile(String dump, File file) throws IOException {
+        assert dump != null;
+        assert file != null;
+        assert !dump.isEmpty();
+
+        try (FileChannel ch = open(file.toPath(), CREATE_NEW, WRITE)) {
+            ByteBuffer buf = ByteBuffer.wrap(dump.getBytes());
+
+            assert buf.position() == 0;
+            assert buf.limit() > 0;
+
+            while (buf.position() != buf.limit())
+                ch.write(buf);
+
+            ch.force(true);
+        }
+
+        return file.getAbsolutePath();
+    }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/dumpprocessors/ToStringDumpProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/dumpprocessors/ToStringDumpProcessor.java
new file mode 100644
index 0000000..51a26dc
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/dumpprocessors/ToStringDumpProcessor.java
@@ -0,0 +1,335 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.persistence.diagnostic.pagelocktracker.dumpprocessors;
+
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.DumpProcessor;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageLockDump;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageMetaInfoStore;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.ThreadPageLocksDumpLock;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.ThreadPageLocksDumpLock.ThreadState;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.log.PageLockLogSnapshot;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.stack.PageLockStackSnapshot;
+import org.apache.ignite.internal.util.typedef.internal.SB;
+import org.apache.ignite.internal.util.typedef.internal.U;
+
+import static org.apache.ignite.internal.pagemem.PageIdUtils.flag;
+import static org.apache.ignite.internal.pagemem.PageIdUtils.pageIndex;
+import static org.apache.ignite.internal.pagemem.PageIdUtils.partId;
+import static org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageLockTracker.BEFORE_READ_LOCK;
+import static org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageLockTracker.BEFORE_WRITE_LOCK;
+import static org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageLockTracker.LOCK_OP_MASK;
+import static org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageLockTracker.READ_LOCK;
+import static org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageLockTracker.READ_UNLOCK;
+import static org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageLockTracker.WRITE_LOCK;
+import static org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageLockTracker.WRITE_UNLOCK;
+import static org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageLockTracker.pageIdToString;
+import static org.apache.ignite.internal.util.IgniteUtils.hexInt;
+import static org.apache.ignite.internal.util.IgniteUtils.hexLong;
+
+/**
+ * Proccessor for buils string from {@link PageLockDump}.
+ */
+public class ToStringDumpProcessor {
+    /** Date format. */
+    public static final SimpleDateFormat DATE_FMT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
+
+    /**
+     * @param pageLockDump Dump.
+     * @return String representation of dump.
+     */
+    public static String toStringDump(PageLockDump pageLockDump) {
+        StringBuilder sb = new StringBuilder();
+
+        ToStringHelper proc = new ToStringHelper(sb, strucutreIdMapFunc(pageLockDump));
+
+        pageLockDump.apply(proc);
+
+        return sb.toString();
+    }
+
+    /** */
+    private static Function<Integer, String> strucutreIdMapFunc(PageLockDump pageLockDump) {
+        if (pageLockDump instanceof ThreadPageLocksDumpLock) {
+            ThreadPageLocksDumpLock dump = (ThreadPageLocksDumpLock)pageLockDump;
+
+            return dump.structureIdToStrcutureName::get;
+        }
+        else
+            return String::valueOf;
+    }
+
+    /** */
+    private static class ToStringHelper implements DumpProcessor {
+        /** */
+        private final Function<Integer, String> strucutreIdMapFunc;
+        /** */
+        private final StringBuilder sb;
+
+        /** */
+        private ToStringHelper(StringBuilder sb, Function<Integer, String> strucutreIdMapFunc) {
+            this.sb = sb;
+            this.strucutreIdMapFunc = strucutreIdMapFunc;
+        }
+
+        /** Helper class for track lock/unlock count. */
+        class LockState {
+            int readlock;
+            int writelock;
+        }
+
+        /** */
+        private String operationToString(int op) {
+            switch (op) {
+                case BEFORE_READ_LOCK:
+                    return "Try Read lock";
+                case BEFORE_WRITE_LOCK:
+                    return "Try Write lock";
+                case READ_LOCK:
+                    return "Read lock";
+                case READ_UNLOCK:
+                    return "Read unlock";
+                case WRITE_LOCK:
+                    return "Write lock";
+                case WRITE_UNLOCK:
+                    return "Write unlock";
+            }
+
+            return "N/A";
+        }
+
+        /**
+         * @param entry Log entry.
+         * @return String line.
+         */
+        private String buildPageInfo(PageLockLogSnapshot.LogEntry entry) {
+            int op = entry.operation;
+            long pageId = entry.pageId;
+            int structureId = entry.structureId;
+
+            return operationToString(op) + " pageId=" + pageId
+                + ", structureId=" + strucutreIdMapFunc.apply(structureId)
+                + " [pageIdHex=" + hexLong(pageId)
+                + ", partId=" + partId(pageId) + ", pageIdx=" + pageIndex(pageId)
+                + ", flags=" + hexInt(flag(pageId)) + "]";
+        }
+
+        /**
+         * @param holdedLocks Holded locks map.
+         * @return String line.
+         */
+        private String lockedPagesInfo(Map<Long, LockState> holdedLocks) {
+            SB sb = new SB();
+
+            sb.a("Locked pages = [");
+
+            boolean first = true;
+
+            for (Map.Entry<Long, LockState> entry : holdedLocks.entrySet()) {
+                Long pageId = entry.getKey();
+                LockState lockState = entry.getValue();
+
+                if (!first)
+                    sb.a(",");
+                else
+                    first = false;
+
+                sb.a(pageId)
+                    .a("[" + hexLong(pageId) + "]")
+                    .a("(r=" + lockState.readlock + "|w=" + lockState.writelock + ")");
+            }
+
+            sb.a("]");
+
+            return sb.toString();
+        }
+
+        /** {@inheritDoc} */
+        @Override public void processDump(PageLockLogSnapshot snapshot) {
+            Map<Long, LockState> holdetLocks = new LinkedHashMap<>();
+
+            SB logLocksStr = new SB();
+
+            List<PageLockLogSnapshot.LogEntry> locklog = snapshot.locklog;
+            int nextOp = snapshot.nextOp;
+            long nextOpPageId = snapshot.nextOpPageId;
+            int nextOpStructureId = snapshot.nextOpStructureId;
+
+            for (PageLockLogSnapshot.LogEntry entry : locklog) {
+                int op = entry.operation;
+                long pageId = entry.pageId;
+                int locksHolded = entry.holdedLocks;
+
+                if (op == READ_LOCK || op == WRITE_LOCK || op == BEFORE_READ_LOCK || op == BEFORE_WRITE_LOCK) {
+                    LockState state = holdetLocks.get(pageId);
+
+                    if (state == null)
+                        holdetLocks.put(pageId, state = new LockState());
+
+                    if (op == READ_LOCK)
+                        state.readlock++;
+
+                    if (op == WRITE_LOCK)
+                        state.writelock++;
+
+                    logLocksStr.a("L=" + locksHolded + " -> " + buildPageInfo(entry) + U.nl());
+                }
+
+                if (op == READ_UNLOCK || op == WRITE_UNLOCK) {
+                    LockState state = holdetLocks.get(pageId);
+
+                    if (op == READ_UNLOCK)
+                        state.readlock--;
+
+                    if (op == WRITE_UNLOCK)
+                        state.writelock--;
+
+                    if (state.readlock == 0 && state.writelock == 0)
+                        holdetLocks.remove(pageId);
+
+                    logLocksStr.a("L=" + locksHolded + " <- " + buildPageInfo(entry) + U.nl());
+                }
+            }
+
+            if (nextOpPageId != 0) {
+                logLocksStr.a("-> " + operationToString(nextOp) + " nextOpPageId=" + nextOpPageId +
+                    ", nextOpStructureId=" + strucutreIdMapFunc.apply(nextOpStructureId)
+                    + " [pageIdHex=" + hexLong(nextOpPageId)
+                    + ", partId=" + partId(nextOpPageId) + ", pageIdx=" + pageIndex(nextOpPageId)
+                    + ", flags=" + hexInt(flag(nextOpPageId)) + "]" + U.nl());
+            }
+
+            sb.append(lockedPagesInfo(holdetLocks)).append(U.nl());
+
+            sb.append("Locked pages log: ").append(snapshot.name)
+                .append(" time=(").append(snapshot.time).append(", ")
+                .append(DATE_FMT.format(new java.util.Date(snapshot.time)))
+                .append(")")
+                .append(U.nl());
+
+            sb.append(logLocksStr).append(U.nl());
+            ;
+        }
+
+        /** {@inheritDoc} */
+        @Override public void processDump(PageLockStackSnapshot snapshot) {
+            int headIdx = snapshot.headIdx;
+            PageMetaInfoStore pageIdLocksStack = snapshot.pageIdLocksStack;
+            long nextOpPageId = snapshot.nextOpPageId;
+
+            Map<Long, LockState> holdedLocks = new LinkedHashMap<>();
+
+            SB stackStr = new SB();
+
+            if (nextOpPageId != 0)
+                stackStr.a("\t-> " + operationToString(snapshot.nextOp) +
+                    " structureId=" + strucutreIdMapFunc.apply(snapshot.nextOpStructureId) +
+                    " " + pageIdToString(nextOpPageId) + U.nl());
+
+            for (int itemIdx = headIdx - 1; itemIdx >= 0; itemIdx--) {
+                long pageId = pageIdLocksStack.getPageId(itemIdx);
+
+                if (pageId == 0 && itemIdx == 0)
+                    break;
+
+                int op;
+
+                if (pageId == 0) {
+                    stackStr.a("\t -\n");
+
+                    continue;
+                }
+                else {
+                    op = pageIdLocksStack.getOperation(itemIdx) & LOCK_OP_MASK;
+
+                    int structureId = pageIdLocksStack.getStructureId(itemIdx);
+
+                    stackStr.a("\t" + operationToString(op) +
+                        " structureId=" + strucutreIdMapFunc.apply(structureId) +
+                        " " + pageIdToString(pageId) + U.nl());
+                }
+
+                if (op == READ_LOCK || op == WRITE_LOCK || op == BEFORE_READ_LOCK) {
+                    LockState state = holdedLocks.get(pageId);
+
+                    if (state == null)
+                        holdedLocks.put(pageId, state = new LockState());
+
+                    if (op == READ_LOCK)
+                        state.readlock++;
+
+                    if (op == WRITE_LOCK)
+                        state.writelock++;
+
+                }
+            }
+
+            sb.append(lockedPagesInfo(holdedLocks)).append(U.nl());
+
+            sb.append("Locked pages stack: ").append(snapshot.name)
+                .append(" time=(").append(snapshot.time).append(", ")
+                .append(DATE_FMT.format(new java.util.Date(snapshot.time)))
+                .append(")")
+                .append(U.nl());
+
+            sb.append(stackStr).append(U.nl());
+        }
+
+        /** {@inheritDoc} */
+        @Override public void processDump(ThreadPageLocksDumpLock snapshot) {
+            sb.append("Page locks dump:").append(U.nl()).append(U.nl());
+
+            List<ThreadState> threadStates = new ArrayList<>(snapshot.threadStates);
+
+            // Sort thread dump by thread names.
+            threadStates.sort(new Comparator<ThreadState>() {
+                /** {@inheritDoc} */
+                @Override public int compare(ThreadState thState1, ThreadState thState2) {
+                    return thState1.threadName.compareTo(thState2.threadName);
+                }
+            });
+
+            for (ThreadState ths : threadStates) {
+                sb.append("Thread=[name=").append(ths.threadName)
+                    .append(", id=").append(ths.threadId)
+                    .append("], state=").append(ths.state)
+                    .append(U.nl());
+
+                PageLockDump pageLockDump0;
+
+                if (ths.invalidContext == null)
+                    pageLockDump0 = ths.pageLockDump;
+                else {
+                    sb.append(ths.invalidContext.msg).append(U.nl());
+
+                    pageLockDump0 = ths.invalidContext.dump;
+                }
+
+                pageLockDump0.apply(this);
+
+                sb.append(U.nl());
+            }
+        }
+    }
+}
+
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/log/LockLog.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/log/LockLog.java
new file mode 100644
index 0000000..a1b92ba
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/log/LockLog.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.persistence.diagnostic.pagelocktracker.log;
+
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageLockTracker;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageLockTrackerManager.MemoryCalculator;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageMetaInfoStore;
+
+/**
+ * Abstract page lock log class.
+ **/
+public class LockLog extends PageLockTracker<PageLockLogSnapshot> {
+    /** */
+    protected int headIdx;
+
+    /**
+     * Constructor.
+     *
+     * @param name Page lock log name.
+     * @param pageMetaInfoStore Object storing page meta info.
+     */
+    public LockLog(String name, PageMetaInfoStore pageMetaInfoStore, MemoryCalculator memCalc) {
+        super(name, pageMetaInfoStore, memCalc);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void onWriteLock0(int structureId, long pageId, long page, long pageAddr) {
+        log(WRITE_LOCK, structureId, pageId, page, pageAddr);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void onWriteUnlock0(int structureId, long pageId, long page, long pageAddr) {
+        log(WRITE_UNLOCK, structureId, pageId, page, pageAddr);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void onReadLock0(int structureId, long pageId, long page, long pageAddr) {
+        log(READ_LOCK, structureId, pageId, page, pageAddr);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void onReadUnlock0(int structureId, long pageId, long page, long pageAddr) {
+        log(READ_UNLOCK, structureId, pageId, page, pageAddr);
+    }
+
+    /**
+     * Log lock operation.
+     *
+     * @param structureId Structure id.
+     * @param pageId Page id.
+     * @param op Operation.
+     */
+    private void log(int op, int structureId, long pageId, long pageAddrHeader, long pageAddr) {
+        if (!validateOperation(structureId, pageId, op))
+            return;
+
+        if (headIdx + 1 > pages.capacity()) {
+            invalid("Log overflow, size:" + pages.capacity() +
+                ", headIdx=" + headIdx + " " + argsToString(structureId, pageId, op));
+
+            return;
+        }
+
+        long pageId0 = pages.getPageId(headIdx);
+
+        if (pageId0 != 0L && pageId0 != pageId) {
+            invalid("Head should be empty, headIdx=" + headIdx + " " +
+                argsToString(structureId, pageId, op));
+
+            return;
+        }
+
+        if (READ_LOCK == op || WRITE_LOCK == op)
+            heldLockCnt++;
+
+        if (READ_UNLOCK == op || WRITE_UNLOCK == op)
+            heldLockCnt--;
+
+        int curIdx = heldLockCnt << OP_OFFSET & LOCK_IDX_MASK;
+
+        pages.add(headIdx, curIdx | op, structureId, pageId, pageAddrHeader, pageAddr);
+
+        if (BEFORE_READ_LOCK == op || BEFORE_WRITE_LOCK == op)
+            return;
+
+        headIdx++;
+
+        if (heldLockCnt == 0)
+            reset();
+
+        if (op != BEFORE_READ_LOCK && op != BEFORE_WRITE_LOCK &&
+            nextOpPageId == pageId && nextOpStructureId == structureId) {
+            nextOpStructureId = 0;
+            nextOpPageId = 0;
+            nextOp = 0;
+        }
+    }
+
+    /**
+     * Reset log state.
+     */
+    private void reset() {
+        for (int itemIdx = 0; itemIdx < headIdx; itemIdx++)
+            pages.remove(itemIdx);
+
+        headIdx = 0;
+    }
+
+    /** {@inheritDoc} */
+    @Override public PageLockLogSnapshot snapshot() {
+        PageMetaInfoStore log = pages.copy();
+
+        return new PageLockLogSnapshot(
+            name,
+            System.currentTimeMillis(),
+            headIdx,
+            log,
+            nextOp,
+            nextOpStructureId,
+            nextOpPageId
+        );
+    }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/log/PageLockLogSnapshot.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/log/PageLockLogSnapshot.java
new file mode 100644
index 0000000..1514df0
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/log/PageLockLogSnapshot.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.persistence.diagnostic.pagelocktracker.log;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageLockDump;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.DumpProcessor;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageMetaInfoStore;
+
+import static org.apache.ignite.internal.pagemem.PageIdUtils.pageId;
+import static org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageLockTracker.LOCK_IDX_MASK;
+import static org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageLockTracker.LOCK_OP_MASK;
+import static org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageLockTracker.OP_OFFSET;
+import static org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.dumpprocessors.ToStringDumpProcessor.toStringDump;
+
+/**
+ * Page lock log snapshot.
+ */
+public class PageLockLogSnapshot implements PageLockDump {
+    /** Page lock log name. */
+    public final String name;
+    /** Creation time. */
+    public final long time;
+    /** Head position. */
+    public final int headIdx;
+    /** List of log entries. */
+    public final List<LogEntry> locklog;
+    /** */
+    public final PageMetaInfoStore log;
+    /** Next operation. */
+    public final int nextOp;
+    /** Next data structure. */
+    public final int nextOpStructureId;
+    /** Next page id. */
+    public final long nextOpPageId;
+
+    /**
+     *
+     */
+    public PageLockLogSnapshot(
+        String name,
+        long time,
+        int headIdx,
+        PageMetaInfoStore log,
+        int nextOp,
+        int nextOpStructureId,
+        long nextOpPageId
+    ) {
+        this.name = name;
+        this.time = time;
+        this.headIdx = headIdx;
+        this.log = log;
+        this.locklog = toList(log);
+        this.nextOp = nextOp;
+        this.nextOpStructureId = nextOpStructureId;
+        this.nextOpPageId = nextOpPageId;
+    }
+
+    /**
+     * Convert log to list {@link PageLockLogSnapshot.LogEntry}.
+     *
+     * @return List of {@link PageLockLogSnapshot.LogEntry}.
+     */
+    private List<PageLockLogSnapshot.LogEntry> toList(PageMetaInfoStore pages) {
+        List<PageLockLogSnapshot.LogEntry> lockLog = new ArrayList<>(pages.capacity());
+
+        for (int itemIdx = 0; itemIdx < headIdx; itemIdx ++) {
+            int metaOnLock = pages.getOperation(itemIdx);
+
+            assert metaOnLock != 0;
+
+            int heldLocks = (int)(metaOnLock & LOCK_IDX_MASK) >> OP_OFFSET;
+
+            assert heldLocks >= 0;
+
+            int op = metaOnLock & LOCK_OP_MASK;
+
+            int structureId = pages.getStructureId(itemIdx);
+
+            long pageId = pages.getPageId(itemIdx);
+
+            lockLog.add(new PageLockLogSnapshot.LogEntry(pageId, structureId, op, heldLocks));
+        }
+
+        return lockLog;
+    }
+
+    /**
+     * Log entry.
+     */
+    public static class LogEntry {
+        /** */
+        public final long pageId;
+        /** */
+        public final int structureId;
+        /** */
+        public final int operation;
+        /** */
+        public final int holdedLocks;
+        /** */
+        public LogEntry(long pageId, int structureId, int operation, int holdedLock) {
+            this.pageId = pageId;
+            this.structureId = structureId;
+            this.operation = operation;
+            this.holdedLocks = holdedLock;
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public void apply(DumpProcessor dumpProcessor) {
+        dumpProcessor.processDump(this);
+    }
+
+    /** {@inheritDoc} */
+    @Override public long time() {
+        return time;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return toStringDump(this);
+    }
+}
\ No newline at end of file
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/stack/LockStack.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/stack/LockStack.java
new file mode 100644
index 0000000..1606c72
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/stack/LockStack.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.persistence.diagnostic.pagelocktracker.stack;
+
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageMetaInfoStore;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageLockTracker;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageLockTrackerManager.MemoryCalculator;
+
+/**
+ * Abstract page lock stack.
+ */
+public class LockStack extends PageLockTracker<PageLockStackSnapshot> {
+    /**
+     *
+     */
+    protected int headIdx;
+
+    /**
+     * @param name Page lock stack name.
+     * @param pageMetaInfoStore Capacity.
+     */
+    public LockStack(String name, PageMetaInfoStore pageMetaInfoStore, MemoryCalculator memCalc) {
+        super(name, pageMetaInfoStore, memCalc);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void onWriteLock0(int structureId, long pageId, long page, long pageAddr) {
+        push(WRITE_LOCK, structureId, pageId, page, pageAddr);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void onWriteUnlock0(int structureId, long pageId, long page, long pageAddr) {
+        pop(WRITE_UNLOCK, structureId, pageId, page, pageAddr);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void onReadLock0(int structureId, long pageId, long page, long pageAddr) {
+        push(READ_LOCK, structureId, pageId, page, pageAddr);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void onReadUnlock0(int structureId, long pageId, long page, long pageAddr) {
+        pop(READ_UNLOCK, structureId, pageId, page, pageAddr);
+    }
+
+    /**
+     * Push operation on top of stack.
+     *
+     * @param structureId Strcuture id.
+     * @param pageId Page id.
+     * @param op Operation type.
+     */
+    private void push(int op, int structureId, long pageId, long pageAddrHeader, long pageAddr) {
+        if (!validateOperation(structureId, pageId, op))
+            return;
+
+        reset();
+
+        if (headIdx + 1 > pages.capacity()) {
+            invalid("Stack overflow, size=" + pages.capacity() +
+                ", headIdx=" + headIdx + " " + argsToString(structureId, pageId, op));
+
+            return;
+        }
+
+        long pageId0 = pages.getPageId(headIdx);
+
+        if (pageId0 != 0L) {
+            invalid("Head element should be empty, headIdx=" + headIdx +
+                ", pageIdOnHead=" + pageId0 + " " + argsToString(structureId, pageId, op));
+
+            return;
+        }
+
+        int curIdx = heldLockCnt << OP_OFFSET & LOCK_IDX_MASK;
+
+        pages.add(headIdx, curIdx | op, structureId, pageId, pageAddrHeader, pageAddr);
+
+        headIdx++;
+        heldLockCnt++;
+    }
+
+    /**
+     * Pop operation from top of stack.
+     *
+     * @param structureId Structure id.
+     * @param pageId Page id.
+     * @param op Operation type.
+     */
+    private void pop(int op, int structureId, long pageId, long pageAddrHeader, long pageAddr) {
+        if (!validateOperation(structureId, pageId, op))
+            return;
+
+        reset();
+
+        if (headIdx > 1) {
+            int lastItemIdx = headIdx - 1;
+
+            long lastPageId = pages.getPageId(lastItemIdx);
+
+            if (lastPageId == pageId) {
+                pages.remove(lastItemIdx);
+
+                //Reset head to the first not empty element.
+                do {
+                    headIdx--;
+                    heldLockCnt--;
+                }
+                while (headIdx > 0 && pages.getPageId(headIdx - 1) == 0);
+            }
+            else {
+                for (int itemIdx = lastItemIdx - 1; itemIdx >= 0; itemIdx--) {
+                    if (pages.getPageId(itemIdx) == pageId) {
+                        pages.remove(itemIdx);
+                        return;
+                    }
+                }
+
+                invalid("Can not find pageId in stack, headIdx=" + headIdx + " "
+                    + argsToString(structureId, pageId, op));
+            }
+        }
+        else {
+            if (headIdx < 0) {
+                invalid("HeadIdx can not be less, headIdx="
+                    + headIdx + ", " + argsToString(structureId, pageId, op));
+
+                return;
+            }
+
+            long pageId0 = pages.getPageId(0);
+
+            if (pageId0 == 0) {
+                invalid("Stack is empty, can not pop elemnt" + argsToString(structureId, pageId, op));
+
+                return;
+            }
+
+            if (pageId0 == pageId) {
+                pages.remove(0);
+
+                headIdx = 0;
+                heldLockCnt = 0;
+            }
+            else
+                invalid("Can not find pageId in stack, headIdx=" + headIdx + " "
+                    + argsToString(structureId, pageId, op));
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override protected PageLockStackSnapshot snapshot() {
+        PageMetaInfoStore stack = pages.copy();
+
+        return new PageLockStackSnapshot(
+            name,
+            System.currentTimeMillis(),
+            headIdx,
+            stack,
+            nextOp,
+            nextOpStructureId,
+            nextOpPageId
+        );
+    }
+
+    /**
+     * Reset next opeation info.
+     */
+    private void reset() {
+        nextOpPageId = 0;
+        nextOp = 0;
+        nextOpStructureId = 0;
+    }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/stack/PageLockStackSnapshot.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/stack/PageLockStackSnapshot.java
new file mode 100644
index 0000000..76e985d
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/stack/PageLockStackSnapshot.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.persistence.diagnostic.pagelocktracker.stack;
+
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.DumpProcessor;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageLockDump;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageMetaInfoStore;
+
+import static org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.dumpprocessors.ToStringDumpProcessor.toStringDump;
+
+/**
+ * Page lock stack snapshot.
+ */
+public class PageLockStackSnapshot implements PageLockDump {
+    /** */
+    public final String name;
+    /** */
+    public final long time;
+    /** */
+    public final int headIdx;
+    /** */
+    public final PageMetaInfoStore pageIdLocksStack;
+    /** */
+    public final int nextOp;
+    /** */
+    public final int nextOpStructureId;
+    /** */
+    public final long nextOpPageId;
+
+    /**
+     *
+     */
+    public PageLockStackSnapshot(
+        String name,
+        long time,
+        int headIdx,
+        PageMetaInfoStore pageIdLocksStack,
+        int nextOp,
+        int nextOpStructureId,
+        long nextOpPageId
+    ) {
+        this.name = name;
+        this.time = time;
+        this.headIdx = headIdx;
+        this.pageIdLocksStack = pageIdLocksStack;
+        this.nextOp = nextOp;
+        this.nextOpStructureId = nextOpStructureId;
+        this.nextOpPageId = nextOpPageId;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void apply(DumpProcessor dumpProcessor) {
+        dumpProcessor.processDump(this);
+    }
+
+    /** {@inheritDoc} */
+    @Override public long time() {
+        return time;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return toStringDump(this);
+    }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/store/HeapPageMetaInfoStore.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/store/HeapPageMetaInfoStore.java
new file mode 100644
index 0000000..051f1e1
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/store/HeapPageMetaInfoStore.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.persistence.diagnostic.pagelocktracker.store;
+
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageMetaInfoStore;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageLockTrackerManager.MemoryCalculator;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ *
+ */
+public class HeapPageMetaInfoStore implements PageMetaInfoStore {
+    /**
+     *
+     */
+    private static final int OVERHEAD_SIZE = 8 + 16 + 8 + 8;
+    /**
+     *
+     */
+    private static final int PAGE_ID_OFFSET = 0;
+    /**
+     *
+     */
+    private static final int PAGE_HEADER_ADDRESS_OFFSET = 1;
+    /**
+     *
+     */
+    private static final int PAGE_ADDRESS_OFFSET = 2;
+    /**
+     *
+     */
+    private static final int PAGE_META_OFFSET = 3;
+    /**
+     *
+     */
+    private static final int ITEM_SIZE = 4;
+    /**
+     *
+     */
+    private long[] arr;
+    /**
+     *
+     */
+    private final MemoryCalculator memoryCalc;
+
+    /**
+     *
+     */
+    public HeapPageMetaInfoStore(int capacity, @Nullable MemoryCalculator memoryCalc) {
+        this.arr = new long[capacity * ITEM_SIZE];
+        this.memoryCalc = memoryCalc;
+
+        if (memoryCalc != null)
+            memoryCalc.onHeapAllocated(arr.length * 8 + OVERHEAD_SIZE);
+    }
+
+    HeapPageMetaInfoStore(long[] arr) {
+        this.arr = arr;
+        memoryCalc = null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int capacity() {
+        return arr.length / ITEM_SIZE;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isEmpty() {
+        for (int i = 0; i < arr.length; i++) {
+            if (arr[i] != 0)
+                return false;
+        }
+
+        return true;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void add(int itemIdx, int op, int structureId, long pageId, long pageAddrHeader, long pageAddr) {
+        arr[ITEM_SIZE * itemIdx + PAGE_ID_OFFSET] = pageId;
+        arr[ITEM_SIZE * itemIdx + PAGE_HEADER_ADDRESS_OFFSET] = pageAddrHeader;
+        arr[ITEM_SIZE * itemIdx + PAGE_ADDRESS_OFFSET] = pageAddr;
+        arr[ITEM_SIZE * itemIdx + PAGE_META_OFFSET] = meta(structureId, op);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void remove(int itemIdx) {
+        arr[ITEM_SIZE * itemIdx + PAGE_ID_OFFSET] = 0;
+        arr[ITEM_SIZE * itemIdx + PAGE_HEADER_ADDRESS_OFFSET] = 0;
+        arr[ITEM_SIZE * itemIdx + PAGE_ADDRESS_OFFSET] = 0;
+        arr[ITEM_SIZE * itemIdx + PAGE_META_OFFSET] = 0;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int getOperation(int itemIdx) {
+        long structureIdAndOp = arr[ITEM_SIZE * itemIdx + PAGE_META_OFFSET];
+
+        return (int)((structureIdAndOp >> 32));
+    }
+
+    /** {@inheritDoc} */
+    @Override public int getStructureId(int itemIdx) {
+        long structureIdAndOp = arr[ITEM_SIZE * itemIdx + PAGE_META_OFFSET];
+
+        return (int)(structureIdAndOp);
+    }
+
+    /** {@inheritDoc} */
+    @Override public long getPageId(int itemIdx) {
+        return arr[ITEM_SIZE * itemIdx];
+    }
+
+    /** {@inheritDoc} */
+    @Override public long getPageAddrHeader(int itemIdx) {
+        return arr[ITEM_SIZE * itemIdx + PAGE_HEADER_ADDRESS_OFFSET];
+    }
+
+    /** {@inheritDoc} */
+    @Override public long getPageAddr(int itemIdx) {
+        return arr[ITEM_SIZE * itemIdx + PAGE_ADDRESS_OFFSET];
+    }
+
+    /** {@inheritDoc} */
+    @Override public PageMetaInfoStore copy() {
+        return new HeapPageMetaInfoStore(arr.clone());
+    }
+
+    /** {@inheritDoc} */
+    @Override public void free() {
+        if (memoryCalc != null)
+            memoryCalc.onHeapFree(arr.length * 8 + OVERHEAD_SIZE);
+
+        arr = null;
+    }
+
+    /**
+     * Build long from two int.
+     *
+     * @param structureId Structure id.
+     * @param op Operation.
+     */
+    private long meta(int structureId, int op) {
+        long major = ((long)op) << 32;
+
+        long minor = structureId & 0xFFFFFFFFL;
+
+        return major | minor;
+    }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/store/OffHeapPageMetaInfoStore.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/store/OffHeapPageMetaInfoStore.java
new file mode 100644
index 0000000..8cdd858
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/store/OffHeapPageMetaInfoStore.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.persistence.diagnostic.pagelocktracker.store;
+
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageMetaInfoStore;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageLockTrackerManager.MemoryCalculator;
+import org.apache.ignite.internal.util.GridUnsafe;
+import org.jetbrains.annotations.Nullable;
+
+import static org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageLockTracker.LOCK_OP_MASK;
+
+/**
+ *
+ */
+public class OffHeapPageMetaInfoStore implements PageMetaInfoStore {
+    /**
+     *
+     */
+    private static final long OVERHEAD_SIZE = 16 + 4 + 4 + 8 + 8;
+    /**
+     *
+     */
+    private static final int PAGE_ID_OFFSET = 0;
+    /**
+     *
+     */
+    private static final int PAGE_HEADER_ADDRESS_OFFSET = 8;
+    /**
+     *
+     */
+    private static final int PAGE_ADDRESS_OFFSET = 16;
+    /**
+     *
+     */
+    private static final int PAGE_META_OFFSET = 24;
+    /**
+     *
+     */
+    private static final int ITEM_SIZE = 4;
+    /**
+     *
+     */
+    private final int size;
+    /**
+     *
+     */
+    private final int capacity;
+    /**
+     *
+     */
+    private final long ptr;
+    /**
+     *
+     */
+    private final MemoryCalculator memCalc;
+
+    /**
+     *
+     */
+    public OffHeapPageMetaInfoStore(int capacity, @Nullable MemoryCalculator memCalc) {
+        this.capacity = capacity;
+        this.size = this.capacity * (8 * ITEM_SIZE);
+        this.ptr = allocate(size);
+        this.memCalc = memCalc;
+
+        if (memCalc != null) {
+            memCalc.onHeapAllocated(OVERHEAD_SIZE);
+            memCalc.onOffHeapAllocated(size);
+        }
+    }
+
+    /**
+     *
+     */
+    private long allocate(int size) {
+        long ptr = GridUnsafe.allocateMemory(size);
+
+        GridUnsafe.setMemory(ptr, size, (byte)0);
+
+        return ptr;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int capacity() {
+        return capacity;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isEmpty() {
+        for (int i = 0; i < size; i++) {
+            if (GridUnsafe.getByte(ptr + i) != 0)
+                return false;
+        }
+
+        return true;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void add(int itemIdx, int op, int structureId, long pageId, long pageAddrHeader, long pageAddr) {
+        GridUnsafe.putLong(offset(itemIdx) + PAGE_ID_OFFSET, pageId);
+        GridUnsafe.putLong(offset(itemIdx) + PAGE_HEADER_ADDRESS_OFFSET, pageAddrHeader);
+        GridUnsafe.putLong(offset(itemIdx) + PAGE_ADDRESS_OFFSET, pageAddr);
+        GridUnsafe.putLong(offset(itemIdx) + PAGE_META_OFFSET, join(structureId, op));
+    }
+
+    /** {@inheritDoc} */
+    @Override public void remove(int itemIdx) {
+        GridUnsafe.putLong(offset(itemIdx) + PAGE_ID_OFFSET, 0);
+        GridUnsafe.putLong(offset(itemIdx) + PAGE_HEADER_ADDRESS_OFFSET, 0);
+        GridUnsafe.putLong(offset(itemIdx) + PAGE_ADDRESS_OFFSET, 0);
+        GridUnsafe.putLong(offset(itemIdx) + PAGE_META_OFFSET, 0);
+    }
+
+    /** {@inheritDoc} */
+    @Override public int getOperation(int itemIdx) {
+        long structureIdAndOp = GridUnsafe.getLong(offset(itemIdx) + PAGE_META_OFFSET);
+
+        return (int)((structureIdAndOp >> 32) & LOCK_OP_MASK);
+    }
+
+    /** {@inheritDoc} */
+    @Override public int getStructureId(int itemIdx) {
+        long structureIdAndOp = GridUnsafe.getLong(offset(itemIdx) + PAGE_META_OFFSET);
+
+        return (int)(structureIdAndOp);
+    }
+
+    /** {@inheritDoc} */
+    @Override public long getPageId(int itemIdx) {
+        return GridUnsafe.getLong(offset(itemIdx) + PAGE_ID_OFFSET);
+    }
+
+    /** {@inheritDoc} */
+    @Override public long getPageAddrHeader(int itemIdx) {
+        return GridUnsafe.getLong(offset(itemIdx) + PAGE_HEADER_ADDRESS_OFFSET);
+    }
+
+    /** {@inheritDoc} */
+    @Override public long getPageAddr(int itemIdx) {
+        return GridUnsafe.getLong(offset(itemIdx) + PAGE_ADDRESS_OFFSET);
+    }
+
+    /**
+     *
+     */
+    private long offset(long itemIdx) {
+        long offset = ptr + itemIdx * 8 * ITEM_SIZE;
+
+        assert offset >= ptr && offset <= ((ptr + size) - 8 * ITEM_SIZE) :"offset=" + (offset - ptr) + ", size=" + size;
+
+        return offset;
+    }
+
+    /** {@inheritDoc} */
+    @Override public PageMetaInfoStore copy() {
+        long[] arr = new long[capacity * 4];
+
+        GridUnsafe.copyMemory(null, ptr, arr, GridUnsafe.LONG_ARR_OFF, size);
+
+        return new HeapPageMetaInfoStore(arr);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void free() {
+        GridUnsafe.freeMemory(ptr);
+
+        if (memCalc != null) {
+            memCalc.onHeapFree(OVERHEAD_SIZE);
+            memCalc.onOffHeapFree(size);
+        }
+    }
+
+    /**
+     * Build long from two int.
+     *
+     * @param structureId Structure id.
+     * @param op Operation.
+     */
+    private long join(int structureId, int op) {
+        long major = ((long)op) << 32;
+
+        long minor = structureId & 0xFFFFFFFFL;
+
+        return major | minor;
+    }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/AbstractFreeList.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/AbstractFreeList.java
index 63e25ac..0d120d7 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/AbstractFreeList.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/AbstractFreeList.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
@@ -39,6 +39,7 @@ import org.apache.ignite.internal.processors.cache.persistence.tree.reuse.LongLi
 import org.apache.ignite.internal.processors.cache.persistence.tree.reuse.ReuseBag;
 import org.apache.ignite.internal.processors.cache.persistence.tree.reuse.ReuseList;
 import org.apache.ignite.internal.processors.cache.persistence.tree.util.PageHandler;
+import org.apache.ignite.internal.processors.cache.persistence.tree.util.PageLockListener;
 import org.apache.ignite.internal.util.typedef.internal.U;
 
 /**
@@ -339,8 +340,10 @@ public abstract class AbstractFreeList<T extends Storable> extends PagesList imp
         ReuseList reuseList,
         IgniteWriteAheadLogManager wal,
         long metaPageId,
-        boolean initNew) throws IgniteCheckedException {
-        super(cacheId, name, memPlc.pageMemory(), BUCKETS, wal, metaPageId);
+        boolean initNew,
+        PageLockListener lockLsnr
+    ) throws IgniteCheckedException {
+        super(cacheId, name, memPlc.pageMemory(), BUCKETS, wal, metaPageId, lockLsnr);
 
         rmvRow = new RemoveRowHandler(cacheId == 0);
 
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/CacheFreeListImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/CacheFreeList.java
similarity index 78%
rename from modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/CacheFreeListImpl.java
rename to modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/CacheFreeList.java
index 2fd3edb..454a600 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/CacheFreeListImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/CacheFreeList.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
@@ -26,12 +26,13 @@ import org.apache.ignite.internal.processors.cache.persistence.tree.io.AbstractD
 import org.apache.ignite.internal.processors.cache.persistence.tree.io.DataPageIO;
 import org.apache.ignite.internal.processors.cache.persistence.tree.io.IOVersions;
 import org.apache.ignite.internal.processors.cache.persistence.tree.reuse.ReuseList;
+import org.apache.ignite.internal.processors.cache.persistence.tree.util.PageLockListener;
 import org.apache.ignite.internal.util.typedef.internal.U;
 
 /**
  * FreeList implementation for cache.
  */
-public class CacheFreeListImpl extends AbstractFreeList<CacheDataRow> {
+public class CacheFreeList extends AbstractFreeList<CacheDataRow> {
     /**
      * @param cacheId Cache id.
      * @param name Name.
@@ -42,10 +43,28 @@ public class CacheFreeListImpl extends AbstractFreeList<CacheDataRow> {
      * @param metaPageId Meta page id.
      * @param initNew Initialize new.
      */
-    public CacheFreeListImpl(int cacheId, String name, DataRegionMetricsImpl regionMetrics, DataRegion dataRegion,
+    public CacheFreeList(
+        int cacheId,
+        String name,
+        DataRegionMetricsImpl regionMetrics,
+        DataRegion dataRegion,
         ReuseList reuseList,
-        IgniteWriteAheadLogManager wal, long metaPageId, boolean initNew) throws IgniteCheckedException {
-        super(cacheId, name, regionMetrics, dataRegion, reuseList, wal, metaPageId, initNew);
+        IgniteWriteAheadLogManager wal,
+        long metaPageId,
+        boolean initNew,
+        PageLockListener lockLsnr
+    ) throws IgniteCheckedException {
+        super(
+            cacheId,
+            name,
+            regionMetrics,
+            dataRegion,
+            reuseList,
+            wal,
+            metaPageId,
+            initNew,
+            lockLsnr
+        );
     }
 
     /** {@inheritDoc} */
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/PagesList.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/PagesList.java
index b1ea92bf9..1fa9062 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/PagesList.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/PagesList.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
@@ -44,6 +44,7 @@ import org.apache.ignite.internal.processors.cache.persistence.tree.io.IOVersion
 import org.apache.ignite.internal.processors.cache.persistence.tree.io.PageIO;
 import org.apache.ignite.internal.processors.cache.persistence.tree.reuse.ReuseBag;
 import org.apache.ignite.internal.processors.cache.persistence.tree.util.PageHandler;
+import org.apache.ignite.internal.processors.cache.persistence.tree.util.PageLockListener;
 import org.apache.ignite.internal.util.GridArrays;
 import org.apache.ignite.internal.util.GridLongList;
 import org.apache.ignite.internal.util.typedef.F;
@@ -136,9 +137,10 @@ public abstract class PagesList extends DataStructure {
         PageMemory pageMem,
         int buckets,
         IgniteWriteAheadLogManager wal,
-        long metaPageId
+        long metaPageId,
+        PageLockListener lockLsnr
     ) {
-        super(cacheId, pageMem, wal);
+        super(cacheId, pageMem, wal, lockLsnr);
 
         this.name = name;
         this.buckets = buckets;
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/metastorage/MetaStorage.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/metastorage/MetaStorage.java
index ea7a997..e36ad17 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/metastorage/MetaStorage.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/metastorage/MetaStorage.java
@@ -45,6 +45,7 @@ import org.apache.ignite.internal.pagemem.wal.IgniteWriteAheadLogManager;
 import org.apache.ignite.internal.pagemem.wal.WALPointer;
 import org.apache.ignite.internal.pagemem.wal.record.MetastoreDataRecord;
 import org.apache.ignite.internal.pagemem.wal.record.delta.MetaPageInitRecord;
+import org.apache.ignite.internal.processors.cache.CacheDiagnosticManager;
 import org.apache.ignite.internal.processors.cache.CacheGroupContext;
 import org.apache.ignite.internal.processors.cache.GridCacheProcessor;
 import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
@@ -66,6 +67,7 @@ import org.apache.ignite.internal.processors.cache.persistence.tree.io.PageParti
 import org.apache.ignite.internal.processors.cache.persistence.tree.io.SimpleDataPageIO;
 import org.apache.ignite.internal.processors.cache.persistence.tree.reuse.ReuseList;
 import org.apache.ignite.internal.processors.cache.persistence.tree.util.PageHandler;
+import org.apache.ignite.internal.processors.cache.persistence.tree.util.PageLockListener;
 import org.apache.ignite.internal.processors.failure.FailureProcessor;
 import org.apache.ignite.internal.util.lang.GridCursor;
 import org.apache.ignite.internal.util.typedef.internal.CU;
@@ -245,14 +247,39 @@ public class MetaStorage implements DbCheckpointListener, ReadOnlyMetastorage, R
             getOrAllocateMetas(partId = PageIdAllocator.METASTORE_PARTITION);
 
         if (!empty) {
-            freeList = new FreeListImpl(METASTORAGE_CACHE_ID, "metastorage",
-                regionMetrics, dataRegion, null, wal, reuseListRoot.pageId().pageId(),
-                reuseListRoot.isAllocated());
+            CacheDiagnosticManager diagnosticMgr = cctx.diagnostic();
+
+            String freeListName = METASTORAGE_CACHE_NAME + "##FreeList";
+            String treeName = METASTORAGE_CACHE_NAME + "##Tree";
+
+            freeList = new FreeListImpl(
+                METASTORAGE_CACHE_ID,
+                freeListName,
+                regionMetrics,
+                dataRegion,
+                null,
+                wal,
+                reuseListRoot.pageId().pageId(),
+                reuseListRoot.isAllocated(),
+                diagnosticMgr.pageLockTracker().createPageLockTracker(freeListName)
+            );
 
             MetastorageRowStore rowStore = new MetastorageRowStore(freeList, db);
 
-            tree = new MetastorageTree(METASTORAGE_CACHE_ID, dataRegion.pageMemory(), wal, rmvId,
-                freeList, rowStore, treeRoot.pageId().pageId(), treeRoot.isAllocated(), failureProcessor, partId);
+            tree = new MetastorageTree(
+                METASTORAGE_CACHE_ID,
+                treeName,
+                dataRegion.pageMemory(),
+                wal,
+                rmvId,
+                freeList,
+                rowStore,
+                treeRoot.pageId().pageId(),
+                treeRoot.isAllocated(),
+                failureProcessor,
+                partId,
+                diagnosticMgr.pageLockTracker().createPageLockTracker(treeName)
+            );
 
             if (!readOnly)
                 ((GridCacheDatabaseSharedManager)db).addCheckpointListener(this);
@@ -636,10 +663,18 @@ public class MetaStorage implements DbCheckpointListener, ReadOnlyMetastorage, R
     /** */
     public class FreeListImpl extends AbstractFreeList<MetastorageDataRow> {
         /** {@inheritDoc} */
-        FreeListImpl(int cacheId, String name, DataRegionMetricsImpl regionMetrics, DataRegion dataRegion,
+        FreeListImpl(
+            int cacheId,
+            String name,
+            DataRegionMetricsImpl regionMetrics,
+            DataRegion dataRegion,
             ReuseList reuseList,
-            IgniteWriteAheadLogManager wal, long metaPageId, boolean initNew) throws IgniteCheckedException {
-            super(cacheId, name, regionMetrics, dataRegion, reuseList, wal, metaPageId, initNew);
+            IgniteWriteAheadLogManager wal,
+            long metaPageId,
+            boolean initNew,
+            PageLockListener lsnr
+        ) throws IgniteCheckedException {
+            super(cacheId, name, regionMetrics, dataRegion, reuseList, wal, metaPageId, initNew, lsnr);
         }
 
         /** {@inheritDoc} */
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/metastorage/MetastorageTree.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/metastorage/MetastorageTree.java
index 936c5af..8c3d282 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/metastorage/MetastorageTree.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/metastorage/MetastorageTree.java
@@ -27,6 +27,7 @@ import org.apache.ignite.internal.processors.cache.persistence.tree.io.BPlusInne
 import org.apache.ignite.internal.processors.cache.persistence.tree.io.BPlusLeafIO;
 import org.apache.ignite.internal.processors.cache.persistence.tree.io.IOVersions;
 import org.apache.ignite.internal.processors.cache.persistence.tree.reuse.ReuseList;
+import org.apache.ignite.internal.processors.cache.persistence.tree.util.PageLockListener;
 import org.apache.ignite.internal.processors.failure.FailureProcessor;
 import org.jetbrains.annotations.Nullable;
 
@@ -57,7 +58,9 @@ public class MetastorageTree extends BPlusTree<MetastorageSearchRow, Metastorage
      * @param failureProcessor To call if the tree is corrupted.
      * @throws IgniteCheckedException If failed to initialize.
      */
-    public MetastorageTree(int cacheId,
+    public MetastorageTree(
+        int cacheId,
+        String name,
         PageMemory pageMem,
         IgniteWriteAheadLogManager wal,
         AtomicLong globalRmvId,
@@ -66,9 +69,22 @@ public class MetastorageTree extends BPlusTree<MetastorageSearchRow, Metastorage
         long metaPageId,
         boolean initNew,
         @Nullable FailureProcessor failureProcessor,
-        int partId) throws IgniteCheckedException {
-        super("Metastorage", cacheId, pageMem, wal,
-            globalRmvId, metaPageId, reuseList, MetastorageInnerIO.VERSIONS, MetastoreLeafIO.VERSIONS, failureProcessor);
+        int partId,
+        @Nullable PageLockListener lockLsnr
+    ) throws IgniteCheckedException {
+        super(
+            name,
+            cacheId,
+            pageMem,
+            wal,
+            globalRmvId,
+            metaPageId,
+            reuseList,
+            MetastorageInnerIO.VERSIONS,
+            MetastoreLeafIO.VERSIONS,
+            failureProcessor,
+            lockLsnr
+        );
 
         this.rowStore = rowStore;
 
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/migration/UpgradePendingTreeToPerPartitionTask.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/migration/UpgradePendingTreeToPerPartitionTask.java
index 059ced4..dca08ce 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/migration/UpgradePendingTreeToPerPartitionTask.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/migration/UpgradePendingTreeToPerPartitionTask.java
@@ -148,7 +148,8 @@ public class UpgradePendingTreeToPerPartitionTask implements IgniteCallable<Bool
                 grp.dataRegion().pageMemory(),
                 pendingRootPage.pageId().pageId(),
                 ((GridCacheOffheapManager)grp.offheap()).reuseListForIndex(null),
-                false
+                false,
+                null
             );
         }
         finally {
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/BPlusTree.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/BPlusTree.java
index 03524e8..422d082 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/BPlusTree.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/BPlusTree.java
@@ -58,6 +58,7 @@ import org.apache.ignite.internal.processors.cache.persistence.tree.reuse.ReuseB
 import org.apache.ignite.internal.processors.cache.persistence.tree.reuse.ReuseList;
 import org.apache.ignite.internal.processors.cache.persistence.tree.util.PageHandler;
 import org.apache.ignite.internal.processors.cache.persistence.tree.util.PageHandlerWrapper;
+import org.apache.ignite.internal.processors.cache.persistence.tree.util.PageLockListener;
 import org.apache.ignite.internal.processors.failure.FailureProcessor;
 import org.apache.ignite.internal.util.GridArrays;
 import org.apache.ignite.internal.util.GridLongList;
@@ -746,9 +747,21 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements
         ReuseList reuseList,
         IOVersions<? extends BPlusInnerIO<L>> innerIos,
         IOVersions<? extends BPlusLeafIO<L>> leafIos,
-        @Nullable FailureProcessor failureProcessor
+        @Nullable FailureProcessor failureProcessor,
+        @Nullable PageLockListener lockLsnr
     ) throws IgniteCheckedException {
-        this(name, cacheId, pageMem, wal, globalRmvId, metaPageId, reuseList, failureProcessor);
+        this(
+            name,
+            cacheId,
+            pageMem,
+            wal,
+            globalRmvId,
+            metaPageId,
+            reuseList,
+            failureProcessor,
+            lockLsnr
+        );
+
         setIos(innerIos, leafIos);
     }
 
@@ -771,9 +784,10 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements
         AtomicLong globalRmvId,
         long metaPageId,
         ReuseList reuseList,
-        @Nullable FailureProcessor failureProcessor
+        @Nullable FailureProcessor failureProcessor,
+        @Nullable PageLockListener lsnr
     ) throws IgniteCheckedException {
-        super(cacheId, pageMem, wal);
+        super(cacheId, pageMem, wal, lsnr);
 
         assert !F.isEmpty(name);
 
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/reuse/ReuseListImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/reuse/ReuseListImpl.java
index aaf07d9..027db9b 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/reuse/ReuseListImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/reuse/ReuseListImpl.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
@@ -21,6 +21,7 @@ import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.internal.pagemem.PageMemory;
 import org.apache.ignite.internal.pagemem.wal.IgniteWriteAheadLogManager;
 import org.apache.ignite.internal.processors.cache.persistence.freelist.PagesList;
+import org.apache.ignite.internal.processors.cache.persistence.tree.util.PageLockListener;
 
 /**
  * Reuse list.
@@ -42,13 +43,24 @@ public class ReuseListImpl extends PagesList implements ReuseList {
      * @param initNew {@code True} if new metadata should be initialized.
      * @throws IgniteCheckedException If failed.
      */
-    public ReuseListImpl(int cacheId,
+    public ReuseListImpl(
+        int cacheId,
         String name,
         PageMemory pageMem,
         IgniteWriteAheadLogManager wal,
         long metaPageId,
-        boolean initNew) throws IgniteCheckedException {
-        super(cacheId, name, pageMem, 1, wal, metaPageId);
+        boolean initNew,
+        PageLockListener lockLsnr
+    ) throws IgniteCheckedException {
+        super(
+            cacheId,
+            name,
+            pageMem,
+            1,
+            wal,
+            metaPageId,
+            lockLsnr
+        );
 
         reuseList = this;
 
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/IgniteWalIteratorFactory.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/IgniteWalIteratorFactory.java
index 6dd565e..3c3d388 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/IgniteWalIteratorFactory.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/IgniteWalIteratorFactory.java
@@ -378,7 +378,7 @@ public class IgniteWalIteratorFactory {
             kernalCtx, null, null, null,
             null, null, null, dbMgr, null,
             null, null, null, null, null,
-            null,null, null, null, null
+            null, null, null, null, null, null
         );
     }
 
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/tree/CacheDataTree.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/tree/CacheDataTree.java
index 0ab46e6..320fd01 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/tree/CacheDataTree.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/tree/CacheDataTree.java
@@ -30,6 +30,7 @@ import org.apache.ignite.internal.processors.cache.persistence.tree.io.DataPageI
 import org.apache.ignite.internal.processors.cache.persistence.tree.io.DataPagePayload;
 import org.apache.ignite.internal.processors.cache.persistence.tree.io.IOVersions;
 import org.apache.ignite.internal.processors.cache.persistence.tree.reuse.ReuseList;
+import org.apache.ignite.internal.processors.cache.persistence.tree.util.PageLockListener;
 import org.apache.ignite.internal.processors.cache.tree.mvcc.data.MvccCacheIdAwareDataInnerIO;
 import org.apache.ignite.internal.processors.cache.tree.mvcc.data.MvccCacheIdAwareDataLeafIO;
 import org.apache.ignite.internal.processors.cache.tree.mvcc.data.MvccDataInnerIO;
@@ -67,9 +68,11 @@ public class CacheDataTree extends BPlusTree<CacheSearchRow, CacheDataRow> {
         ReuseList reuseList,
         CacheDataRowStore rowStore,
         long metaPageId,
-        boolean initNew
+        boolean initNew,
+        PageLockListener lockLsnr
     ) throws IgniteCheckedException {
-        super(name,
+        super(
+            name,
             grp.groupId(),
             grp.dataRegion().pageMemory(),
             grp.dataRegion().config().isPersistenceEnabled() ? grp.shared().wal() : null,
@@ -78,7 +81,9 @@ public class CacheDataTree extends BPlusTree<CacheSearchRow, CacheDataRow> {
             reuseList,
             innerIO(grp),
             leafIO(grp),
-            grp.shared().kernalContext().failure());
+            grp.shared().kernalContext().failure(),
+            lockLsnr
+        );
 
         assert rowStore != null;
 
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/tree/PendingEntriesTree.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/tree/PendingEntriesTree.java
index 9e5d65d..407e630 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/tree/PendingEntriesTree.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/tree/PendingEntriesTree.java
@@ -22,6 +22,7 @@ import org.apache.ignite.internal.processors.cache.CacheGroupContext;
 import org.apache.ignite.internal.processors.cache.persistence.tree.BPlusTree;
 import org.apache.ignite.internal.processors.cache.persistence.tree.io.BPlusIO;
 import org.apache.ignite.internal.processors.cache.persistence.tree.reuse.ReuseList;
+import org.apache.ignite.internal.processors.cache.persistence.tree.util.PageLockListener;
 import org.apache.ignite.internal.util.typedef.internal.CU;
 
 /**
@@ -49,9 +50,11 @@ public class PendingEntriesTree extends BPlusTree<PendingRow, PendingRow> {
         PageMemory pageMem,
         long metaPageId,
         ReuseList reuseList,
-        boolean initNew)
-        throws IgniteCheckedException {
-        super(name,
+        boolean initNew,
+        PageLockListener lockLsnr
+    ) throws IgniteCheckedException {
+        super(
+            name,
             grp.groupId(),
             pageMem,
             grp.dataRegion().config().isPersistenceEnabled() ? grp.shared().wal() : null,
@@ -60,7 +63,9 @@ public class PendingEntriesTree extends BPlusTree<PendingRow, PendingRow> {
             reuseList,
             grp.sharedGroup() ? CacheIdAwarePendingEntryInnerIO.VERSIONS : PendingEntryInnerIO.VERSIONS,
             grp.sharedGroup() ? CacheIdAwarePendingEntryLeafIO.VERSIONS : PendingEntryLeafIO.VERSIONS,
-            grp.shared().kernalContext().failure());
+            grp.shared().kernalContext().failure(),
+            lockLsnr
+        );
 
         this.grp = grp;
 
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/diagnostic/DiagnosticProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/diagnostic/DiagnosticProcessor.java
index 36cb248..a063dc6 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/diagnostic/DiagnosticProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/diagnostic/DiagnosticProcessor.java
@@ -22,6 +22,7 @@ import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.IgniteSystemProperties;
 import org.apache.ignite.failure.FailureContext;
 import org.apache.ignite.internal.GridKernalContext;
 import org.apache.ignite.internal.processors.GridProcessorAdapter;
@@ -41,6 +42,9 @@ import static org.apache.ignite.internal.util.IgniteStopwatch.logTime;
  * Processor which contained helper methods for different diagnostic cases.
  */
 public class DiagnosticProcessor extends GridProcessorAdapter {
+    /** Value of the system property that enables page locks dumping on failure. */
+    private static final boolean IGNITE_DUMP_PAGE_LOCK_ON_FAILURE =
+        IgniteSystemProperties.getBoolean(IgniteSystemProperties.IGNITE_DUMP_PAGE_LOCK_ON_FAILURE, true);
     /** Time formatter for dump file name. */
     private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH-mm-ss_SSS");
     /** Folder name for store diagnostic info. **/
@@ -93,6 +97,10 @@ public class DiagnosticProcessor extends GridProcessorAdapter {
      * @param failureCtx Failure context.
      */
     public void onFailure(Ignite ignite, FailureContext failureCtx) {
+        // Dump data structures page locks.
+        if (IGNITE_DUMP_PAGE_LOCK_ON_FAILURE)
+            ctx.cache().context().diagnostic().pageLockTracker().dumpLocksToLog();
+
         // If we have some corruption in data structure,
         // we should scan WAL and print to log and save to file all pages related to corruption for
         // future investigation.
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/visor/diagnostic/VisorPageLocksResult.java b/modules/core/src/main/java/org/apache/ignite/internal/visor/diagnostic/VisorPageLocksResult.java
new file mode 100644
index 0000000..6c6cdde
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/visor/diagnostic/VisorPageLocksResult.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.visor.diagnostic;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import org.apache.ignite.internal.dto.IgniteDataTransferObject;
+
+/**
+ *
+ */
+public class VisorPageLocksResult extends IgniteDataTransferObject {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /** */
+    private String payload;
+
+    /**
+     *
+     */
+    public VisorPageLocksResult() {
+        //No-op.
+    }
+
+    /**
+     * @param payload Result payload as string.
+     */
+    public VisorPageLocksResult(String payload) {
+        this.payload = payload;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void writeExternalData(ObjectOutput out) throws IOException {
+        if (payload == null) {
+            out.writeInt(0);
+        }
+        else {
+            byte[] bytes = payload.getBytes();
+            int length = bytes.length;
+
+            out.writeInt(length);
+            out.write(bytes);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void readExternalData(byte protoVer, ObjectInput in)
+        throws IOException, ClassNotFoundException {
+        int length = in.readInt();
+
+        if (length != 0) {
+            byte[] bytes = new byte[length];
+
+            in.read(bytes);
+
+            payload = new String(bytes);
+        }
+    }
+
+    /**
+     * @return String result represetnation.
+     */
+    public String result() {
+        return payload;
+    }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/visor/diagnostic/VisorPageLocksTask.java b/modules/core/src/main/java/org/apache/ignite/internal/visor/diagnostic/VisorPageLocksTask.java
new file mode 100644
index 0000000..cbe6c47
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/visor/diagnostic/VisorPageLocksTask.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.visor.diagnostic;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.UUID;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.compute.ComputeJobResult;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageLockTrackerManager;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.dumpprocessors.ToStringDumpProcessor;
+import org.apache.ignite.internal.processors.task.GridInternal;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.apache.ignite.internal.visor.VisorJob;
+import org.apache.ignite.internal.visor.VisorMultiNodeTask;
+import org.apache.ignite.internal.visor.VisorTaskArgument;
+import org.jetbrains.annotations.Nullable;
+
+@GridInternal
+public class VisorPageLocksTask
+    extends VisorMultiNodeTask<VisorPageLocksTrackerArgs, Map<ClusterNode, VisorPageLocksResult>, VisorPageLocksResult> {
+    /**
+     *
+     */
+    private static final long serialVersionUID = 0L;
+
+    /** {@inheritDoc} */
+    @Override protected VisorJob<VisorPageLocksTrackerArgs, VisorPageLocksResult> job(VisorPageLocksTrackerArgs arg) {
+        return new VisorPageLocksTrackerJob(arg, debug);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected Collection<UUID> jobNodes(VisorTaskArgument<VisorPageLocksTrackerArgs> arg) {
+        Set<UUID> nodeIds = new HashSet<>();
+
+        Set<String> nodeIds0 = arg.getArgument().nodeIds();
+
+        for (ClusterNode node : ignite.cluster().nodes()) {
+            if (nodeIds0.contains(String.valueOf(node.consistentId())) || nodeIds0.contains(node.id().toString()))
+                nodeIds.add(node.id());
+        }
+
+        if (F.isEmpty(nodeIds))
+            nodeIds.add(ignite.localNode().id());
+
+        return nodeIds;
+    }
+
+    /** {@inheritDoc} */
+    @Nullable @Override protected Map<ClusterNode, VisorPageLocksResult> reduce0(
+        List<ComputeJobResult> results
+    ) throws IgniteException {
+        Map<ClusterNode, VisorPageLocksResult> mapRes = new TreeMap<>();
+
+        results.forEach(j -> {
+            if (j.getException() == null)
+                mapRes.put(j.getNode(), j.getData());
+            else if (j.getException() != null) {
+                StringWriter sw = new StringWriter();
+                PrintWriter pw = new PrintWriter(sw);
+
+                j.getException().printStackTrace(pw);
+
+                mapRes.put(j.getNode(), new VisorPageLocksResult(sw.toString()));
+            }
+        });
+
+        return mapRes;
+    }
+
+    /**
+     *
+     */
+    private static class VisorPageLocksTrackerJob extends VisorJob<VisorPageLocksTrackerArgs, VisorPageLocksResult> {
+        /** */
+        private static final long serialVersionUID = 0L;
+
+        /**
+         * @param arg Formal job argument.
+         * @param debug Debug flag.
+         */
+        private VisorPageLocksTrackerJob(VisorPageLocksTrackerArgs arg, boolean debug) {
+            super(arg, debug);
+        }
+
+        /** {@inheritDoc} */
+        @Override protected VisorPageLocksResult run(VisorPageLocksTrackerArgs arg) {
+            PageLockTrackerManager lockTrackerMgr = ignite.context().cache().context().diagnostic().pageLockTracker();
+
+            String op = arg.type();
+
+            String result;
+
+            if ("dump".equals(op)) {
+                String filePath = arg.filePath() != null ?
+                    lockTrackerMgr.dumpLocksToFile(arg.filePath()) :
+                    lockTrackerMgr.dumpLocksToFile();
+
+                result = "Page locks dump was writtern to file " + filePath;
+            }
+            else if ("dump_log".equals(op)) {
+                lockTrackerMgr.dumpLocksToLog();
+
+                result = "Page locks dump was printed to console " +
+                    ToStringDumpProcessor.DATE_FMT.format(new Date(System.currentTimeMillis()));
+            }
+            else
+                result = "Unsupported operation: " + op;
+
+            return new VisorPageLocksResult(result);
+        }
+
+        /** {@inheritDoc} */
+        @Override public String toString() {
+            return S.toString(VisorPageLocksTrackerJob.class, this);
+        }
+    }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/visor/diagnostic/VisorPageLocksTrackerArgs.java b/modules/core/src/main/java/org/apache/ignite/internal/visor/diagnostic/VisorPageLocksTrackerArgs.java
new file mode 100644
index 0000000..2911ee5
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/visor/diagnostic/VisorPageLocksTrackerArgs.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.visor.diagnostic;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.Collections;
+import java.util.Set;
+import org.apache.ignite.internal.dto.IgniteDataTransferObject;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ *
+ */
+public class VisorPageLocksTrackerArgs extends IgniteDataTransferObject {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /** */
+    private String op;
+    /** */
+    private String type;
+    /** */
+    private String filePath;
+    /** */
+    @Nullable private Set<String> consistentIds;
+
+    public VisorPageLocksTrackerArgs() {
+
+    }
+
+    public VisorPageLocksTrackerArgs(String op, String type, String filePath, Set<String> consistentIds) {
+        this.op = op;
+        this.type = type;
+        this.filePath = filePath;
+        this.consistentIds = consistentIds;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void writeExternalData(ObjectOutput out) throws IOException {
+        if (op == null)
+            out.writeInt(0);
+        else {
+            byte[] bytes = op.getBytes();
+            out.writeInt(bytes.length);
+            out.write(bytes);
+        }
+
+        if (type == null)
+            out.writeInt(0);
+        else {
+            byte[] bytes = type.getBytes();
+            out.writeInt(bytes.length);
+            out.write(bytes);
+        }
+
+        if (filePath == null)
+            out.writeInt(0);
+        else {
+            byte[] bytes = filePath.getBytes();
+            out.writeInt(bytes.length);
+            out.write(bytes);
+        }
+
+        if (consistentIds != null)
+            U.writeCollection(out, consistentIds);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void readExternalData(byte protoVer, ObjectInput in) throws IOException, ClassNotFoundException {
+        int opLenght = in.readInt();
+
+        if (opLenght != 0) {
+            byte[] bytes = new byte[opLenght];
+
+            in.read(bytes);
+
+            op = new String(bytes);
+        }
+
+        int typeLenght = in.readInt();
+
+        if (typeLenght != 0) {
+            byte[] bytes = new byte[typeLenght];
+
+            in.read(bytes);
+
+            type = new String(bytes);
+        }
+
+        int filePathLenght = in.readInt();
+
+        if (filePathLenght != 0) {
+            byte[] bytes = new byte[filePathLenght];
+
+            in.read(bytes);
+
+            filePath = new String(bytes);
+        }
+
+        consistentIds = U.readSet(in);
+    }
+
+    public String operation() {
+        return op;
+    }
+
+    public String type() {
+        return type;
+    }
+
+    public String filePath() {
+        return filePath;
+    }
+
+    public Set<String> nodeIds(){
+        return Collections.unmodifiableSet(consistentIds);
+    }
+}
diff --git a/modules/core/src/main/resources/META-INF/classnames.properties b/modules/core/src/main/resources/META-INF/classnames.properties
index e33dcb3..36529a0 100644
--- a/modules/core/src/main/resources/META-INF/classnames.properties
+++ b/modules/core/src/main/resources/META-INF/classnames.properties
@@ -2345,6 +2345,10 @@ org.apache.ignite.internal.visor.tx.VisorTxTask$TxKillClosure
 org.apache.ignite.internal.visor.tx.VisorTxTask$VisorTxJob
 org.apache.ignite.internal.visor.tx.VisorTxTaskArg
 org.apache.ignite.internal.visor.tx.VisorTxTaskResult
+org.apache.ignite.internal.visor.diagnostic.VisorPageLocksTrackerArgs
+org.apache.ignite.internal.visor.diagnostic.VisorPageLocksResult
+org.apache.ignite.internal.visor.diagnostic.VisorPageLocksTask
+org.apache.ignite.internal.visor.diagnostic.VisorPageLocksTask$VisorPageLocksTrackerJob
 org.apache.ignite.internal.visor.util.VisorClusterGroupEmptyException
 org.apache.ignite.internal.visor.util.VisorEventMapper
 org.apache.ignite.internal.visor.util.VisorExceptionWrapper
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/IgniteWalIteratorSwitchSegmentTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/IgniteWalIteratorSwitchSegmentTest.java
index 00515d2..47cd341 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/IgniteWalIteratorSwitchSegmentTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/IgniteWalIteratorSwitchSegmentTest.java
@@ -152,6 +152,7 @@ public class IgniteWalIteratorSwitchSegmentTest extends GridCommonAbstractTest {
                 null,
                 null,
                 null,
+                null,
                 null)
         ).createSerializer(serVer);
 
@@ -478,6 +479,7 @@ public class IgniteWalIteratorSwitchSegmentTest extends GridCommonAbstractTest {
             null,
             null,
             null,
+            null,
             null
         );
 
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/WalRecoveryTxLogicalRecordsTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/WalRecoveryTxLogicalRecordsTest.java
index e172e01..e2caf16 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/WalRecoveryTxLogicalRecordsTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/WalRecoveryTxLogicalRecordsTest.java
@@ -54,7 +54,7 @@ import org.apache.ignite.internal.processors.cache.persistence.CacheDataRow;
 import org.apache.ignite.internal.processors.cache.persistence.GridCacheDatabaseSharedManager;
 import org.apache.ignite.internal.processors.cache.persistence.file.FilePageStoreManager;
 import org.apache.ignite.internal.processors.cache.persistence.freelist.AbstractFreeList;
-import org.apache.ignite.internal.processors.cache.persistence.freelist.CacheFreeListImpl;
+import org.apache.ignite.internal.processors.cache.persistence.freelist.CacheFreeList;
 import org.apache.ignite.internal.processors.cache.persistence.freelist.PagesList;
 import org.apache.ignite.internal.processors.cache.persistence.tree.reuse.ReuseListImpl;
 import org.apache.ignite.internal.util.typedef.F;
@@ -885,7 +885,7 @@ public class WalRecoveryTxLogicalRecordsTest extends GridCommonAbstractTest {
         boolean foundTails = false;
 
         for (GridDhtLocalPartition part : parts) {
-            CacheFreeListImpl freeList = GridTestUtils.getFieldValue(part.dataStore(), "freeList");
+            CacheFreeList freeList = GridTestUtils.getFieldValue(part.dataStore(), "freeList");
 
             if (freeList == null)
                 // Lazy store.
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/AbstractPageLockTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/AbstractPageLockTest.java
new file mode 100644
index 0000000..f5172c5
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/AbstractPageLockTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.persistence.diagnostic.pagelocktracker;
+
+import java.util.concurrent.ThreadLocalRandom;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.internal.IgniteInterruptedCheckedException;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.log.PageLockLogSnapshot;
+import org.apache.ignite.internal.util.typedef.internal.U;
+
+import static org.junit.Assert.assertEquals;
+
+/** */
+public abstract class AbstractPageLockTest {
+    /** */
+    protected void doRunnable(int deep, Runnable r) {
+        for (int i = 0; i < deep; i++)
+            r.run();
+    }
+
+    /** */
+    protected void awaitRandom(int bound) {
+        try {
+            U.sleep(nextRandomWaitTimeout(bound));
+        }
+        catch (IgniteInterruptedCheckedException e) {
+            throw new IgniteException(e);
+        }
+    }
+
+    protected int nextRandomWaitTimeout(int bound) {
+        ThreadLocalRandom rnd = ThreadLocalRandom.current();
+
+        return rnd.nextInt(bound);
+    }
+
+    protected void checkNextOp(PageLockLogSnapshot lockLog, long nextOpPageId, long nextOp, int nextOpStructureId) {
+        assertEquals(nextOpStructureId, lockLog.nextOpStructureId);
+        assertEquals(nextOp, lockLog.nextOp);
+        assertEquals(nextOpPageId, lockLog.nextOpPageId);
+    }
+}
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/PageLockTrackerMXBeanImplTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/PageLockTrackerMXBeanImplTest.java
new file mode 100644
index 0000000..6772eb3
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/PageLockTrackerMXBeanImplTest.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.persistence.diagnostic.pagelocktracker;
+
+import java.lang.management.ManagementFactory;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.internal.processors.cache.CacheDiagnosticManager;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.junit.Assert;
+import org.junit.Test;
+
+import static javax.management.MBeanServerInvocationHandler.newProxyInstance;
+
+/**
+ * {@link PageLockTrackerMXBean} test.
+ */
+public class PageLockTrackerMXBeanImplTest extends GridCommonAbstractTest {
+    /** {@inheritDoc} */
+    @Override protected void beforeTest() throws Exception {
+        super.beforeTest();
+
+        stopAllGrids();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        super.afterTest();
+
+        stopAllGrids();
+    }
+
+    /**
+     * Simple chekc that mxbean is registrated on node start.
+     *
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testSimple() throws Exception {
+        Ignite ig = startGrid();
+
+        PageLockTrackerMXBean pageLockTrackerMXBean = getPageLockTrackerMXBean(ig);
+
+        Assert.assertNotNull(pageLockTrackerMXBean);
+    }
+
+    /**
+     * @param ignite Ignite.
+     */
+    private PageLockTrackerMXBean getPageLockTrackerMXBean(Ignite ignite) throws Exception {
+        ObjectName mBeanName = U.makeMBeanName(
+            ignite.name(),
+            CacheDiagnosticManager.MBEAN_GROUP,
+            PageLockTrackerMXBean.MBEAN_NAME
+        );
+
+        MBeanServer mBeanSrv = ManagementFactory.getPlatformMBeanServer();
+
+        if (!mBeanSrv.isRegistered(mBeanName))
+            fail("MBean is not registered: " + mBeanName.getCanonicalName());
+
+        return newProxyInstance(mBeanSrv, mBeanName, PageLockTrackerMXBean.class, true);
+    }
+}
\ No newline at end of file
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/PageLockTrackerManagerTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/PageLockTrackerManagerTest.java
new file mode 100644
index 0000000..fdc8379
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/PageLockTrackerManagerTest.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.persistence.diagnostic.pagelocktracker;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import org.apache.ignite.internal.processors.cache.persistence.DataStructure;
+import org.apache.ignite.internal.processors.cache.persistence.tree.util.PageLockListener;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.testframework.ListeningTestLogger;
+import org.junit.Assert;
+import org.junit.Test;
+
+import static org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.LockTrackerFactory.HEAP_LOG;
+import static org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.LockTrackerFactory.HEAP_STACK;
+import static org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.LockTrackerFactory.OFF_HEAP_LOG;
+import static org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.LockTrackerFactory.OFF_HEAP_STACK;
+
+/**
+ *
+ */
+public class PageLockTrackerManagerTest {
+    /**
+     *
+     */
+    @Test
+    public void testDisableTracking(){
+        System.setProperty("IGNITE_PAGE_LOCK_TRACKER_TYPE", String.valueOf(-1));
+
+        try {
+            PageLockTrackerManager mgr = new PageLockTrackerManager(new ListeningTestLogger());
+
+            PageLockListener pll = mgr.createPageLockTracker("test");
+
+            Assert.assertNotNull(pll);
+            Assert.assertSame(pll, DataStructure.NOOP_LSNR);
+
+        }finally {
+            System.clearProperty("IGNITE_PAGE_LOCK_TRACKER_TYPE");
+        }
+
+        System.setProperty("IGNITE_PAGE_LOCK_TRACKER_TYPE", String.valueOf(HEAP_LOG));
+
+        try {
+            PageLockTrackerManager mgr = new PageLockTrackerManager(new ListeningTestLogger());
+
+            PageLockListener pll = mgr.createPageLockTracker("test");
+
+            Assert.assertNotNull(pll);
+            Assert.assertNotSame(pll, DataStructure.NOOP_LSNR);
+
+        }finally {
+            System.clearProperty("IGNITE_PAGE_LOCK_TRACKER_TYPE");
+        }
+    }
+
+    /**
+     *
+     */
+    @Test
+    public void testMemoryCalculation() throws Exception {
+        int[] trackerTypes = new int[] {HEAP_STACK, HEAP_LOG, OFF_HEAP_STACK, OFF_HEAP_LOG};
+
+        for (int type : trackerTypes)
+            testMemoryCalculation0(type);
+    }
+
+    /**
+     * @param type Tracker type.
+     */
+    public void testMemoryCalculation0(int type) throws Exception {
+        System.out.println(">>> Calculation mempory tracker type:" + type);
+
+        int timeOutWorkerInterval = 10_000;
+
+        System.setProperty("IGNITE_PAGE_LOCK_TRACKER_TYPE", String.valueOf(type));
+        System.setProperty("IGNITE_PAGE_LOCK_TRACKER_CHECK_INTERVAL", String.valueOf(timeOutWorkerInterval));
+
+        try {
+            PageLockTrackerManager mgr = new PageLockTrackerManager(new ListeningTestLogger());
+
+            mgr.start();
+
+            printOverhead(mgr);
+
+            long heapOverhead0 = mgr.getHeapOverhead();
+            long offHeapOverhead0 = mgr.getOffHeapOverhead();
+            long totalOverhead0 = mgr.getTotalOverhead();
+
+            Assert.assertTrue(heapOverhead0 > 0);
+            Assert.assertTrue(offHeapOverhead0 >= 0);
+            Assert.assertEquals(heapOverhead0 + offHeapOverhead0, totalOverhead0);
+
+            PageLockListener pls = mgr.createPageLockTracker("test");
+
+            printOverhead(mgr);
+
+            long heapOverhead1 = mgr.getHeapOverhead();
+            long offHeapOverhead1 = mgr.getOffHeapOverhead();
+            long totalOverhead1 = mgr.getTotalOverhead();
+
+            Assert.assertTrue(heapOverhead1 > 0);
+            Assert.assertTrue(offHeapOverhead1 >= 0);
+            Assert.assertTrue(heapOverhead1 > heapOverhead0);
+            Assert.assertTrue(offHeapOverhead1 >= offHeapOverhead0);
+            Assert.assertEquals(heapOverhead1 + offHeapOverhead1, totalOverhead1);
+
+            int threads = 2_000;
+
+            int cacheId = 1;
+            long pageId = 2;
+            long page = 3;
+            long pageAdder = 4;
+
+            List<Thread> threadsList = new ArrayList<>(threads);
+
+            String threadNamePreffix = "my-thread-";
+
+            CountDownLatch startThreadsLatch = new CountDownLatch(threads);
+            CountDownLatch finishThreadsLatch = new CountDownLatch(1);
+
+            for (int i = 0; i < threads; i++) {
+                Thread th = new Thread(() -> {
+                    startThreadsLatch.countDown();
+
+                    pls.onBeforeReadLock(cacheId, pageId, page);
+
+                    pls.onReadLock(cacheId, pageId, page, pageAdder);
+
+                    pls.onReadUnlock(cacheId, pageId, page, pageAdder);
+
+                    try {
+                        finishThreadsLatch.await();
+                    }
+                    catch (InterruptedException ignored) {
+                        // No-op.
+                    }
+                });
+
+                th.setName(threadNamePreffix + i);
+
+                threadsList.add(th);
+
+                th.start();
+
+                System.out.println(">>> start thread:" + th.getName());
+            }
+
+            startThreadsLatch.await();
+
+            printOverhead(mgr);
+
+            long heapOverhead2 = mgr.getHeapOverhead();
+            long offHeapOverhead2 = mgr.getOffHeapOverhead();
+            long totalOverhead2 = mgr.getTotalOverhead();
+
+            Assert.assertTrue(heapOverhead2 > heapOverhead1);
+            Assert.assertTrue(offHeapOverhead2 >= offHeapOverhead1);
+            Assert.assertEquals(heapOverhead2 + offHeapOverhead2, totalOverhead2);
+
+            finishThreadsLatch.countDown();
+
+            threadsList.forEach(th -> {
+                try {
+                    System.out.println(">>> await thread:" + th.getName());
+
+                    th.join();
+                }
+                catch (InterruptedException ignored) {
+                    // No-op.
+                }
+            });
+
+            // Await cleanup worker interval.
+            U.sleep(2 * timeOutWorkerInterval);
+
+            printOverhead(mgr);
+
+            long heapOverhead3 = mgr.getHeapOverhead();
+            long offHeapOverhead3 = mgr.getOffHeapOverhead();
+            long totalOverhead3 = mgr.getTotalOverhead();
+
+            Assert.assertTrue(heapOverhead3 > 0);
+            Assert.assertTrue(offHeapOverhead3 >= 0);
+            Assert.assertTrue(heapOverhead3 < heapOverhead2);
+            Assert.assertTrue(offHeapOverhead3 <= offHeapOverhead2);
+            Assert.assertEquals(heapOverhead3 + offHeapOverhead3, totalOverhead3);
+
+            mgr.stop();
+        }
+        finally {
+            System.clearProperty("IGNITE_PAGE_LOCK_TRACKER_TYPE");
+            System.clearProperty("IGNITE_PAGE_LOCK_TRACKER_CHECK_INTERVAL");
+        }
+    }
+
+    private void printOverhead(PageLockTrackerManager mgr) {
+        System.out.println(
+            "Head:" + mgr.getHeapOverhead()
+                + ", OffHeap:" + mgr.getOffHeapOverhead()
+                + ", Total:" + mgr.getTotalOverhead());
+    }
+}
\ No newline at end of file
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/PageLockTrackerTestSuit.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/PageLockTrackerTestSuit.java
new file mode 100644
index 0000000..78afb50
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/PageLockTrackerTestSuit.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.persistence.diagnostic.pagelocktracker;
+
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.dumpprocessors.ToFileDumpProcessorTest;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.log.HeapArrayLockLogTest;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.log.OffHeapLockLogTest;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.stack.HeapArrayLockStackTest;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.stack.OffHeapLockStackTest;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+/**
+ * Test suite for all tests ralated to {@link PageLockTracker}.
+ */
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+    PageLockTrackerManagerTest.class,
+    SharedPageLockTrackerTest.class,
+    ToFileDumpProcessorTest.class,
+    HeapArrayLockLogTest.class,
+    OffHeapLockLogTest.class,
+    HeapArrayLockStackTest.class,
+    OffHeapLockStackTest.class,
+})
+
+public class PageLockTrackerTestSuit {
+
+}
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/SharedPageLockTrackerTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/SharedPageLockTrackerTest.java
new file mode 100644
index 0000000..8611422
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/SharedPageLockTrackerTest.java
@@ -0,0 +1,541 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.persistence.diagnostic.pagelocktracker;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Consumer;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.internal.IgniteInternalFuture;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageLockTrackerManager.MemoryCalculator;
+import org.apache.ignite.internal.processors.cache.persistence.tree.util.PageLockListener;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.testframework.GridTestUtils;
+import org.junit.Assert;
+import org.junit.Test;
+
+import static org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.LockTrackerFactory.HEAP_LOG;
+import static org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.LockTrackerFactory.HEAP_STACK;
+import static org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.LockTrackerFactory.OFF_HEAP_LOG;
+import static org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.LockTrackerFactory.OFF_HEAP_STACK;
+import static org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.dumpprocessors.ToStringDumpProcessor.toStringDump;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+/**
+ *
+ */
+public class SharedPageLockTrackerTest extends AbstractPageLockTest {
+    /**
+     *
+     */
+    @Test
+    public void testTakeDumpByCount() throws Exception {
+        int[] trackerTypes = new int[] {HEAP_STACK, HEAP_LOG, OFF_HEAP_STACK, OFF_HEAP_LOG};
+
+        LockTrackerFactory.DEFAULT_CAPACITY = 512;
+
+        for (int i = 0; i < trackerTypes.length; i++) {
+            LockTrackerFactory.DEFAULT_TYPE = trackerTypes[i];
+
+            doTestTakeDumpByCount(5, 1, 10, 1);
+
+            doTestTakeDumpByCount(5, 2, 10, 2);
+
+            doTestTakeDumpByCount(10, 3, 20, 4);
+
+            doTestTakeDumpByCount(20, 6, 40, 8);
+        }
+    }
+
+    /**
+     *
+     */
+    @Test
+    public void testTakeDumpByTime() throws Exception {
+        int[] trackerTypes = new int[] {HEAP_STACK, HEAP_LOG, OFF_HEAP_STACK, OFF_HEAP_LOG};
+
+        LockTrackerFactory.DEFAULT_CAPACITY = 512;
+
+        for (int i = 0; i < trackerTypes.length; i++) {
+            LockTrackerFactory.DEFAULT_TYPE = trackerTypes[i];
+
+            doTestTakeDumpByTime(5, 1, 40_000, 1);
+
+            doTestTakeDumpByTime(5, 2, 20_000, 2);
+
+            doTestTakeDumpByTime(10, 3, 10_000, 4);
+
+            doTestTakeDumpByTime(20, 6, 10_000, 8);
+        }
+    }
+
+    /**
+     *
+     */
+    private void doTestTakeDumpByCount(
+        int pagesCnt,
+        int structuresCnt,
+        int dumpCnt,
+        int threads
+    ) throws IgniteCheckedException, InterruptedException {
+        SharedPageLockTracker sharedPageLockTracker = new SharedPageLockTracker();
+
+        List<PageMeta> pageMetas = new CopyOnWriteArrayList<>();
+
+        int id = 1;
+
+        for (int i = 0; i < pagesCnt; i++)
+            pageMetas.add(new PageMeta((id++) % structuresCnt, id++, id++, id++));
+
+        List<PageLockListener> pageLsnrs = new ArrayList<>();
+
+        for (int i = 0; i < structuresCnt; i++)
+            pageLsnrs.add(sharedPageLockTracker.registrateStructure("my-structure-" + i));
+
+        AtomicBoolean stop = new AtomicBoolean();
+
+        CountDownLatch awaitThreadStartLatch = new CountDownLatch(threads);
+
+        IgniteInternalFuture f = GridTestUtils.runMultiThreadedAsync(() -> {
+            List<PageLockListener> locks = new ArrayList<>(pageLsnrs);
+            List<PageMeta> pages = new ArrayList<>();
+
+            pages.addAll(pageMetas);
+
+            while (!stop.get()) {
+                Collections.shuffle(locks);
+                Collections.shuffle(pages);
+
+                for (PageLockListener lsnr : locks) {
+                    for (PageMeta pageMeta : pages) {
+                        awaitRandom(50);
+
+                        lsnr.onBeforeReadLock(pageMeta.structureId, pageMeta.pageId, pageMeta.page);
+
+                        awaitRandom(50);
+
+                        lsnr.onReadLock(pageMeta.structureId, pageMeta.pageId, pageMeta.page, pageMeta.pageAddr);
+                    }
+                }
+
+                awaitRandom(10);
+
+                Collections.reverse(locks);
+                Collections.reverse(pages);
+
+                for (PageLockListener lsnr : locks) {
+                    for (PageMeta pageMeta : pages) {
+                        awaitRandom(50);
+
+                        lsnr.onReadUnlock(pageMeta.structureId, pageMeta.pageId, pageMeta.page, pageMeta.pageAddr);
+                    }
+                }
+
+                if (awaitThreadStartLatch.getCount() > 0)
+                    awaitThreadStartLatch.countDown();
+            }
+        }, threads, "PageLocker");
+
+        awaitThreadStartLatch.await();
+
+        for (int i = 0; i < dumpCnt; i++) {
+            awaitRandom(1000);
+
+            ThreadPageLocksDumpLock dump = sharedPageLockTracker.dump();
+
+            System.out.println(toStringDump(dump));
+
+            assertEquals(threads, dump.threadStates.size());
+            assertEquals(0, dump.threadStates.stream().filter(e -> e.invalidContext != null).count());
+        }
+
+        stop.set(true);
+
+        f.get();
+    }
+
+    /**
+     *
+     */
+    private void doTestTakeDumpByTime(
+        int pagesCnt,
+        int structuresCnt,
+        int dumpTime,
+        int threads
+    ) throws IgniteCheckedException, InterruptedException {
+        SharedPageLockTracker sharedPageLockTracker = new SharedPageLockTracker();
+
+        List<PageMeta> pageMetas = new CopyOnWriteArrayList<>();
+
+        int id = 1;
+
+        for (int i = 0; i < pagesCnt; i++)
+            pageMetas.add(new PageMeta((id++) % structuresCnt, id++, id++, id++));
+
+        List<PageLockListener> pageLsnrs = new ArrayList<>();
+
+        for (int i = 0; i < structuresCnt; i++)
+            pageLsnrs.add(sharedPageLockTracker.registrateStructure("my-structure-" + i));
+
+        AtomicBoolean stop = new AtomicBoolean();
+
+        CountDownLatch awaitThreadStartLatch = new CountDownLatch(threads);
+
+        IgniteInternalFuture f = GridTestUtils.runMultiThreadedAsync(() -> {
+            List<PageLockListener> locks = new ArrayList<>(pageLsnrs);
+            List<PageMeta> pages = new ArrayList<>();
+
+            pages.addAll(pageMetas);
+
+            while (!stop.get()) {
+                Collections.shuffle(locks);
+                Collections.shuffle(pages);
+
+                for (PageLockListener lsnr : locks) {
+                    for (PageMeta pageMeta : pages) {
+                        //awaitRandom(5);
+
+                        lsnr.onBeforeReadLock(pageMeta.structureId, pageMeta.pageId, pageMeta.page);
+
+                        //awaitRandom(5);
+
+                        lsnr.onReadLock(pageMeta.structureId, pageMeta.pageId, pageMeta.page, pageMeta.pageAddr);
+                    }
+                }
+
+                Collections.reverse(locks);
+                Collections.reverse(pages);
+
+                for (PageLockListener lsnr : locks) {
+                    for (PageMeta pageMeta : pages) {
+                        // awaitRandom(5);
+
+                        lsnr.onReadUnlock(pageMeta.structureId, pageMeta.pageId, pageMeta.page, pageMeta.pageAddr);
+                    }
+                }
+
+                if (awaitThreadStartLatch.getCount() > 0)
+                    awaitThreadStartLatch.countDown();
+            }
+        }, threads, "PageLocker");
+
+        IgniteInternalFuture dumpFut = GridTestUtils.runAsync(() -> {
+            try {
+                awaitThreadStartLatch.await();
+            }
+            catch (InterruptedException e) {
+                // Ignore.
+                return;
+            }
+
+            while (!stop.get()) {
+                awaitRandom(20);
+
+                ThreadPageLocksDumpLock dump = sharedPageLockTracker.dump();
+
+                System.out.println(toStringDump(dump));
+
+                assertEquals(threads, dump.threadStates.size());
+                assertEquals(0, dump.threadStates.stream().filter(e -> e.invalidContext != null).count());
+            }
+        });
+
+        Thread.sleep(dumpTime);
+
+        stop.set(true);
+
+        f.get();
+
+        dumpFut.get();
+    }
+
+    /**
+     * Test for checking that internal maps is not leaked after threads stopped.
+     */
+    @Test
+    public void testMemoryLeakOnThreadTerminates() throws Exception {
+        int threadLimits = 1000;
+        int timeOutWorkerInterval = 10_000;
+        Consumer<Set<SharedPageLockTracker.State>> handler = (threads) -> {
+        };
+
+        SharedPageLockTracker sharedPageLockTracker = new SharedPageLockTracker(
+            threadLimits, timeOutWorkerInterval, handler, new MemoryCalculator());
+
+        int threads = 10_000;
+
+        int cacheId = 1;
+        long pageId = 2;
+        long page = 3;
+        long pageAdder = 4;
+
+        PageLockListener lt = sharedPageLockTracker.registrateStructure("test");
+
+        List<Thread> threadsList = new ArrayList<>(threads);
+
+        String threadNamePreffix = "my-thread-";
+
+        for (int i = 0; i < threads; i++) {
+            Thread th = new Thread(() -> {
+                lt.onBeforeReadLock(cacheId, pageId, page);
+
+                lt.onReadLock(cacheId, pageId, page, pageAdder);
+
+                lt.onReadUnlock(cacheId, pageId, page, pageAdder);
+            });
+
+            th.setName(threadNamePreffix + i);
+
+            threadsList.add(th);
+
+            th.start();
+
+            System.out.println(">>> start thread:" + th.getName());
+        }
+
+        threadsList.forEach(th -> {
+            try {
+                System.out.println(">>> await thread:" + th.getName());
+
+                th.join();
+            }
+            catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+        });
+
+        sharedPageLockTracker.start();
+
+        ThreadPageLocksDumpLock dump = sharedPageLockTracker.dump();
+
+        assertTrue(dump.time > 0);
+        assertTrue(!dump.threadStates.isEmpty());
+
+        for (ThreadPageLocksDumpLock.ThreadState threadState : dump.threadStates) {
+            assertNull(threadState.invalidContext);
+            assertTrue(threadState.threadName.startsWith(threadNamePreffix));
+            assertSame(Thread.State.TERMINATED, threadState.state);
+
+        }
+
+        Assert.assertEquals(1, dump.structureIdToStrcutureName.size());
+
+        synchronized (sharedPageLockTracker) {
+            Map<Long, Thread> threadMap0 = U.field(sharedPageLockTracker, "threadIdToThreadRef");
+            Map<Long, ?> threadStacksMap0 = U.field(sharedPageLockTracker, "threadStacks");
+
+            // Stopped threads should remove from map after map limit reached.
+            assertTrue(threadMap0.size() <= threadLimits);
+            assertTrue(threadStacksMap0.size() <= threadLimits);
+        }
+
+        // Await cleanup worker interval.
+        U.sleep(timeOutWorkerInterval + 1000);
+
+        synchronized (sharedPageLockTracker) {
+            Map<Long, Thread> threadMap1 = U.field(sharedPageLockTracker, "threadIdToThreadRef");
+            Map<Long, ?> threadStacksMap1 = U.field(sharedPageLockTracker, "threadStacks");
+
+            // Cleanup worker should remove all stopped threads.
+            assertTrue(threadMap1.isEmpty());
+            assertTrue(threadStacksMap1.isEmpty());
+        }
+
+        ThreadPageLocksDumpLock dump1 = sharedPageLockTracker.dump();
+
+        assertTrue(dump1.time > 0);
+        assertTrue(dump1.threadStates.isEmpty());
+    }
+
+    /**
+     *
+     */
+    @Test
+    public void testAutoDetectHangThreads() throws Exception {
+        String thInWaitName = "threadInWait";
+        String thInRunnableName = "threadInRunnable";
+        String thInAwaitWithoutLocksName = "threadInAwaitWithoutLocks";
+
+        AtomicReference<Exception> error = new AtomicReference<>();
+
+        CountDownLatch awaitLatch = new CountDownLatch(1);
+
+        SharedPageLockTracker sharedPageLockTracker = new SharedPageLockTracker(
+            1000,
+            10_000,
+            hangsThreads -> {
+                if (hangsThreads.isEmpty()) {
+                    error.set(new Exception("No one thread is hangs."));
+
+                    return;
+                }
+
+                // Checking threads.
+                for (SharedPageLockTracker.State state : hangsThreads) {
+                    String name = state.thread.getName();
+
+                    if (name.equals(thInAwaitWithoutLocksName)) {
+                        error.set(new Exception("Thread without locks should not be here." + state));
+                        continue;
+                    }
+
+                    if (name.equals(thInWaitName)) {
+                        if (state.heldLockCnt == 0)
+                            error.set(new Exception("Thread should hold lock." + state));
+
+                        if (state.thread.getState() != Thread.State.WAITING)
+                            error.set(new Exception("Thread should in WAITING state." + state));
+
+                        continue;
+                    }
+
+                    if (name.equals(thInRunnableName)) {
+                        if (state.heldLockCnt == 0)
+                            error.set(new Exception("Thread should hold lock." + state));
+
+                        if (state.thread.getState() != Thread.State.RUNNABLE)
+                            error.set(new Exception("Thread should in RUNNABLE state." + state));
+
+                        continue;
+                    }
+                }
+
+                awaitLatch.countDown();
+            }, new MemoryCalculator()
+        );
+
+        int cacheId = 1;
+        long pageId = 2;
+        long page = 3;
+        long pageAdder = 4;
+
+        PageLockListener lt = sharedPageLockTracker.registrateStructure("test");
+
+        Thread thInWait = new Thread(() -> {
+            lt.onBeforeReadLock(cacheId, pageId, page);
+
+            lt.onReadLock(cacheId, pageId, page, pageAdder);
+
+            try {
+                awaitLatch.await();
+            }
+            catch (InterruptedException ignored) {
+                // No-op.
+            }
+        });
+
+        thInWait.setName(thInWaitName);
+
+        Thread thInRunnable = new Thread(() -> {
+            lt.onBeforeReadLock(cacheId, pageId, page);
+
+            lt.onReadLock(cacheId, pageId, page, pageAdder);
+
+            while (awaitLatch.getCount() > 0) {
+                // Busy wait. Can not park this thread, we should check running hangs too.
+            }
+        });
+
+        thInRunnable.setName(thInRunnableName);
+
+        Thread thInAwaitWithoutLocks = new Thread(() -> {
+            lt.onBeforeReadLock(cacheId, pageId, page);
+
+            lt.onReadLock(cacheId, pageId, page, pageAdder);
+
+            lt.onReadUnlock(cacheId, pageId, page, pageAdder);
+
+            try {
+                awaitLatch.await();
+            }
+            catch (InterruptedException ignored) {
+                // No-op.
+            }
+        });
+
+        thInAwaitWithoutLocks.setName(thInAwaitWithoutLocksName);
+
+        sharedPageLockTracker.start();
+
+        thInWait.start();
+        thInRunnable.start();
+        thInAwaitWithoutLocks.start();
+
+        thInWait.join();
+        thInRunnable.join();
+        thInAwaitWithoutLocks.join();
+
+        if (error.get() != null)
+            throw error.get();
+    }
+
+    /**
+     *
+     */
+    private static class PageMeta {
+        /**
+         *
+         */
+        final int structureId;
+        /**
+         *
+         */
+        final long pageId;
+        /**
+         *
+         */
+        final long page;
+        /**
+         *
+         */
+        final long pageAddr;
+
+        /**
+         *
+         */
+        private PageMeta(
+            int structureId,
+            long pageId,
+            long page,
+            long pageAddr
+        ) {
+            this.structureId = structureId;
+            this.pageId = pageId;
+            this.page = page;
+            this.pageAddr = pageAddr;
+        }
+
+        @Override public String toString() {
+            return "PageMeta{" +
+                "structureId=" + structureId +
+                ", pageId=" + pageId +
+                ", page=" + page +
+                ", pageAddr=" + pageAddr +
+                '}';
+        }
+    }
+}
\ No newline at end of file
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/dumpprocessors/ToFileDumpProcessorTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/dumpprocessors/ToFileDumpProcessorTest.java
new file mode 100644
index 0000000..696ab3b
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/dumpprocessors/ToFileDumpProcessorTest.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.persistence.diagnostic.pagelocktracker.dumpprocessors;
+
+import java.io.File;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.file.StandardOpenOption;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageLockDump;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.LockTrackerFactory;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageLockTracker;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import static java.nio.file.Paths.get;
+
+/**
+ *
+ */
+public class ToFileDumpProcessorTest {
+    /** */
+    private File file;
+
+    @Before
+    public void beforeTest() {
+        cleanFile();
+    }
+
+    @After
+    public void afterTest() {
+        //  cleanFile();
+    }
+
+    /**
+     * Clean files.
+     */
+    public void cleanFile() {
+        if (file != null && file.exists())
+            file.delete();
+    }
+
+    /** */
+    @Test
+    public void toFileDump() throws Exception {
+        String igHome = U.defaultWorkDirectory();
+
+        System.out.println("IGNITE_HOME:" + igHome);
+
+        PageLockTracker pageLockTracker = LockTrackerFactory.create("test");
+
+        pageLockTracker.onBeforeReadLock(1, 2, 3);
+        pageLockTracker.onReadLock(1, 2, 3, 4);
+
+        PageLockDump pageLockDump = pageLockTracker.dump();
+
+        Assert.assertNotNull(pageLockDump);
+
+        String expDumpStr = ToStringDumpProcessor.toStringDump(pageLockDump);
+
+        String filePath = ToFileDumpProcessor.toFileDump(pageLockDump, file = new File(igHome), "test");
+
+        System.out.println("Dump saved:" + filePath);
+
+        boolean found = false;
+
+        for (File file : file.listFiles()) {
+            if (file.getAbsolutePath().equals(filePath)) {
+                found = true;
+
+                break;
+            }
+        }
+
+        Assert.assertTrue(found);
+
+        String actDumpStr;
+
+        try (FileChannel ch = FileChannel.open(get(filePath), StandardOpenOption.READ)) {
+            long size = ch.size();
+
+            ByteBuffer buf = ByteBuffer.allocate((int)size);
+
+            while (buf.position() != buf.capacity())
+                ch.read(buf);
+
+            actDumpStr = new String(buf.array());
+        }
+
+        Assert.assertEquals(expDumpStr, actDumpStr);
+    }
+}
\ No newline at end of file
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/log/HeapArrayLockLogTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/log/HeapArrayLockLogTest.java
new file mode 100644
index 0000000..41fc802
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/log/HeapArrayLockLogTest.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.persistence.diagnostic.pagelocktracker.log;
+
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.LockTrackerFactory;
+
+import static org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.LockTrackerFactory.HEAP_LOG;
+
+/** */
+public class HeapArrayLockLogTest extends PageLockLogTest {
+    /** {@inheritDoc} */
+    @Override protected LockLog createLogStackTracer(String name) {
+        return (LockLog)LockTrackerFactory.create(HEAP_LOG, name);
+    }
+}
\ No newline at end of file
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/log/OffHeapLockLogTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/log/OffHeapLockLogTest.java
new file mode 100644
index 0000000..ef1aed4
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/log/OffHeapLockLogTest.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.persistence.diagnostic.pagelocktracker.log;
+
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.LockTrackerFactory;
+
+import static org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.LockTrackerFactory.OFF_HEAP_LOG;
+
+/** */
+public class OffHeapLockLogTest extends PageLockLogTest {
+    /** {@inheritDoc} */
+    @Override protected LockLog createLogStackTracer(String name) {
+        return (LockLog)LockTrackerFactory.create(OFF_HEAP_LOG, name);
+    }
+}
\ No newline at end of file
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/log/PageLockLogTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/log/PageLockLogTest.java
new file mode 100644
index 0000000..5075d5a
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/log/PageLockLogTest.java
@@ -0,0 +1,641 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.persistence.diagnostic.pagelocktracker.log;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.internal.IgniteInternalFuture;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.AbstractPageLockTest;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.log.PageLockLogSnapshot.LogEntry;
+import org.apache.ignite.testframework.GridTestUtils;
+import org.junit.Assert;
+import org.junit.Test;
+
+import static java.lang.System.out;
+import static java.time.Duration.ofMinutes;
+import static java.util.stream.IntStream.range;
+import static org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.LockTrackerFactory.DEFAULT_CAPACITY;
+import static org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageLockTracker.BEFORE_READ_LOCK;
+import static org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageLockTracker.READ_LOCK;
+import static org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageLockTracker.READ_UNLOCK;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/** */
+public abstract class PageLockLogTest extends AbstractPageLockTest {
+    /** */
+    protected static final int STRUCTURE_ID = 123;
+
+    /** */
+    protected abstract LockLog createLogStackTracer(String name);
+
+    /** */
+    private void checkLogEntry(LogEntry logEntry, long pageId, int operation, int structureId, int holdedLocks) {
+        assertEquals(pageId, logEntry.pageId);
+        assertEquals(operation, logEntry.operation);
+        assertEquals(structureId, logEntry.structureId);
+        assertEquals(holdedLocks, logEntry.holdedLocks);
+    }
+
+    /** */
+    @Test
+    public void testOneReadPageLock() {
+        LockLog lockLog = createLogStackTracer(Thread.currentThread().getName());
+
+        long pageId = 1;
+        long page = 2;
+        long pageAddr = 3;
+
+        PageLockLogSnapshot logDump;
+
+        lockLog.onBeforeReadLock(STRUCTURE_ID, pageId, page);
+
+        logDump = lockLog.dump();
+
+        out.println(logDump);
+
+        assertEquals(0, logDump.headIdx);
+        assertTrue(logDump.locklog.isEmpty());
+        checkNextOp(logDump, pageId, BEFORE_READ_LOCK, STRUCTURE_ID);
+
+        lockLog.onReadLock(STRUCTURE_ID, pageId, page, pageAddr);
+
+        logDump = lockLog.dump();
+
+        out.println(logDump);
+
+        assertEquals(1, logDump.headIdx);
+        checkLogEntry(logDump.locklog.get(0), pageId, READ_LOCK, STRUCTURE_ID, 1);
+        checkNextOp(logDump, 0, 0, 0);
+
+        lockLog.onReadUnlock(STRUCTURE_ID, pageId, page, pageAddr);
+
+        logDump = lockLog.dump();
+
+        out.println(logDump);
+
+        assertTrue(logDump.locklog.isEmpty());
+        checkNextOp(logDump, 0, 0, 0);
+    }
+
+    /** */
+    @Test
+    public void testTwoReadPageLock() {
+        LockLog lockLog = createLogStackTracer(Thread.currentThread().getName());
+
+        long pageId1 = 1;
+        long pageId2 = 11;
+        long page1 = 2;
+        long page2 = 12;
+        long pageAddr1 = 3;
+        long pageAddr2 = 13;
+
+        PageLockLogSnapshot logDump;
+
+        lockLog.onBeforeReadLock(STRUCTURE_ID, pageId1, page1);
+
+        logDump = lockLog.dump();
+
+        out.println(logDump);
+
+        assertEquals(0, logDump.headIdx);
+        assertTrue(logDump.locklog.isEmpty());
+        checkNextOp(logDump, pageId1, BEFORE_READ_LOCK, STRUCTURE_ID);
+
+        lockLog.onReadLock(STRUCTURE_ID, pageId1, page1, pageAddr1);
+
+        logDump = lockLog.dump();
+
+        out.println(logDump);
+
+        assertEquals(1, logDump.headIdx);
+        checkLogEntry(logDump.locklog.get(0), pageId1, READ_LOCK, STRUCTURE_ID, 1);
+        checkNextOp(logDump, 0, 0, 0);
+
+        lockLog.onBeforeReadLock(STRUCTURE_ID, pageId2, page2);
+
+        logDump = lockLog.dump();
+
+        out.println(logDump);
+
+        assertEquals(1, logDump.headIdx);
+        checkLogEntry(logDump.locklog.get(0), pageId1, READ_LOCK, STRUCTURE_ID, 1);
+        checkNextOp(logDump, pageId2, BEFORE_READ_LOCK, STRUCTURE_ID);
+
+        lockLog.onReadLock(STRUCTURE_ID, pageId2, page2, pageAddr2);
+
+        logDump = lockLog.dump();
+
+        out.println(logDump);
+
+        assertEquals(2, logDump.locklog.size());
+
+        checkLogEntry(logDump.locklog.get(0), pageId1, READ_LOCK, STRUCTURE_ID, 1);
+        checkLogEntry(logDump.locklog.get(1), pageId2, READ_LOCK, STRUCTURE_ID, 2);
+        checkNextOp(logDump, 0, 0, 0);
+
+        lockLog.onReadUnlock(STRUCTURE_ID, pageId2, page2, pageAddr2);
+
+        logDump = lockLog.dump();
+
+        out.println(logDump);
+
+        assertEquals(3, logDump.locklog.size());
+
+        checkLogEntry(logDump.locklog.get(0), pageId1, READ_LOCK, STRUCTURE_ID, 1);
+        checkLogEntry(logDump.locklog.get(1), pageId2, READ_LOCK, STRUCTURE_ID, 2);
+        checkLogEntry(logDump.locklog.get(2), pageId2, READ_UNLOCK, STRUCTURE_ID, 1);
+        checkNextOp(logDump, 0, 0, 0);
+
+        lockLog.onReadUnlock(STRUCTURE_ID, pageId1, page1, pageAddr1);
+
+        logDump = lockLog.dump();
+
+        out.println(logDump);
+
+        assertTrue(logDump.locklog.isEmpty());
+        checkNextOp(logDump, 0, 0, 0);
+    }
+
+    /** */
+    @Test
+    public void testThreeReadPageLock_1() {
+        LockLog lockLog = createLogStackTracer(Thread.currentThread().getName());
+
+        long pageId1 = 1;
+        long pageId2 = 11;
+        long pageId3 = 111;
+        long page1 = 2;
+        long page2 = 12;
+        long page3 = 122;
+        long pageAddr1 = 3;
+        long pageAddr2 = 13;
+        long pageAddr3 = 133;
+
+        PageLockLogSnapshot logDump;
+
+        lockLog.onBeforeReadLock(STRUCTURE_ID, pageId1, page1);
+
+        logDump = lockLog.dump();
+
+        out.println(logDump);
+
+        assertEquals(0, logDump.headIdx);
+        assertTrue(logDump.locklog.isEmpty());
+        checkNextOp(logDump, pageId1, BEFORE_READ_LOCK, STRUCTURE_ID);
+
+        lockLog.onReadLock(STRUCTURE_ID, pageId1, page1, pageAddr1);
+
+        logDump = lockLog.dump();
+
+        out.println(logDump);
+
+        assertEquals(1, logDump.headIdx);
+        checkLogEntry(logDump.locklog.get(0), pageId1, READ_LOCK, STRUCTURE_ID, 1);
+        checkNextOp(logDump, 0, 0, 0);
+
+        lockLog.onBeforeReadLock(STRUCTURE_ID, pageId2, page2);
+
+        logDump = lockLog.dump();
+
+        out.println(logDump);
+
+        assertEquals(1, logDump.headIdx);
+        checkLogEntry(logDump.locklog.get(0), pageId1, READ_LOCK, STRUCTURE_ID, 1);
+        checkNextOp(logDump, pageId2, BEFORE_READ_LOCK, STRUCTURE_ID);
+
+        lockLog.onReadLock(STRUCTURE_ID, pageId2, page2, pageAddr2);
+
+        logDump = lockLog.dump();
+
+        out.println(logDump);
+
+        assertEquals(2, logDump.headIdx);
+        checkLogEntry(logDump.locklog.get(0), pageId1, READ_LOCK, STRUCTURE_ID, 1);
+        checkLogEntry(logDump.locklog.get(1), pageId2, READ_LOCK, STRUCTURE_ID, 2);
+        checkNextOp(logDump, 0, 0, 0);
+
+        lockLog.onBeforeReadLock(STRUCTURE_ID, pageId3, page3);
+
+        logDump = lockLog.dump();
+
+        out.println(logDump);
+
+        assertEquals(2, logDump.headIdx);
+        checkLogEntry(logDump.locklog.get(0), pageId1, READ_LOCK, STRUCTURE_ID, 1);
+        checkLogEntry(logDump.locklog.get(1), pageId2, READ_LOCK, STRUCTURE_ID, 2);
+        checkNextOp(logDump, pageId3, BEFORE_READ_LOCK, STRUCTURE_ID);
+
+        lockLog.onReadLock(STRUCTURE_ID, pageId3, page3, pageAddr3);
+
+        logDump = lockLog.dump();
+
+        out.println(logDump);
+
+        assertEquals(3, logDump.headIdx);
+        checkLogEntry(logDump.locklog.get(0), pageId1, READ_LOCK, STRUCTURE_ID, 1);
+        checkLogEntry(logDump.locklog.get(1), pageId2, READ_LOCK, STRUCTURE_ID, 2);
+        checkLogEntry(logDump.locklog.get(2), pageId3, READ_LOCK, STRUCTURE_ID, 3);
+        checkNextOp(logDump, 0, 0, 0);
+
+        lockLog.onReadUnlock(STRUCTURE_ID, pageId3, page3, pageAddr3);
+
+        logDump = lockLog.dump();
+
+        out.println(logDump);
+
+        assertEquals(4, logDump.headIdx);
+        checkLogEntry(logDump.locklog.get(0), pageId1, READ_LOCK, STRUCTURE_ID, 1);
+        checkLogEntry(logDump.locklog.get(1), pageId2, READ_LOCK, STRUCTURE_ID, 2);
+        checkLogEntry(logDump.locklog.get(2), pageId3, READ_LOCK, STRUCTURE_ID, 3);
+        checkLogEntry(logDump.locklog.get(3), pageId3, READ_UNLOCK, STRUCTURE_ID, 2);
+        checkNextOp(logDump, 0, 0, 0);
+
+        lockLog.onReadUnlock(STRUCTURE_ID, pageId2, page2, pageAddr2);
+
+        logDump = lockLog.dump();
+
+        out.println(logDump);
+
+        assertEquals(5, logDump.headIdx);
+        checkLogEntry(logDump.locklog.get(0), pageId1, READ_LOCK, STRUCTURE_ID, 1);
+        checkLogEntry(logDump.locklog.get(1), pageId2, READ_LOCK, STRUCTURE_ID, 2);
+        checkLogEntry(logDump.locklog.get(2), pageId3, READ_LOCK, STRUCTURE_ID, 3);
+        checkLogEntry(logDump.locklog.get(3), pageId3, READ_UNLOCK, STRUCTURE_ID, 2);
+        checkLogEntry(logDump.locklog.get(4), pageId2, READ_UNLOCK, STRUCTURE_ID, 1);
+        checkNextOp(logDump, 0, 0, 0);
+
+        lockLog.onReadUnlock(STRUCTURE_ID, pageId1, page1, pageAddr1);
+
+        logDump = lockLog.dump();
+
+        out.println(logDump);
+
+        assertEquals(0, logDump.headIdx);
+        assertTrue(logDump.locklog.isEmpty());
+        checkNextOp(logDump, 0, 0, 0);
+    }
+
+    /** */
+    @Test
+    public void testThreeReadPageLock_2() {
+        LockLog lockLog = createLogStackTracer(Thread.currentThread().getName());
+
+        long pageId1 = 1;
+        long pageId2 = 11;
+        long pageId3 = 111;
+        long page1 = 2;
+        long page2 = 12;
+        long page3 = 122;
+        long pageAddr1 = 3;
+        long pageAddr2 = 13;
+        long pageAddr3 = 133;
+
+        PageLockLogSnapshot logDump;
+
+        lockLog.onBeforeReadLock(STRUCTURE_ID, pageId1, page1);
+
+        logDump = lockLog.dump();
+
+        out.println(logDump);
+
+        assertEquals(0, logDump.headIdx);
+        assertTrue(logDump.locklog.isEmpty());
+        checkNextOp(logDump, pageId1, BEFORE_READ_LOCK, STRUCTURE_ID);
+
+        lockLog.onReadLock(STRUCTURE_ID, pageId1, page1, pageAddr1);
+
+        logDump = lockLog.dump();
+
+        out.println(logDump);
+
+        assertEquals(1, logDump.headIdx);
+        checkLogEntry(logDump.locklog.get(0), pageId1, READ_LOCK, STRUCTURE_ID, 1);
+        checkNextOp(logDump, 0, 0, 0);
+
+        lockLog.onBeforeReadLock(STRUCTURE_ID, pageId2, page2);
+
+        logDump = lockLog.dump();
+
+        out.println(logDump);
+
+        assertEquals(1, logDump.headIdx);
+        checkLogEntry(logDump.locklog.get(0), pageId1, READ_LOCK, STRUCTURE_ID, 1);
+        checkNextOp(logDump, pageId2, BEFORE_READ_LOCK, STRUCTURE_ID);
+
+        lockLog.onReadLock(STRUCTURE_ID, pageId2, page2, pageAddr2);
+
+        logDump = lockLog.dump();
+
+        out.println(logDump);
+
+        assertEquals(2, logDump.headIdx);
+        checkLogEntry(logDump.locklog.get(0), pageId1, READ_LOCK, STRUCTURE_ID, 1);
+        checkLogEntry(logDump.locklog.get(1), pageId2, READ_LOCK, STRUCTURE_ID, 2);
+        checkNextOp(logDump, 0, 0, 0);
+
+        lockLog.onReadUnlock(STRUCTURE_ID, pageId2, page2, pageAddr2);
+
+        logDump = lockLog.dump();
+
+        out.println(logDump);
+
+        assertEquals(3, logDump.headIdx);
+        checkLogEntry(logDump.locklog.get(0), pageId1, READ_LOCK, STRUCTURE_ID, 1);
+        checkLogEntry(logDump.locklog.get(1), pageId2, READ_LOCK, STRUCTURE_ID, 2);
+        checkLogEntry(logDump.locklog.get(2), pageId2, READ_UNLOCK, STRUCTURE_ID, 1);
+        checkNextOp(logDump, 0, 0, 0);
+
+        lockLog.onBeforeReadLock(STRUCTURE_ID, pageId3, page3);
+
+        logDump = lockLog.dump();
+
+        out.println(logDump);
+
+        assertEquals(3, logDump.headIdx);
+        checkLogEntry(logDump.locklog.get(0), pageId1, READ_LOCK, STRUCTURE_ID, 1);
+        checkLogEntry(logDump.locklog.get(1), pageId2, READ_LOCK, STRUCTURE_ID, 2);
+        checkLogEntry(logDump.locklog.get(2), pageId2, READ_UNLOCK, STRUCTURE_ID, 1);
+        checkNextOp(logDump, pageId3, BEFORE_READ_LOCK, STRUCTURE_ID);
+
+        lockLog.onReadLock(STRUCTURE_ID, pageId3, page3, pageAddr3);
+
+        logDump = lockLog.dump();
+
+        out.println(logDump);
+
+        assertEquals(4, logDump.headIdx);
+        checkLogEntry(logDump.locklog.get(0), pageId1, READ_LOCK, STRUCTURE_ID, 1);
+        checkLogEntry(logDump.locklog.get(1), pageId2, READ_LOCK, STRUCTURE_ID, 2);
+        checkLogEntry(logDump.locklog.get(2), pageId2, READ_UNLOCK, STRUCTURE_ID, 1);
+        checkLogEntry(logDump.locklog.get(3), pageId3, READ_LOCK, STRUCTURE_ID, 2);
+        checkNextOp(logDump, 0, 0, 0);
+
+        lockLog.onReadUnlock(STRUCTURE_ID, pageId3, page3, pageAddr3);
+
+        logDump = lockLog.dump();
+
+        out.println(logDump);
+
+        assertEquals(5, logDump.headIdx);
+        checkLogEntry(logDump.locklog.get(0), pageId1, READ_LOCK, STRUCTURE_ID, 1);
+        checkLogEntry(logDump.locklog.get(1), pageId2, READ_LOCK, STRUCTURE_ID, 2);
+        checkLogEntry(logDump.locklog.get(2), pageId2, READ_UNLOCK, STRUCTURE_ID, 1);
+        checkLogEntry(logDump.locklog.get(3), pageId3, READ_LOCK, STRUCTURE_ID, 2);
+        checkLogEntry(logDump.locklog.get(4), pageId3, READ_UNLOCK, STRUCTURE_ID, 1);
+        checkNextOp(logDump, 0, 0, 0);
+
+        lockLog.onReadUnlock(STRUCTURE_ID, pageId1, page1, pageAddr1);
+
+        logDump = lockLog.dump();
+
+        out.println(logDump);
+
+        assertEquals(0, logDump.headIdx);
+        assertTrue(logDump.locklog.isEmpty());
+        checkNextOp(logDump, 0, 0, 0);
+    }
+
+    /** */
+    @Test
+    public void testThreeReadPageLock_3() {
+        LockLog lockLog = createLogStackTracer(Thread.currentThread().getName());
+
+        long pageId1 = 1;
+        long pageId2 = 11;
+        long pageId3 = 111;
+        long page1 = 2;
+        long page2 = 12;
+        long page3 = 122;
+        long pageAddr1 = 3;
+        long pageAddr2 = 13;
+        long pageAddr3 = 133;
+
+        PageLockLogSnapshot logDump;
+
+        lockLog.onBeforeReadLock(STRUCTURE_ID, pageId1, page1);
+
+        logDump = lockLog.dump();
+
+        out.println(logDump);
+
+        assertEquals(0, logDump.headIdx);
+        assertTrue(logDump.locklog.isEmpty());
+        checkNextOp(logDump, pageId1, BEFORE_READ_LOCK, STRUCTURE_ID);
+
+        lockLog.onReadLock(STRUCTURE_ID, pageId1, page1, pageAddr1);
+
+        logDump = lockLog.dump();
+
+        out.println(logDump);
+
+        assertEquals(1, logDump.headIdx);
+        checkLogEntry(logDump.locklog.get(0), pageId1, READ_LOCK, STRUCTURE_ID, 1);
+        checkNextOp(logDump, 0, 0, 0);
+
+        lockLog.onBeforeReadLock(STRUCTURE_ID, pageId2, page2);
+
+        logDump = lockLog.dump();
+
+        out.println(logDump);
+
+        assertEquals(1, logDump.headIdx);
+        checkLogEntry(logDump.locklog.get(0), pageId1, READ_LOCK, STRUCTURE_ID, 1);
+        checkNextOp(logDump, pageId2, BEFORE_READ_LOCK, STRUCTURE_ID);
+
+        lockLog.onReadLock(STRUCTURE_ID, pageId2, page2, pageAddr2);
+
+        logDump = lockLog.dump();
+
+        out.println(logDump);
+
+        assertEquals(2, logDump.headIdx);
+        checkLogEntry(logDump.locklog.get(0), pageId1, READ_LOCK, STRUCTURE_ID, 1);
+        checkLogEntry(logDump.locklog.get(1), pageId2, READ_LOCK, STRUCTURE_ID, 2);
+        checkNextOp(logDump, 0, 0, 0);
+
+        lockLog.onBeforeReadLock(STRUCTURE_ID, pageId3, page3);
+
+        logDump = lockLog.dump();
+
+        out.println(logDump);
+
+        assertEquals(2, logDump.headIdx);
+        checkLogEntry(logDump.locklog.get(0), pageId1, READ_LOCK, STRUCTURE_ID, 1);
+        checkLogEntry(logDump.locklog.get(1), pageId2, READ_LOCK, STRUCTURE_ID, 2);
+        checkNextOp(logDump, pageId3, BEFORE_READ_LOCK, STRUCTURE_ID);
+
+        lockLog.onReadLock(STRUCTURE_ID, pageId3, page3, pageAddr3);
+
+        logDump = lockLog.dump();
+
+        out.println(logDump);
+
+        assertEquals(3, logDump.headIdx);
+        checkLogEntry(logDump.locklog.get(0), pageId1, READ_LOCK, STRUCTURE_ID, 1);
+        checkLogEntry(logDump.locklog.get(1), pageId2, READ_LOCK, STRUCTURE_ID, 2);
+        checkLogEntry(logDump.locklog.get(2), pageId3, READ_LOCK, STRUCTURE_ID, 3);
+        checkNextOp(logDump, 0,0, 0);
+
+        lockLog.onReadUnlock(STRUCTURE_ID, pageId2, page2, pageAddr2);
+
+        logDump = lockLog.dump();
+
+        out.println(logDump);
+
+        assertEquals(4, logDump.headIdx);
+        checkLogEntry(logDump.locklog.get(0), pageId1, READ_LOCK, STRUCTURE_ID, 1);
+        checkLogEntry(logDump.locklog.get(1), pageId2, READ_LOCK, STRUCTURE_ID, 2);
+        checkLogEntry(logDump.locklog.get(2), pageId3, READ_LOCK, STRUCTURE_ID, 3);
+        checkLogEntry(logDump.locklog.get(3), pageId2, READ_UNLOCK, STRUCTURE_ID, 2);
+        checkNextOp(logDump, 0,0, 0);
+
+        lockLog.onReadUnlock(STRUCTURE_ID, pageId3, page3, pageAddr3);
+
+        out.println(lockLog);
+
+        logDump = lockLog.dump();
+
+        assertEquals(5, logDump.headIdx);
+        checkLogEntry(logDump.locklog.get(0), pageId1, READ_LOCK, STRUCTURE_ID, 1);
+        checkLogEntry(logDump.locklog.get(1), pageId2, READ_LOCK, STRUCTURE_ID, 2);
+        checkLogEntry(logDump.locklog.get(2), pageId3, READ_LOCK, STRUCTURE_ID, 3);
+        checkLogEntry(logDump.locklog.get(3), pageId2, READ_UNLOCK, STRUCTURE_ID, 2);
+        checkLogEntry(logDump.locklog.get(4), pageId3, READ_UNLOCK, STRUCTURE_ID, 1);
+        checkNextOp(logDump, 0,0, 0);
+
+        lockLog.onReadUnlock(STRUCTURE_ID, pageId1, page1, pageAddr1);
+
+        logDump = lockLog.dump();
+
+        out.println(logDump);
+
+        assertEquals(0, logDump.headIdx);
+        assertTrue(logDump.locklog.isEmpty());
+        checkNextOp(logDump, 0, 0, 0);
+    }
+
+    /** */
+    @Test
+    public void testLogOverFlow() {
+        LockLog lockLog = createLogStackTracer(Thread.currentThread().getName());
+
+        long pageId = 1;
+        long page = 2;
+        long pageAddr = 3;
+
+        PageLockLogSnapshot log;
+
+        // Lock log should be invalid after this operation because we can get lock more that
+        // log capacity, +1 for overflow.
+        range(0, DEFAULT_CAPACITY + 1).forEach((i) -> {
+            lockLog.onReadLock(STRUCTURE_ID, pageId, page, pageAddr);
+        });
+
+        out.println(lockLog);
+
+        log = lockLog.dump();
+
+        Assert.assertTrue(lockLog.isInvalid());
+
+        String msg = lockLog.invalidContext().msg;
+
+        Assert.assertTrue(msg, msg.contains("Log overflow"));
+    }
+
+    /** */
+    @Test
+    public void testThreadlog() throws IgniteCheckedException {
+        LockLog lockLog = createLogStackTracer(Thread.currentThread().getName());
+
+        long pageId = 1;
+        long page = 2;
+        long pageAddr = 3;
+
+        int cntlogs = 5_000;
+
+        AtomicBoolean done = new AtomicBoolean();
+
+        int maxWaitTime = 500;
+
+        int maxdeep = 16;
+
+        IgniteInternalFuture f = GridTestUtils.runAsync(() -> {
+            while (!done.get()) {
+                int iter = nextRandomWaitTimeout(maxdeep);
+
+                doRunnable(iter, () -> {
+                    awaitRandom(100);
+
+                    lockLog.onBeforeReadLock(STRUCTURE_ID, pageId, page);
+
+                    awaitRandom(100);
+
+                    lockLog.onReadLock(STRUCTURE_ID, pageId, page, pageAddr);
+                });
+
+                try {
+                    awaitRandom(maxWaitTime);
+                }
+                finally {
+                    doRunnable(iter, () -> {
+                        lockLog.onReadUnlock(STRUCTURE_ID, pageId, page, pageAddr);
+                    });
+                }
+            }
+        });
+
+        long totalExecutionTime = 0L;
+
+        for (int i = 0; i < cntlogs; i++) {
+            awaitRandom(50);
+
+            long time = System.nanoTime();
+
+            PageLockLogSnapshot logDump = lockLog.dump();
+
+            long logTime = System.nanoTime() - time;
+
+            if (logDump.nextOp != 0)
+                assertTrue(logDump.nextOpPageId != 0);
+
+            assertTrue(logDump.time != 0);
+            Assert.assertNotNull(logDump.name);
+
+            if (logDump.headIdx > 0) {
+                //TODO
+               /* for (int j = 0; j < log.headIdx; j++)
+                    Assert.assertTrue(String.valueOf(log.headIdx), log.pageIdLocksStack[j] != 0);*/
+            }
+
+            Assert.assertNotNull(logDump);
+
+            totalExecutionTime += logTime;
+
+            assertTrue(logTime <= ofMinutes((long)(maxWaitTime + (maxWaitTime * 0.1))).toNanos());
+
+            if (i != 0 && i % 100 == 0)
+                out.println(">>> log:" + i);
+        }
+
+        done.set(true);
+
+        f.get();
+
+        out.println(">>> Avarage time log creation:" + (totalExecutionTime / cntlogs) + " ns");
+    }
+}
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/stack/HeapArrayLockStackTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/stack/HeapArrayLockStackTest.java
new file mode 100644
index 0000000..942f251
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/stack/HeapArrayLockStackTest.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.persistence.diagnostic.pagelocktracker.stack;
+
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.LockTrackerFactory;
+
+import static org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.LockTrackerFactory.HEAP_STACK;
+
+/** */
+public class HeapArrayLockStackTest extends PageLockStackTest {
+    /** {@inheritDoc} */
+    @Override protected LockStack createLockStackTracer(String name) {
+        return (LockStack)LockTrackerFactory.create(HEAP_STACK, name);
+    }
+}
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/stack/OffHeapLockStackTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/stack/OffHeapLockStackTest.java
new file mode 100644
index 0000000..2f44643
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/stack/OffHeapLockStackTest.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.persistence.diagnostic.pagelocktracker.stack;
+
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.LockTrackerFactory;
+
+import static org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.LockTrackerFactory.OFF_HEAP_STACK;
+
+/** */
+public class OffHeapLockStackTest extends PageLockStackTest {
+    /** {@inheritDoc} */
+    @Override protected LockStack createLockStackTracer(String name) {
+        return (LockStack)LockTrackerFactory.create(OFF_HEAP_STACK, name);
+    }
+}
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/stack/PageLockStackTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/stack/PageLockStackTest.java
new file mode 100644
index 0000000..d20d031
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/diagnostic/pagelocktracker/stack/PageLockStackTest.java
@@ -0,0 +1,751 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.persistence.diagnostic.pagelocktracker.stack;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.internal.IgniteInternalFuture;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.AbstractPageLockTest;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.LockTrackerFactory;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageLockTracker;
+import org.apache.ignite.testframework.GridTestUtils;
+import org.junit.Assert;
+import org.junit.Test;
+
+import static java.time.Duration.ofMinutes;
+import static java.util.stream.IntStream.range;
+import static org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageLockTracker.BEFORE_READ_LOCK;
+
+/** */
+public abstract class PageLockStackTest extends AbstractPageLockTest {
+    /** */
+    protected static final int STRUCTURE_ID = 123;
+    /** */
+    protected abstract LockStack createLockStackTracer(String name);
+
+    /** */
+    @Test
+    public void testOneReadPageLock() {
+        LockStack lockStack = createLockStackTracer(Thread.currentThread().getName());
+
+        long pageId = 1;
+        long page = 2;
+        long pageAddr = 3;
+
+        PageLockStackSnapshot dump;
+
+        lockStack.onBeforeReadLock(STRUCTURE_ID, pageId, page);
+
+        dump = lockStack.dump();
+
+        Assert.assertEquals(0, dump.headIdx);
+        Assert.assertTrue(String.valueOf(dump.pageIdLocksStack), dump.pageIdLocksStack.isEmpty());
+        Assert.assertEquals(pageId, dump.nextOpPageId);
+        Assert.assertEquals(BEFORE_READ_LOCK, dump.nextOp);
+
+        lockStack.onReadLock(STRUCTURE_ID, pageId, page, pageAddr);
+
+        dump = lockStack.dump();
+
+        Assert.assertEquals(1, dump.headIdx);
+        Assert.assertEquals(pageId, dump.pageIdLocksStack.getPageId(0));
+        Assert.assertEquals(0, dump.nextOpPageId);
+        Assert.assertEquals(0, dump.nextOp);
+
+        lockStack.onReadUnlock(STRUCTURE_ID, pageId, page, pageAddr);
+
+        dump = lockStack.dump();
+
+        Assert.assertEquals(0, dump.headIdx);
+        Assert.assertTrue(dump.pageIdLocksStack.isEmpty());
+        Assert.assertEquals(0, dump.nextOpPageId);
+        Assert.assertEquals(0, dump.nextOp);
+    }
+
+    /** */
+    @Test
+    public void testTwoReadPageLock() {
+        LockStack lockStack = createLockStackTracer(Thread.currentThread().getName());
+
+        long pageId1 = 1;
+        long pageId2 = 11;
+        long page1 = 2;
+        long page2 = 12;
+        long pageAddr1 = 3;
+        long pageAddr2 = 13;
+
+        PageLockStackSnapshot dump;
+
+        lockStack.onBeforeReadLock(STRUCTURE_ID, pageId1, page1);
+
+        dump = lockStack.dump();
+
+        Assert.assertEquals(0, dump.headIdx);
+        Assert.assertTrue(dump.pageIdLocksStack.isEmpty());
+        Assert.assertEquals(pageId1, dump.nextOpPageId);
+        Assert.assertEquals(BEFORE_READ_LOCK, dump.nextOp);
+
+        lockStack.onReadLock(STRUCTURE_ID, pageId1, page1, pageAddr1);
+
+        dump = lockStack.dump();
+
+        Assert.assertEquals(1, dump.headIdx);
+        Assert.assertEquals(pageId1, dump.pageIdLocksStack.getPageId(0));
+        Assert.assertEquals(0, dump.nextOpPageId);
+        Assert.assertEquals(0, dump.nextOp);
+
+        lockStack.onBeforeReadLock(STRUCTURE_ID, pageId2, page2);
+
+        dump = lockStack.dump();
+
+        Assert.assertEquals(1, dump.headIdx);
+        Assert.assertEquals(pageId1, dump.pageIdLocksStack.getPageId(0));
+        Assert.assertEquals(pageId2, dump.nextOpPageId);
+        Assert.assertEquals(BEFORE_READ_LOCK, dump.nextOp);
+
+        lockStack.onReadLock(STRUCTURE_ID, pageId2, page2, pageAddr2);
+
+        dump = lockStack.dump();
+
+        Assert.assertEquals(2, dump.headIdx);
+        Assert.assertEquals(pageId1, dump.pageIdLocksStack.getPageId(0));
+        Assert.assertEquals(pageId2, dump.pageIdLocksStack.getPageId(1));
+        Assert.assertEquals(0, dump.nextOpPageId);
+        Assert.assertEquals(0, dump.nextOp);
+
+        lockStack.onReadUnlock(STRUCTURE_ID, pageId2, page2, pageAddr2);
+
+        dump = lockStack.dump();
+
+        Assert.assertEquals(1, dump.headIdx);
+        Assert.assertEquals(pageId1, dump.pageIdLocksStack.getPageId(0));
+        Assert.assertEquals(0, dump.pageIdLocksStack.getPageId(1));
+        Assert.assertEquals(0, dump.nextOpPageId);
+        Assert.assertEquals(0, dump.nextOp);
+
+        lockStack.onReadUnlock(STRUCTURE_ID, pageId1, page1, pageAddr1);
+
+        dump = lockStack.dump();
+
+        Assert.assertEquals(0, dump.headIdx);
+        Assert.assertTrue(dump.pageIdLocksStack.isEmpty());
+        Assert.assertEquals(0, dump.nextOpPageId);
+        Assert.assertEquals(0, dump.nextOp);
+    }
+
+    /** */
+    @Test
+    public void testThreeReadPageLock_1() {
+        LockStack lockStack = createLockStackTracer(Thread.currentThread().getName());
+
+        long pageId1 = 1;
+        long pageId2 = 11;
+        long pageId3 = 111;
+        long page1 = 2;
+        long page2 = 12;
+        long page3 = 122;
+        long pageAddr1 = 3;
+        long pageAddr2 = 13;
+        long pageAddr3 = 133;
+
+        PageLockStackSnapshot dump;
+
+        lockStack.onBeforeReadLock(STRUCTURE_ID, pageId1, page1);
+
+        dump = lockStack.dump();
+
+        Assert.assertEquals(0, dump.headIdx);
+        Assert.assertTrue(dump.pageIdLocksStack.isEmpty());
+        Assert.assertEquals(pageId1, dump.nextOpPageId);
+        Assert.assertEquals(BEFORE_READ_LOCK, dump.nextOp);
+
+        lockStack.onReadLock(STRUCTURE_ID, pageId1, page1, pageAddr1);
+
+        dump = lockStack.dump();
+
+        Assert.assertEquals(1, dump.headIdx);
+        Assert.assertEquals(pageId1, dump.pageIdLocksStack.getPageId(0));
+        Assert.assertEquals(0, dump.nextOpPageId);
+        Assert.assertEquals(0, dump.nextOp);
+
+        lockStack.onBeforeReadLock(STRUCTURE_ID, pageId2, page2);
+
+        dump = lockStack.dump();
+
+        Assert.assertEquals(1, dump.headIdx);
+        Assert.assertEquals(pageId1, dump.pageIdLocksStack.getPageId(0));
+        Assert.assertEquals(pageId2, dump.nextOpPageId);
+        Assert.assertEquals(BEFORE_READ_LOCK, dump.nextOp);
+
+        lockStack.onReadLock(STRUCTURE_ID, pageId2, page2, pageAddr2);
+
+        dump = lockStack.dump();
+
+        Assert.assertEquals(2, dump.headIdx);
+        Assert.assertEquals(pageId1, dump.pageIdLocksStack.getPageId(0));
+        Assert.assertEquals(pageId2, dump.pageIdLocksStack.getPageId(1));
+        Assert.assertEquals(0, dump.nextOpPageId);
+        Assert.assertEquals(0, dump.nextOp);
+
+        lockStack.onBeforeReadLock(STRUCTURE_ID, pageId3, page3);
+
+        dump = lockStack.dump();
+
+        Assert.assertEquals(2, dump.headIdx);
+        Assert.assertEquals(pageId1, dump.pageIdLocksStack.getPageId(0));
+        Assert.assertEquals(pageId2, dump.pageIdLocksStack.getPageId(1));
+        Assert.assertEquals(pageId3, dump.nextOpPageId);
+        Assert.assertEquals(BEFORE_READ_LOCK, dump.nextOp);
+
+        lockStack.onReadLock(STRUCTURE_ID, pageId3, page3, pageAddr3);
+
+        dump = lockStack.dump();
+
+        Assert.assertEquals(3, dump.headIdx);
+        Assert.assertEquals(pageId1, dump.pageIdLocksStack.getPageId(0));
+        Assert.assertEquals(pageId2, dump.pageIdLocksStack.getPageId(1));
+        Assert.assertEquals(pageId3, dump.pageIdLocksStack.getPageId(2));
+        Assert.assertEquals(0, dump.nextOpPageId);
+        Assert.assertEquals(0, dump.nextOp);
+
+        lockStack.onReadUnlock(STRUCTURE_ID, pageId3, page3, pageAddr3);
+
+        dump = lockStack.dump();
+
+        Assert.assertEquals(2, dump.headIdx);
+        Assert.assertEquals(pageId1, dump.pageIdLocksStack.getPageId(0));
+        Assert.assertEquals(pageId2, dump.pageIdLocksStack.getPageId(1));
+        Assert.assertEquals(0, dump.pageIdLocksStack.getPageId(2));
+        Assert.assertEquals(0, dump.nextOpPageId);
+        Assert.assertEquals(0, dump.nextOp);
+
+        lockStack.onReadUnlock(STRUCTURE_ID, pageId2, page2, pageAddr2);
+
+        dump = lockStack.dump();
+
+        Assert.assertEquals(1, dump.headIdx);
+        Assert.assertEquals(pageId1, dump.pageIdLocksStack.getPageId(0));
+        Assert.assertEquals(0, dump.pageIdLocksStack.getPageId(1));
+        Assert.assertEquals(0, dump.pageIdLocksStack.getPageId(2));
+        Assert.assertEquals(0, dump.nextOpPageId);
+        Assert.assertEquals(0, dump.nextOp);
+
+        lockStack.onReadUnlock(STRUCTURE_ID, pageId1, page1, pageAddr1);
+
+        dump = lockStack.dump();
+
+        Assert.assertEquals(0, dump.headIdx);
+        Assert.assertTrue(dump.pageIdLocksStack.isEmpty());
+        Assert.assertEquals(0, dump.nextOpPageId);
+        Assert.assertEquals(0, dump.nextOp);
+    }
+
+    /** */
+    @Test
+    public void testThreeReadPageLock_2() {
+        LockStack lockStack = createLockStackTracer(Thread.currentThread().getName());
+
+        long pageId1 = 1;
+        long pageId2 = 11;
+        long pageId3 = 111;
+        long page1 = 2;
+        long page2 = 12;
+        long page3 = 122;
+        long pageAddr1 = 3;
+        long pageAddr2 = 13;
+        long pageAddr3 = 133;
+
+        PageLockStackSnapshot dump;
+
+        lockStack.onBeforeReadLock(STRUCTURE_ID, pageId1, page1);
+
+        dump = lockStack.dump();
+
+        Assert.assertEquals(0, dump.headIdx);
+        Assert.assertTrue(dump.pageIdLocksStack.isEmpty());
+        Assert.assertEquals(pageId1, dump.nextOpPageId);
+        Assert.assertEquals(BEFORE_READ_LOCK, dump.nextOp);
+
+        lockStack.onReadLock(STRUCTURE_ID, pageId1, page1, pageAddr1);
+
+        dump = lockStack.dump();
+
+        Assert.assertEquals(1, dump.headIdx);
+        Assert.assertEquals(pageId1, dump.pageIdLocksStack.getPageId(0));
+        Assert.assertEquals(0, dump.nextOpPageId);
+        Assert.assertEquals(0, dump.nextOp);
+
+        lockStack.onBeforeReadLock(STRUCTURE_ID, pageId2, page2);
+
+        dump = lockStack.dump();
+
+        Assert.assertEquals(1, dump.headIdx);
+        Assert.assertEquals(pageId1, dump.pageIdLocksStack.getPageId(0));
+        Assert.assertEquals(pageId2, dump.nextOpPageId);
+        Assert.assertEquals(BEFORE_READ_LOCK, dump.nextOp);
+
+        lockStack.onReadLock(STRUCTURE_ID, pageId2, page2, pageAddr2);
+
+        dump = lockStack.dump();
+
+        Assert.assertEquals(2, dump.headIdx);
+        Assert.assertEquals(pageId1, dump.pageIdLocksStack.getPageId(0));
+        Assert.assertEquals(pageId2, dump.pageIdLocksStack.getPageId(1));
+        Assert.assertEquals(0, dump.nextOpPageId);
+        Assert.assertEquals(0, dump.nextOp);
+
+        lockStack.onReadUnlock(STRUCTURE_ID, pageId2, page2, pageAddr2);
+
+        dump = lockStack.dump();
+
+        Assert.assertEquals(1, dump.headIdx);
+        Assert.assertEquals(pageId1, dump.pageIdLocksStack.getPageId(0));
+        Assert.assertEquals(0, dump.pageIdLocksStack.getPageId(1));
+        Assert.assertEquals(0, dump.nextOpPageId);
+        Assert.assertEquals(0, dump.nextOp);
+
+        lockStack.onBeforeReadLock(STRUCTURE_ID, pageId3, page3);
+
+        dump = lockStack.dump();
+
+        Assert.assertEquals(1, dump.headIdx);
+        Assert.assertEquals(pageId1, dump.pageIdLocksStack.getPageId(0));
+        Assert.assertEquals(pageId3, dump.nextOpPageId);
+        Assert.assertEquals(BEFORE_READ_LOCK, dump.nextOp);
+
+        lockStack.onReadLock(STRUCTURE_ID, pageId3, page3, pageAddr3);
+
+        dump = lockStack.dump();
+
+        Assert.assertEquals(2, dump.headIdx);
+        Assert.assertEquals(pageId1, dump.pageIdLocksStack.getPageId(0));
+        Assert.assertEquals(pageId3, dump.pageIdLocksStack.getPageId(1));
+        Assert.assertEquals(0, dump.nextOpPageId);
+        Assert.assertEquals(0, dump.nextOp);
+
+        lockStack.onReadUnlock(STRUCTURE_ID, pageId3, page3, pageAddr3);
+
+        dump = lockStack.dump();
+
+        Assert.assertEquals(1, dump.headIdx);
+        Assert.assertEquals(pageId1, dump.pageIdLocksStack.getPageId(0));
+        Assert.assertEquals(0, dump.pageIdLocksStack.getPageId(1));
+        Assert.assertEquals(0, dump.nextOpPageId);
+        Assert.assertEquals(0, dump.nextOp);
+
+        lockStack.onReadUnlock(STRUCTURE_ID, pageId1, page1, pageAddr1);
+
+        dump = lockStack.dump();
+
+        Assert.assertEquals(0, dump.headIdx);
+        Assert.assertTrue(dump.pageIdLocksStack.isEmpty());
+        Assert.assertEquals(0, dump.nextOpPageId);
+        Assert.assertEquals(0, dump.nextOp);
+    }
+
+    /** */
+    @Test
+    public void testThreeReadPageLock_3() {
+        LockStack lockStack = createLockStackTracer(Thread.currentThread().getName());
+
+        long pageId1 = 1;
+        long pageId2 = 11;
+        long pageId3 = 111;
+        long page1 = 2;
+        long page2 = 12;
+        long page3 = 122;
+        long pageAddr1 = 3;
+        long pageAddr2 = 13;
+        long pageAddr3 = 133;
+
+        PageLockStackSnapshot dump;
+
+        lockStack.onBeforeReadLock(STRUCTURE_ID, pageId1, page1);
+
+        dump = lockStack.dump();
+
+        Assert.assertEquals(0, dump.headIdx);
+        Assert.assertTrue(dump.pageIdLocksStack.isEmpty());
+        Assert.assertEquals(pageId1, dump.nextOpPageId);
+        Assert.assertEquals(BEFORE_READ_LOCK, dump.nextOp);
+
+        lockStack.onReadLock(STRUCTURE_ID, pageId1, page1, pageAddr1);
+
+        dump = lockStack.dump();
+
+        Assert.assertEquals(1, dump.headIdx);
+        Assert.assertEquals(pageId1, dump.pageIdLocksStack.getPageId(0));
+        Assert.assertEquals(0, dump.nextOpPageId);
+        Assert.assertEquals(0, dump.nextOp);
+
+        lockStack.onBeforeReadLock(STRUCTURE_ID, pageId2, page2);
+
+        dump = lockStack.dump();
+
+        Assert.assertEquals(1, dump.headIdx);
+        Assert.assertEquals(pageId1, dump.pageIdLocksStack.getPageId(0));
+        Assert.assertEquals(pageId2, dump.nextOpPageId);
+        Assert.assertEquals(BEFORE_READ_LOCK, dump.nextOp);
+
+        lockStack.onReadLock(STRUCTURE_ID, pageId2, page2, pageAddr2);
+
+        dump = lockStack.dump();
+
+        Assert.assertEquals(2, dump.headIdx);
+        Assert.assertEquals(pageId1, dump.pageIdLocksStack.getPageId(0));
+        Assert.assertEquals(pageId2, dump.pageIdLocksStack.getPageId(1));
+        Assert.assertEquals(0, dump.nextOpPageId);
+        Assert.assertEquals(0, dump.nextOp);
+
+        lockStack.onBeforeReadLock(STRUCTURE_ID, pageId3, page3);
+
+        dump = lockStack.dump();
+
+        Assert.assertEquals(2, dump.headIdx);
+        Assert.assertEquals(pageId1, dump.pageIdLocksStack.getPageId(0));
+        Assert.assertEquals(pageId2, dump.pageIdLocksStack.getPageId(1));
+        Assert.assertEquals(pageId3, dump.nextOpPageId);
+        Assert.assertEquals(BEFORE_READ_LOCK, dump.nextOp);
+
+        lockStack.onReadLock(STRUCTURE_ID, pageId3, page3, pageAddr3);
+
+        dump = lockStack.dump();
+
+        Assert.assertEquals(3, dump.headIdx);
+        Assert.assertEquals(pageId1, dump.pageIdLocksStack.getPageId(0));
+        Assert.assertEquals(pageId2, dump.pageIdLocksStack.getPageId(1));
+        Assert.assertEquals(pageId3, dump.pageIdLocksStack.getPageId(2));
+        Assert.assertEquals(0, dump.nextOpPageId);
+        Assert.assertEquals(0, dump.nextOp);
+
+        lockStack.onReadUnlock(STRUCTURE_ID, pageId2, page2, pageAddr2);
+
+        dump = lockStack.dump();
+
+        Assert.assertEquals(3, dump.headIdx);
+        Assert.assertEquals(pageId1, dump.pageIdLocksStack.getPageId(0));
+        Assert.assertEquals(0, dump.pageIdLocksStack.getPageId(1));
+        Assert.assertEquals(pageId3, dump.pageIdLocksStack.getPageId(2));
+        Assert.assertEquals(0, dump.nextOpPageId);
+        Assert.assertEquals(0, dump.nextOp);
+
+        lockStack.onReadUnlock(STRUCTURE_ID, pageId3, page3, pageAddr3);
+
+        dump = lockStack.dump();
+
+        Assert.assertEquals(1, dump.headIdx);
+        Assert.assertEquals(pageId1, dump.pageIdLocksStack.getPageId(0));
+        Assert.assertEquals(0, dump.pageIdLocksStack.getPageId(1));
+        Assert.assertEquals(0, dump.pageIdLocksStack.getPageId(2));
+        Assert.assertEquals(0, dump.nextOpPageId);
+        Assert.assertEquals(0, dump.nextOp);
+
+        lockStack.onReadUnlock(STRUCTURE_ID, pageId1, page1, pageAddr1);
+
+        dump = lockStack.dump();
+
+        Assert.assertEquals(0, dump.headIdx);
+        Assert.assertTrue(dump.pageIdLocksStack.isEmpty());
+        Assert.assertEquals(0, dump.nextOpPageId);
+        Assert.assertEquals(0, dump.nextOp);
+    }
+
+    /** */
+    @Test
+    public void testUnlockUnexcpected() {
+        LockStack lockStack = createLockStackTracer(Thread.currentThread().getName());
+
+        long pageId = 1;
+        long page = 2;
+        long pageAddr = 3;
+
+        PageLockStackSnapshot dump;
+
+        // Lock stack should be invalid after this operation because we can not unlock page
+        // which was not locked.
+        lockStack.onReadUnlock(STRUCTURE_ID, pageId, page, pageAddr);
+
+        dump = lockStack.dump();
+
+        Assert.assertTrue(lockStack.isInvalid());
+        String msg = lockStack.invalidContext().msg;
+
+        Assert.assertTrue(msg, msg.contains("Stack is empty"));
+
+        Assert.assertEquals(0, dump.headIdx);
+        Assert.assertTrue(dump.pageIdLocksStack.isEmpty());
+        Assert.assertEquals(0, dump.nextOpPageId);
+        Assert.assertEquals(0, dump.nextOp);
+    }
+
+    /** */
+    @Test
+    public void testUnlockUnexcpectedOnNotEmptyStack() {
+        LockStack lockStack = createLockStackTracer(Thread.currentThread().getName());
+
+        long pageId1 = 1;
+        long pageId2 = 11;
+        long page1 = 2;
+        long page2 = 12;
+        long pageAddr1 = 3;
+        long pageAddr2 = 13;
+
+        PageLockStackSnapshot dump;
+
+        lockStack.onReadLock(STRUCTURE_ID, pageId1, page1, pageAddr1);
+
+        // Lock stack should be invalid after this operation because we can not unlock page
+        // which was not locked.
+        lockStack.onReadUnlock(STRUCTURE_ID, pageId2, page2, pageAddr2);
+
+        dump = lockStack.dump();
+
+        Assert.assertTrue(lockStack.isInvalid());
+        String msg = lockStack.invalidContext().msg;
+
+        Assert.assertTrue(msg, msg.contains("Can not find pageId in stack"));
+
+        Assert.assertEquals(1, dump.headIdx);
+        Assert.assertEquals(pageId1, dump.pageIdLocksStack.getPageId(0));
+        Assert.assertEquals(0, dump.nextOpPageId);
+        Assert.assertEquals(0, dump.nextOp);
+    }
+
+    /** */
+    @Test
+    public void testUnlockUnexcpectedOnNotEmptyStackMultiLocks() {
+        LockStack lockStack = createLockStackTracer(Thread.currentThread().getName());
+
+        long pageId1 = 1;
+        long pageId2 = 11;
+        long pageId3 = 111;
+        long pageId4 = 1111;
+        long page1 = 2;
+        long page2 = 12;
+        long page3 = 122;
+        long page4 = 1222;
+        long pageAddr1 = 3;
+        long pageAddr2 = 13;
+        long pageAddr3 = 133;
+        long pageAddr4 = 1333;
+
+        PageLockStackSnapshot dump;
+
+        lockStack.onReadLock(STRUCTURE_ID, pageId1, page1, pageAddr1);
+        lockStack.onReadLock(STRUCTURE_ID, pageId2, page2, pageAddr2);
+        lockStack.onReadLock(STRUCTURE_ID, pageId3, page3, pageAddr3);
+
+        // Lock stack should be invalid after this operation because we can not unlock page
+        // which was not locked.
+        lockStack.onReadUnlock(STRUCTURE_ID, pageId4, page4, pageAddr4);
+
+        dump = lockStack.dump();
+
+        Assert.assertTrue(lockStack.isInvalid());
+        String msg = lockStack.invalidContext().msg;
+
+        Assert.assertTrue(msg, msg.contains("Can not find pageId in stack"));
+
+        Assert.assertEquals(3, dump.headIdx);
+        Assert.assertEquals(pageId1, dump.pageIdLocksStack.getPageId(0));
+        Assert.assertEquals(pageId2, dump.pageIdLocksStack.getPageId(1));
+        Assert.assertEquals(pageId3, dump.pageIdLocksStack.getPageId(2));
+        Assert.assertEquals(0, dump.nextOpPageId);
+        Assert.assertEquals(0, dump.nextOp);
+    }
+
+    /** */
+    @Test
+    public void testStackOverFlow() {
+        LockStack lockStack = createLockStackTracer(Thread.currentThread().getName());
+
+        long pageId = 1;
+        long page = 2;
+        long pageAddr = 3;
+
+        PageLockStackSnapshot dump;
+
+        // Lock stack should be invalid after this operation because we can get lock more that
+        // stack capacity, +1 for overflow.
+        range(0, LockTrackerFactory.DEFAULT_CAPACITY + 1).forEach((i) -> {
+            lockStack.onReadLock(STRUCTURE_ID, pageId, page, pageAddr);
+        });
+
+        dump = lockStack.dump();
+
+        Assert.assertTrue(lockStack.isInvalid());
+        Assert.assertTrue(lockStack.invalidContext().msg.contains("Stack overflow"));
+
+        Assert.assertEquals(LockTrackerFactory.DEFAULT_CAPACITY, dump.headIdx);
+        Assert.assertFalse(dump.pageIdLocksStack.isEmpty());
+        Assert.assertEquals(0, dump.nextOpPageId);
+        Assert.assertEquals(0, dump.nextOp);
+    }
+
+    /** */
+    @Test
+    public void testStackOperationAfterInvalid() {
+        LockStack lockStack = createLockStackTracer(Thread.currentThread().getName());
+
+        long pageId = 1;
+        long page = 2;
+        long pageAddr = 3;
+
+        PageLockStackSnapshot dump;
+
+        // Lock stack should be invalid after this operation because we can not unlock page
+        // which was not locked.
+        lockStack.onReadUnlock(STRUCTURE_ID, pageId, page, pageAddr);
+
+        dump = lockStack.dump();
+
+        Assert.assertTrue(lockStack.isInvalid());
+        String msg = lockStack.invalidContext().msg;
+
+        Assert.assertTrue(msg, msg.contains("Stack is empty"));
+
+        System.out.println(lockStack.invalidContext());
+
+        Assert.assertEquals(0, dump.headIdx);
+        Assert.assertTrue(dump.pageIdLocksStack.isEmpty());
+        Assert.assertEquals(0, dump.nextOpPageId);
+        Assert.assertEquals(0, dump.nextOp);
+
+        lockStack.onBeforeReadLock(STRUCTURE_ID, pageId, page);
+
+        Assert.assertTrue(lockStack.isInvalid());
+        msg = lockStack.invalidContext().msg;
+
+        Assert.assertTrue(msg, msg.contains("Stack is empty"));
+
+        Assert.assertEquals(0, dump.headIdx);
+        Assert.assertTrue(dump.pageIdLocksStack.isEmpty());
+        Assert.assertEquals(0, dump.nextOpPageId);
+        Assert.assertEquals(0, dump.nextOp);
+
+        lockStack.onReadLock(STRUCTURE_ID, pageId, page, pageAddr);
+
+        Assert.assertTrue(lockStack.isInvalid());
+        msg = lockStack.invalidContext().msg;
+
+        Assert.assertTrue(msg, msg.contains("Stack is empty"));
+
+        Assert.assertEquals(0, dump.headIdx);
+        Assert.assertTrue(dump.pageIdLocksStack.isEmpty());
+        Assert.assertEquals(0, dump.nextOpPageId);
+        Assert.assertEquals(0, dump.nextOp);
+
+        lockStack.onReadUnlock(STRUCTURE_ID, pageId, page, pageAddr);
+
+        Assert.assertTrue(lockStack.isInvalid());
+        msg = lockStack.invalidContext().msg;
+
+        Assert.assertTrue(msg, msg.contains("Stack is empty"));
+
+        Assert.assertEquals(0, dump.headIdx);
+        Assert.assertTrue(dump.pageIdLocksStack.isEmpty());
+        Assert.assertEquals(0, dump.nextOpPageId);
+        Assert.assertEquals(0, dump.nextOp);
+    }
+
+    /** */
+    @Test
+    public void testThreadDump() throws IgniteCheckedException {
+        PageLockTracker<PageLockStackSnapshot> lockStack = createLockStackTracer(Thread.currentThread().getName());
+
+        long pageId = 1;
+        long page = 2;
+        long pageAddr = 3;
+
+        int cntDumps = 5_000;
+
+        AtomicBoolean done = new AtomicBoolean();
+
+        int maxWaitTime = 500;
+
+        int maxdeep = 16;
+
+        IgniteInternalFuture f = GridTestUtils.runAsync(() -> {
+            while (!done.get()) {
+                int iter = nextRandomWaitTimeout(maxdeep);
+
+                doRunnable(iter, () -> {
+                    awaitRandom(100);
+
+                    lockStack.onBeforeReadLock(STRUCTURE_ID, pageId, page);
+
+                    awaitRandom(100);
+
+                    lockStack.onReadLock(STRUCTURE_ID, pageId, page, pageAddr);
+                });
+
+                try {
+                    awaitRandom(maxWaitTime);
+                }
+                finally {
+                    doRunnable(iter, () -> {
+                        lockStack.onReadUnlock(STRUCTURE_ID, pageId, page, pageAddr);
+                    });
+                }
+            }
+        });
+
+        long totalExecutionTime = 0L;
+
+        for (int i = 0; i < cntDumps; i++) {
+            awaitRandom(50);
+
+            long time = System.nanoTime();
+
+            PageLockStackSnapshot dump = lockStack.dump();
+
+            long dumpTime = System.nanoTime() - time;
+
+            if (dump.nextOp != 0)
+                Assert.assertTrue(dump.nextOpPageId != 0);
+
+            Assert.assertTrue(dump.time != 0);
+            Assert.assertNotNull(dump.name);
+
+            if (dump.headIdx > 0) {
+                for (int itemIdx = 0; itemIdx < dump.headIdx; itemIdx++) {
+                    Assert.assertTrue(String.valueOf(dump.headIdx), dump.pageIdLocksStack.getPageId(itemIdx) != 0);
+                    Assert.assertTrue(dump.pageIdLocksStack.getOperation(itemIdx) != 0);
+                    Assert.assertTrue(dump.pageIdLocksStack.getStructureId(itemIdx) != 0);
+                    Assert.assertTrue(dump.pageIdLocksStack.getPageAddrHeader(itemIdx) != 0);
+                    Assert.assertTrue(dump.pageIdLocksStack.getPageAddr(itemIdx) != 0);
+                }
+            }
+
+            Assert.assertNotNull(dump);
+
+            totalExecutionTime += dumpTime;
+
+            Assert.assertTrue(dumpTime <= ofMinutes((long)(maxWaitTime + (maxWaitTime * 0.1))).toNanos());
+
+            if (i != 0 && i % 100 == 0)
+                System.out.println(">>> Dump:" + i);
+        }
+
+        done.set(true);
+
+        f.get();
+
+        System.out.println(">>> Avarage time dump creation:" + (totalExecutionTime / cntDumps) + " ns");
+    }
+
+}
\ No newline at end of file
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/BPlusTreePageMemoryImplTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/BPlusTreePageMemoryImplTest.java
index 43f51f7..7b81cfa 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/BPlusTreePageMemoryImplTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/BPlusTreePageMemoryImplTest.java
@@ -24,6 +24,7 @@ import org.apache.ignite.internal.mem.DirectMemoryProvider;
 import org.apache.ignite.internal.mem.unsafe.UnsafeMemoryProvider;
 import org.apache.ignite.internal.pagemem.FullPageId;
 import org.apache.ignite.internal.pagemem.PageMemory;
+import org.apache.ignite.internal.processors.cache.CacheDiagnosticManager;
 import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
 import org.apache.ignite.internal.processors.cache.persistence.CheckpointWriteProgressSupplier;
 import org.apache.ignite.internal.processors.cache.persistence.DataRegionMetricsImpl;
@@ -80,7 +81,8 @@ public class BPlusTreePageMemoryImplTest extends BPlusTreeSelfTest {
             null,
             null,
             null,
-            null
+            null,
+            new CacheDiagnosticManager()
         );
 
         PageMemory mem = new PageMemoryImpl(
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/BPlusTreeReuseListPageMemoryImplTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/BPlusTreeReuseListPageMemoryImplTest.java
index 20d55eb..8b62314 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/BPlusTreeReuseListPageMemoryImplTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/BPlusTreeReuseListPageMemoryImplTest.java
@@ -80,6 +80,7 @@ public class BPlusTreeReuseListPageMemoryImplTest extends BPlusTreeReuseSelfTest
             null,
             null,
             null,
+            null,
             null
         );
 
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/IndexStoragePageMemoryImplTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/IndexStoragePageMemoryImplTest.java
index 529f723..0673623 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/IndexStoragePageMemoryImplTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/IndexStoragePageMemoryImplTest.java
@@ -25,6 +25,7 @@ import org.apache.ignite.internal.mem.DirectMemoryProvider;
 import org.apache.ignite.internal.mem.file.MappedFileMemoryProvider;
 import org.apache.ignite.internal.pagemem.FullPageId;
 import org.apache.ignite.internal.pagemem.PageMemory;
+import org.apache.ignite.internal.processors.cache.CacheDiagnosticManager;
 import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
 import org.apache.ignite.internal.processors.cache.persistence.CheckpointWriteProgressSupplier;
 import org.apache.ignite.internal.processors.cache.persistence.DataRegionMetricsImpl;
@@ -95,7 +96,8 @@ public class IndexStoragePageMemoryImplTest extends IndexStorageSelfTest {
             null,
             null,
             null,
-            null
+            null,
+            new CacheDiagnosticManager()
         );
 
         return new PageMemoryImpl(
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImplNoLoadTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImplNoLoadTest.java
index becdaeb..66261c4 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImplNoLoadTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImplNoLoadTest.java
@@ -89,6 +89,7 @@ public class PageMemoryImplNoLoadTest extends PageMemoryNoLoadSelfTest {
             null,
             null,
             null,
+            null,
             null
         );
 
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImplTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImplTest.java
index 20114f5..8e7fb35 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImplTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImplTest.java
@@ -315,6 +315,7 @@ public class PageMemoryImplTest extends GridCommonAbstractTest {
             null,
             null,
             null,
+            null,
             null
         );
 
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/database/BPlusTreeReuseSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/database/BPlusTreeReuseSelfTest.java
index 992d897..f581334 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/database/BPlusTreeReuseSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/database/BPlusTreeReuseSelfTest.java
@@ -24,6 +24,7 @@ import org.apache.ignite.internal.pagemem.wal.IgniteWriteAheadLogManager;
 import org.apache.ignite.internal.processors.cache.persistence.tree.io.PageIO;
 import org.apache.ignite.internal.processors.cache.persistence.tree.reuse.ReuseList;
 import org.apache.ignite.internal.processors.cache.persistence.tree.reuse.ReuseListImpl;
+import org.apache.ignite.internal.processors.cache.persistence.tree.util.PageLockListener;
 
 import static org.apache.ignite.internal.pagemem.PageIdUtils.effectivePageId;
 
@@ -32,9 +33,20 @@ import static org.apache.ignite.internal.pagemem.PageIdUtils.effectivePageId;
  */
 public class BPlusTreeReuseSelfTest extends BPlusTreeSelfTest {
     /** {@inheritDoc} */
-    @Override protected ReuseList createReuseList(int cacheId, PageMemory pageMem, long rootId, boolean initNew)
-        throws IgniteCheckedException {
-        return new TestReuseList(cacheId, "test", pageMem, null, rootId, initNew);
+    @Override protected ReuseList createReuseList(
+        int cacheId,
+        PageMemory pageMem,
+        long rootId,
+        boolean initNew
+    ) throws IgniteCheckedException {
+        return new TestReuseList(
+            cacheId,
+            "test",
+            pageMem,
+            null,
+            rootId,
+            initNew
+        );
     }
 
     /** {@inheritDoc} */
@@ -48,19 +60,6 @@ public class BPlusTreeReuseSelfTest extends BPlusTreeSelfTest {
      *
      */
     private static class TestReuseList extends ReuseListImpl {
-        /** */
-        private static ThreadLocal<Set<Long>> readLocks = new ThreadLocal<Set<Long>>() {
-            @Override protected Set<Long> initialValue() {
-                return new HashSet<>();
-            }
-        };
-
-        /** */
-        private static ThreadLocal<Set<Long>> writeLocks = new ThreadLocal<Set<Long>>() {
-            @Override protected Set<Long> initialValue() {
-                return new HashSet<>();
-            }
-        };
 
         /**
          * @param cacheId    Cache ID.
@@ -79,9 +78,34 @@ public class BPlusTreeReuseSelfTest extends BPlusTreeSelfTest {
             long metaPageId,
             boolean initNew
         ) throws IgniteCheckedException {
-            super(cacheId, name, pageMem, wal, metaPageId, initNew);
+            super(cacheId, name, pageMem, wal, metaPageId, initNew, new TestPageLockListener());
         }
 
+        /**
+         *
+         */
+        static boolean checkNoLocks() {
+            return TestPageLockListener.readLocks.get().isEmpty() && TestPageLockListener.writeLocks.get().isEmpty();
+        }
+    }
+
+    /** */
+    private static class TestPageLockListener implements PageLockListener {
+
+        /** */
+        private static ThreadLocal<Set<Long>> readLocks = new ThreadLocal<Set<Long>>() {
+            @Override protected Set<Long> initialValue() {
+                return new HashSet<>();
+            }
+        };
+
+        /** */
+        private static ThreadLocal<Set<Long>> writeLocks = new ThreadLocal<Set<Long>>() {
+            @Override protected Set<Long> initialValue() {
+                return new HashSet<>();
+            }
+        };
+
         /** {@inheritDoc} */
         @Override public void onBeforeReadLock(int cacheId, long pageId, long page) {
             // No-op.
@@ -122,9 +146,5 @@ public class BPlusTreeReuseSelfTest extends BPlusTreeSelfTest {
 
             assertTrue(writeLocks.get().remove(pageId));
         }
-
-        static boolean checkNoLocks() {
-            return readLocks.get().isEmpty() && writeLocks.get().isEmpty();
-        }
     }
 }
\ No newline at end of file
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/database/BPlusTreeSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/database/BPlusTreeSelfTest.java
index 14cc760..6ccf667 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/database/BPlusTreeSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/database/BPlusTreeSelfTest.java
@@ -63,6 +63,7 @@ import org.apache.ignite.internal.processors.cache.persistence.tree.io.BPlusLeaf
 import org.apache.ignite.internal.processors.cache.persistence.tree.io.IOVersions;
 import org.apache.ignite.internal.processors.cache.persistence.tree.io.PageIO;
 import org.apache.ignite.internal.processors.cache.persistence.tree.reuse.ReuseList;
+import org.apache.ignite.internal.processors.cache.persistence.tree.util.PageLockListener;
 import org.apache.ignite.internal.util.GridConcurrentHashSet;
 import org.apache.ignite.internal.util.GridRandom;
 import org.apache.ignite.internal.util.GridStripedLock;
@@ -83,6 +84,7 @@ import org.junit.runners.JUnit4;
 
 import static org.apache.ignite.internal.pagemem.PageIdUtils.effectivePageId;
 import static org.apache.ignite.internal.processors.cache.persistence.tree.BPlusTree.rnd;
+import static org.apache.ignite.internal.processors.database.BPlusTreeSelfTest.TestTree.threadId;
 import static org.apache.ignite.internal.util.IgniteTree.OperationType.NOOP;
 import static org.apache.ignite.internal.util.IgniteTree.OperationType.PUT;
 import static org.apache.ignite.internal.util.IgniteTree.OperationType.REMOVE;
@@ -143,7 +145,7 @@ public class BPlusTreeSelfTest extends GridCommonAbstractTest {
      * Check that we do not keep any locks at the moment.
      */
     protected void assertNoLocks() {
-        assertTrue(TestTree.checkNoLocks());
+        assertTrue(TestPageLockListener.checkNoLocks());
     }
 
     /** {@inheritDoc} */
@@ -2733,7 +2735,8 @@ public class BPlusTreeSelfTest extends GridCommonAbstractTest {
      * @throws IgniteCheckedException If failed.
      */
     protected TestTree createTestTree(boolean canGetRow) throws IgniteCheckedException {
-        TestTree tree = new TestTree(reuseList, canGetRow, CACHE_ID, pageMem, allocateMetaPage().pageId());
+        TestTree tree = new TestTree(
+            reuseList, canGetRow, CACHE_ID, pageMem, allocateMetaPage().pageId(), new TestPageLockListener());
 
         assertEquals(0, tree.size());
         assertEquals(0, tree.rootLevel());
@@ -2753,18 +2756,6 @@ public class BPlusTreeSelfTest extends GridCommonAbstractTest {
      * Test tree.
      */
     protected static class TestTree extends BPlusTree<Long, Long> {
-        /** */
-        private static ConcurrentMap<Object, Long> beforeReadLock = new ConcurrentHashMap<>();
-
-        /** */
-        private static ConcurrentMap<Object, Long> beforeWriteLock = new ConcurrentHashMap<>();
-
-        /** */
-        private static ConcurrentMap<Object, Map<Long, Long>> readLocks = new ConcurrentHashMap<>();
-
-        /** */
-        private static ConcurrentMap<Object, Map<Long, Long>> writeLocks = new ConcurrentHashMap<>();
-
         /** Number of retries. */
         private int numRetries = super.getLockRetries();
 
@@ -2776,10 +2767,27 @@ public class BPlusTreeSelfTest extends GridCommonAbstractTest {
          * @param metaPageId Meta page ID.
          * @throws IgniteCheckedException If failed.
          */
-        public TestTree(ReuseList reuseList, boolean canGetRow, int cacheId, PageMemory pageMem, long metaPageId)
-            throws IgniteCheckedException {
-            super("test", cacheId, pageMem, null, new AtomicLong(), metaPageId, reuseList,
-                new IOVersions<>(new LongInnerIO(canGetRow)), new IOVersions<>(new LongLeafIO()), null);
+        public TestTree(
+            ReuseList reuseList,
+            boolean canGetRow,
+            int cacheId,
+            PageMemory pageMem,
+            long metaPageId,
+            TestPageLockListener lsnr
+        ) throws IgniteCheckedException {
+            super(
+                "test",
+                cacheId,
+                pageMem,
+                null,
+                new AtomicLong(),
+                metaPageId,
+                reuseList,
+                new IOVersions<>(new LongInnerIO(canGetRow)),
+                new IOVersions<>(new LongLeafIO()),
+                null,
+                lsnr
+            );
 
             PageIO.registerTest(latestInnerIO(), latestLeafIO());
 
@@ -2805,114 +2813,10 @@ public class BPlusTreeSelfTest extends GridCommonAbstractTest {
         /**
          * @return Thread ID.
          */
-        private static Object threadId() {
+        static Object threadId() {
             return Thread.currentThread().getId(); //.getName();
         }
 
-        /**
-         * @param read Read or write locks.
-         * @return Locks map.
-         */
-        private static Map<Long, Long> locks(boolean read) {
-            ConcurrentMap<Object, Map<Long, Long>> m = read ? readLocks : writeLocks;
-
-            Object thId = threadId();
-
-            Map<Long, Long> locks = m.get(thId);
-
-            if (locks == null) {
-                locks = new ConcurrentLinkedHashMap<>();
-
-                if (m.putIfAbsent(thId, locks) != null)
-                    locks = m.get(thId);
-            }
-
-            return locks;
-        }
-
-        /** {@inheritDoc} */
-        @Override public void onBeforeReadLock(int cacheId, long pageId, long page) {
-            if (PRINT_LOCKS)
-                X.println("  onBeforeReadLock: " + U.hexLong(pageId));
-//
-//            U.dumpStack();
-
-            assertNull(beforeReadLock.put(threadId(), pageId));
-        }
-
-        /** {@inheritDoc} */
-        @Override public void onReadLock(int cacheId, long pageId, long page, long pageAddr) {
-            if (PRINT_LOCKS)
-                X.println("  onReadLock: " + U.hexLong(pageId));
-
-            if (pageAddr != 0L) {
-                long actual = PageIO.getPageId(pageAddr);
-
-                checkPageId(pageId, pageAddr);
-
-                assertNull(locks(true).put(pageId, actual));
-            }
-
-            assertEquals(Long.valueOf(pageId), beforeReadLock.remove(threadId()));
-        }
-
-        /** {@inheritDoc} */
-        @Override public void onReadUnlock(int cacheId, long pageId, long page, long pageAddr) {
-            if (PRINT_LOCKS)
-                X.println("  onReadUnlock: " + U.hexLong(pageId));
-
-            checkPageId(pageId, pageAddr);
-
-            long actual = PageIO.getPageId(pageAddr);
-
-            assertEquals(Long.valueOf(actual), locks(true).remove(pageId));
-        }
-
-        /** {@inheritDoc} */
-        @Override public void onBeforeWriteLock(int cacheId, long pageId, long page) {
-            if (PRINT_LOCKS)
-                X.println("  onBeforeWriteLock: " + U.hexLong(pageId));
-
-            assertNull(beforeWriteLock.put(threadId(), pageId));
-        }
-
-        /** {@inheritDoc} */
-        @Override public void onWriteLock(int cacheId, long pageId, long page, long pageAddr) {
-            if (PRINT_LOCKS)
-                X.println("  onWriteLock: " + U.hexLong(pageId));
-//
-//            U.dumpStack();
-
-            if (pageAddr != 0L) {
-                checkPageId(pageId, pageAddr);
-
-                long actual = PageIO.getPageId(pageAddr);
-
-                if (actual == 0L)
-                    actual = pageId; // It is a newly allocated page.
-
-                assertNull(locks(false).put(pageId, actual));
-            }
-
-            assertEquals(Long.valueOf(pageId), beforeWriteLock.remove(threadId()));
-        }
-
-        /** {@inheritDoc} */
-        @Override public void onWriteUnlock(int cacheId, long pageId, long page, long pageAddr) {
-            if (PRINT_LOCKS)
-                X.println("  onWriteUnlock: " + U.hexLong(pageId));
-
-            assertEquals(effectivePageId(pageId), effectivePageId(PageIO.getPageId(pageAddr)));
-
-            assertEquals(Long.valueOf(pageId), locks(false).remove(pageId));
-        }
-
-        /**
-         * @return {@code true} If current thread does not keep any locks.
-         */
-        static boolean checkNoLocks() {
-            return locks(true).isEmpty() && locks(false).isEmpty();
-        }
 
         /**
          * @param b String builder.
@@ -2952,11 +2856,11 @@ public class BPlusTreeSelfTest extends GridCommonAbstractTest {
 
             b.a("\n--------read---------\n");
 
-            printLocks(b, readLocks, beforeReadLock);
+            printLocks(b, TestPageLockListener.readLocks, TestPageLockListener.beforeReadLock);
 
             b.a("\n-+------write---------\n");
 
-            printLocks(b, writeLocks, beforeWriteLock);
+            printLocks(b, TestPageLockListener.writeLocks, TestPageLockListener.beforeWriteLock);
 
             return b.toString();
         }
@@ -3152,4 +3056,127 @@ public class BPlusTreeSelfTest extends GridCommonAbstractTest {
             return vals.contains(val);
         }
     }
+
+    private static class TestPageLockListener implements PageLockListener {
+        /** */
+        static ConcurrentMap<Object, Long> beforeReadLock = new ConcurrentHashMap<>();
+
+        /** */
+        static ConcurrentMap<Object, Long> beforeWriteLock = new ConcurrentHashMap<>();
+
+        /** */
+        static ConcurrentMap<Object, Map<Long, Long>> readLocks = new ConcurrentHashMap<>();
+
+        /** */
+        static ConcurrentMap<Object, Map<Long, Long>> writeLocks = new ConcurrentHashMap<>();
+
+
+        /** {@inheritDoc} */
+        @Override public void onBeforeReadLock(int cacheId, long pageId, long page) {
+            if (PRINT_LOCKS)
+                X.println("  onBeforeReadLock: " + U.hexLong(pageId));
+//
+//            U.dumpStack();
+
+            assertNull(beforeReadLock.put(threadId(), pageId));
+        }
+
+        /** {@inheritDoc} */
+        @Override public void onReadLock(int cacheId, long pageId, long page, long pageAddr) {
+            if (PRINT_LOCKS)
+                X.println("  onReadLock: " + U.hexLong(pageId));
+
+            if (pageAddr != 0L) {
+                long actual = PageIO.getPageId(pageAddr);
+
+                checkPageId(pageId, pageAddr);
+
+                assertNull(locks(true).put(pageId, actual));
+            }
+
+            assertEquals(Long.valueOf(pageId), beforeReadLock.remove(threadId()));
+        }
+
+        /** {@inheritDoc} */
+        @Override public void onReadUnlock(int cacheId, long pageId, long page, long pageAddr) {
+            if (PRINT_LOCKS)
+                X.println("  onReadUnlock: " + U.hexLong(pageId));
+
+            checkPageId(pageId, pageAddr);
+
+            long actual = PageIO.getPageId(pageAddr);
+
+            assertEquals(Long.valueOf(actual), locks(true).remove(pageId));
+        }
+
+        /** {@inheritDoc} */
+        @Override public void onBeforeWriteLock(int cacheId, long pageId, long page) {
+            if (PRINT_LOCKS)
+                X.println("  onBeforeWriteLock: " + U.hexLong(pageId));
+
+            assertNull(beforeWriteLock.put(threadId(), pageId));
+        }
+
+        /** {@inheritDoc} */
+        @Override public void onWriteLock(int cacheId, long pageId, long page, long pageAddr) {
+            if (PRINT_LOCKS)
+                X.println("  onWriteLock: " + U.hexLong(pageId));
+//
+//            U.dumpStack();
+
+            if (pageAddr != 0L) {
+                checkPageId(pageId, pageAddr);
+
+                long actual = PageIO.getPageId(pageAddr);
+
+                if (actual == 0L)
+                    actual = pageId; // It is a newly allocated page.
+
+                assertNull(locks(false).put(pageId, actual));
+            }
+
+            assertEquals(Long.valueOf(pageId), beforeWriteLock.remove(threadId()));
+        }
+
+        /** {@inheritDoc} */
+        @Override public void onWriteUnlock(int cacheId, long pageId, long page, long pageAddr) {
+            if (PRINT_LOCKS)
+                X.println("  onWriteUnlock: " + U.hexLong(pageId));
+
+            assertEquals(effectivePageId(pageId), effectivePageId(PageIO.getPageId(pageAddr)));
+
+            assertEquals(Long.valueOf(pageId), locks(false).remove(pageId));
+        }
+
+        /**
+         * @param read Read or write locks.
+         * @return Locks map.
+         */
+        private static Map<Long, Long> locks(boolean read) {
+            ConcurrentMap<Object, Map<Long, Long>> m = read ? readLocks : writeLocks;
+
+            Object thId = threadId();
+
+            Map<Long, Long> locks = m.get(thId);
+
+            if (locks == null) {
+                locks = new ConcurrentLinkedHashMap<>();
+
+                if (m.putIfAbsent(thId, locks) != null)
+                    locks = m.get(thId);
+            }
+
+            return locks;
+        }
+
+
+
+        /**
+         * @return {@code true} If current thread does not keep any locks.
+         */
+        static boolean checkNoLocks() {
+            return locks(true).isEmpty() && locks(false).isEmpty();
+        }
+
+    }
 }
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/database/CacheFreeListImplSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/database/CacheFreeListSelfTest.java
similarity index 98%
rename from modules/core/src/test/java/org/apache/ignite/internal/processors/database/CacheFreeListImplSelfTest.java
rename to modules/core/src/test/java/org/apache/ignite/internal/processors/database/CacheFreeListSelfTest.java
index a852321..d1e905c 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/database/CacheFreeListImplSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/database/CacheFreeListSelfTest.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
@@ -42,7 +42,7 @@ import org.apache.ignite.internal.processors.cache.persistence.CacheDataRow;
 import org.apache.ignite.internal.processors.cache.persistence.DataRegion;
 import org.apache.ignite.internal.processors.cache.persistence.DataRegionMetricsImpl;
 import org.apache.ignite.internal.processors.cache.persistence.evict.NoOpPageEvictionTracker;
-import org.apache.ignite.internal.processors.cache.persistence.freelist.CacheFreeListImpl;
+import org.apache.ignite.internal.processors.cache.persistence.freelist.CacheFreeList;
 import org.apache.ignite.internal.processors.cache.persistence.freelist.FreeList;
 import org.apache.ignite.internal.processors.cache.persistence.tree.io.CacheVersionIO;
 import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
@@ -59,7 +59,7 @@ import org.junit.runners.JUnit4;
  *
  */
 @RunWith(JUnit4.class)
-public class CacheFreeListImplSelfTest extends GridCommonAbstractTest {
+public class CacheFreeListSelfTest extends GridCommonAbstractTest {
     /** */
     private static final int CPUS = Runtime.getRuntime().availableProcessors();
 
@@ -361,7 +361,17 @@ public class CacheFreeListImplSelfTest extends GridCommonAbstractTest {
 
         DataRegion dataRegion = new DataRegion(pageMem, plcCfg, regionMetrics, new NoOpPageEvictionTracker());
 
-        return new CacheFreeListImpl(1, "freelist", regionMetrics, dataRegion, null, null, metaPageId, true);
+        return new CacheFreeList(
+            1,
+            "freelist",
+            regionMetrics,
+            dataRegion,
+            null,
+            null,
+            metaPageId,
+            true,
+            null
+        );
     }
 
     /**
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/database/IndexStorageSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/database/IndexStorageSelfTest.java
index b2e8e82..309633ba 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/database/IndexStorageSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/database/IndexStorageSelfTest.java
@@ -111,6 +111,7 @@ public class IndexStorageSelfTest extends GridCommonAbstractTest {
                         null,
                         mem.allocatePage(cacheId, PageIdAllocator.INDEX_PARTITION, PageMemory.FLAG_IDX),
                         true,
+                        null,
                         null
                     );
 
diff --git a/modules/core/src/test/java/org/apache/ignite/loadtests/hashmap/GridCacheTestContext.java b/modules/core/src/test/java/org/apache/ignite/loadtests/hashmap/GridCacheTestContext.java
index e9edff1..46811bd 100644
--- a/modules/core/src/test/java/org/apache/ignite/loadtests/hashmap/GridCacheTestContext.java
+++ b/modules/core/src/test/java/org/apache/ignite/loadtests/hashmap/GridCacheTestContext.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
@@ -21,6 +21,7 @@ import org.apache.ignite.cache.store.CacheStore;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
 import org.apache.ignite.internal.processors.cache.CacheAffinitySharedManager;
+import org.apache.ignite.internal.processors.cache.CacheDiagnosticManager;
 import org.apache.ignite.internal.processors.cache.CacheOsConflictResolutionManager;
 import org.apache.ignite.internal.processors.cache.CacheType;
 import org.apache.ignite.internal.processors.cache.GridCacheAffinityManager;
@@ -83,7 +84,8 @@ public class GridCacheTestContext<K, V> extends GridCacheContext<K, V> {
                 new CacheNoopJtaManager(),
                 null,
                 null,
-                null
+                null,
+                new CacheDiagnosticManager()
             ),
             defaultCacheConfiguration(),
             null,
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicTestSuite.java
index 3d1ae50..e707f13 100644
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicTestSuite.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicTestSuite.java
@@ -71,7 +71,7 @@ import org.apache.ignite.internal.processors.continuous.GridMessageListenSelfTes
 import org.apache.ignite.internal.processors.database.BPlusTreeFakeReuseSelfTest;
 import org.apache.ignite.internal.processors.database.BPlusTreeReuseSelfTest;
 import org.apache.ignite.internal.processors.database.BPlusTreeSelfTest;
-import org.apache.ignite.internal.processors.database.CacheFreeListImplSelfTest;
+import org.apache.ignite.internal.processors.database.CacheFreeListSelfTest;
 import org.apache.ignite.internal.processors.database.DataRegionMetricsSelfTest;
 import org.apache.ignite.internal.processors.database.IndexStorageSelfTest;
 import org.apache.ignite.internal.processors.database.SwapPathConstructionSelfTest;
@@ -202,7 +202,7 @@ public class IgniteBasicTestSuite {
         suite.addTest(new JUnit4TestAdapter(BPlusTreeFakeReuseSelfTest.class));
         suite.addTest(new JUnit4TestAdapter(BPlusTreeReuseSelfTest.class));
         suite.addTest(new JUnit4TestAdapter(IndexStorageSelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(CacheFreeListImplSelfTest.class));
+        suite.addTest(new JUnit4TestAdapter(CacheFreeListSelfTest.class));
         suite.addTest(new JUnit4TestAdapter(DataRegionMetricsSelfTest.class));
         suite.addTest(new JUnit4TestAdapter(SwapPathConstructionSelfTest.class));
         suite.addTest(new JUnit4TestAdapter(BitSetIntSetTest.class));
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePdsTestSuite4.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePdsTestSuite4.java
index c199c3c..92f1202 100644
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePdsTestSuite4.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePdsTestSuite4.java
@@ -31,6 +31,13 @@ import org.apache.ignite.internal.processors.cache.persistence.db.IgnitePdsPageE
 import org.apache.ignite.internal.processors.cache.persistence.db.IgnitePdsPartitionPreloadTest;
 import org.apache.ignite.internal.processors.cache.persistence.db.IgnitePdsStartWIthEmptyArchive;
 import org.apache.ignite.internal.processors.cache.persistence.db.IgnitePdsTransactionsHangTest;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageLockTrackerManagerTest;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.SharedPageLockTrackerTest;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.dumpprocessors.ToFileDumpProcessorTest;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.log.HeapArrayLockLogTest;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.log.OffHeapLockLogTest;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.stack.HeapArrayLockStackTest;
+import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.stack.OffHeapLockStackTest;
 import org.apache.ignite.internal.processors.cache.persistence.file.FileDownloaderTest;
 import org.apache.ignite.testframework.GridTestUtils;
 import org.junit.runner.RunWith;
@@ -68,6 +75,15 @@ public class IgnitePdsTestSuite4 {
         GridTestUtils.addTestIfNeeded(suite, IgnitePdsStartWIthEmptyArchive.class, ignoredTests);
         GridTestUtils.addTestIfNeeded(suite, CorruptedTreeFailureHandlingTest.class, ignoredTests);
 
+        // Page lock tracker tests.
+        GridTestUtils.addTestIfNeeded(suite, PageLockTrackerManagerTest.class, ignoredTests);
+        GridTestUtils.addTestIfNeeded(suite, SharedPageLockTrackerTest.class, ignoredTests);
+        GridTestUtils.addTestIfNeeded(suite, ToFileDumpProcessorTest.class, ignoredTests);
+        GridTestUtils.addTestIfNeeded(suite, HeapArrayLockLogTest.class, ignoredTests);
+        GridTestUtils.addTestIfNeeded(suite, HeapArrayLockStackTest.class, ignoredTests);
+        GridTestUtils.addTestIfNeeded(suite, OffHeapLockLogTest.class, ignoredTests);
+        GridTestUtils.addTestIfNeeded(suite, OffHeapLockStackTest.class, ignoredTests);
+
         return suite;
     }
 
diff --git a/modules/core/src/test/java/org/apache/ignite/util/GridCommandHandlerTest.java b/modules/core/src/test/java/org/apache/ignite/util/GridCommandHandlerTest.java
index 1778498..e97f82d 100644
--- a/modules/core/src/test/java/org/apache/ignite/util/GridCommandHandlerTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/util/GridCommandHandlerTest.java
@@ -1066,7 +1066,7 @@ public class GridCommandHandlerTest extends GridCommandHandlerAbstractTest {
         for (CacheSubcommands cmd : CacheSubcommands.values()) {
             Class<? extends Enum<? extends CommandArg>> args = cmd.getCommandArgs();
 
-            if(args != null)
+            if (args != null)
                 for (Enum<? extends CommandArg> arg : args.getEnumConstants())
                     assertTrue(arg.toString(), p.matcher(arg.toString()).matches());
         }
@@ -2454,9 +2454,53 @@ public class GridCommandHandlerTest extends GridCommandHandlerAbstractTest {
     }
 
     /**
-     * Starts several long transactions in order to test --tx command.
-     * Transactions will last until unlock latch is released: first transaction will wait for unlock latch directly,
-     * some others will wait for key lock acquisition.
+     * Test execution of --diagnostic command.
+     *
+     * @throws Exception if failed.
+     */
+    @Test
+    public void testDiagnosticPageLocksTracker() throws Exception {
+        Ignite ignite = startGrids(4);
+
+        Collection<ClusterNode> nodes = ignite.cluster().nodes();
+
+        List<ClusterNode> nodes0 = new ArrayList<>(nodes);
+
+        ClusterNode node0 = nodes0.get(0);
+        ClusterNode node1 = nodes0.get(1);
+        ClusterNode node2 = nodes0.get(2);
+        ClusterNode node3 = nodes0.get(3);
+
+        ignite.cluster().active(true);
+
+        String dir = U.defaultWorkDirectory() + "/diagnostic/";
+
+        assertEquals(EXIT_CODE_OK, execute("--diagnostic"));
+        assertEquals(EXIT_CODE_OK, execute("--diagnostic", "help"));
+        assertEquals(EXIT_CODE_OK, execute("--diagnostic", "pageLocks", "help"));
+
+        assertEquals(EXIT_CODE_OK, execute("--diagnostic", "pageLocks", "dump"));
+        assertEquals(EXIT_CODE_OK, execute("--diagnostic", "pageLocks", "dump_log"));
+        assertEquals(EXIT_CODE_OK, execute("--diagnostic", "pageLocks", "dump", dir));
+
+        assertEquals(EXIT_CODE_OK, execute("--diagnostic", "pageLocks", "dump", "--all"));
+        assertEquals(EXIT_CODE_OK, execute("--diagnostic", "pageLocks", "dump_log", "--all"));
+        assertEquals(EXIT_CODE_OK, execute("--diagnostic", "pageLocks", "dump", dir, "--all"));
+
+        assertEquals(EXIT_CODE_OK, execute("--diagnostic", "pageLocks", "dump", "--nodes",
+            node0.id().toString(), node2.id().toString()));
+        assertEquals(EXIT_CODE_OK, execute("--diagnostic", "pageLocks", "dump", "--nodes",
+            node0.consistentId().toString(), node2.consistentId().toString()));
+
+        assertEquals(EXIT_CODE_OK, execute("--diagnostic", "pageLocks", "dump_log", "--nodes",
+            node1.id().toString(), node3.id().toString()));
+        assertEquals(EXIT_CODE_OK, execute("--diagnostic", "pageLocks", "dump", dir, "--nodes",
+            node1.consistentId().toString(), node3.consistentId().toString()));
+    }
+
+    /**
+     * Starts several long transactions in order to test --tx command. Transactions will last until unlock latch is
+     * released: first transaction will wait for unlock latch directly, some others will wait for key lock acquisition.
      *
      * @param lockLatch Lock latch. Will be released inside body of the first transaction.
      * @param unlockLatch Unlock latch. Should be released externally. First transaction won't be finished until unlock
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
index 15e8993..b90093c 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
@@ -79,6 +79,7 @@ import org.apache.ignite.internal.processors.cache.persistence.tree.io.BPlusIO;
 import org.apache.ignite.internal.processors.cache.persistence.tree.io.BPlusMetaIO;
 import org.apache.ignite.internal.processors.cache.persistence.tree.io.PageIO;
 import org.apache.ignite.internal.processors.cache.persistence.tree.reuse.ReuseList;
+import org.apache.ignite.internal.processors.cache.persistence.tree.util.PageLockListener;
 import org.apache.ignite.internal.processors.cache.query.GridCacheQueryMarshallable;
 import org.apache.ignite.internal.processors.cache.query.GridCacheTwoStepQuery;
 import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode;
@@ -3204,6 +3205,11 @@ public class IgniteH2Indexing implements GridQueryIndexing {
 
         int inlineSize = getInlineSize(page, grpId, pageMemory);
 
+        String grpName = ctx.cache().cacheGroup(grpId).cacheOrGroupName();
+
+        PageLockListener lockLsnr = ctx.cache().context().diagnostic()
+            .pageLockTracker().createPageLockTracker(grpName + "IndexTree##" + indexName);
+
         BPlusTree<GridH2SearchRow, GridH2Row> tree = new BPlusTree<GridH2SearchRow, GridH2Row>(
             indexName,
             grpId,
@@ -3214,7 +3220,8 @@ public class IgniteH2Indexing implements GridQueryIndexing {
             reuseList,
             H2ExtrasInnerIO.getVersions(inlineSize, mvccEnabled),
             H2ExtrasLeafIO.getVersions(inlineSize, mvccEnabled),
-            ctx.failure()
+            ctx.failure(),
+            lockLsnr
         ) {
             @Override protected int compare(BPlusIO io, long pageAddr, int idx, GridH2SearchRow row) {
                 throw new AssertionError();
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2Tree.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2Tree.java
index d41b9b3..cd3619e 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2Tree.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2Tree.java
@@ -156,7 +156,17 @@ public abstract class H2Tree extends BPlusTree<GridH2SearchRow, GridH2Row> {
         @Nullable FailureProcessor failureProcessor,
         IgniteLogger log
     ) throws IgniteCheckedException {
-        super(name, grpId, pageMem, wal, globalRmvId, metaPageId, reuseList, failureProcessor);
+        super(
+            name,
+            grpId,
+            pageMem,
+            wal,
+            globalRmvId,
+            metaPageId,
+            reuseList,
+            failureProcessor,
+            null
+        );
 
         if (!initNew) {
             // Page is ready - read inline size from it.


[ignite] 19/31: GG-19180 [GG-19116] Backport: Fix CacheContinuousQueryAsyncFailoverAtomicSelfTest.testFailoverStartStopBackup (#73)

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch gg-19225
in repository https://gitbox.apache.org/repos/asf/ignite.git

commit 3d758743b1cbc1164d7ef659d8796a40bfbee768
Author: pavlukhin <vo...@gmail.com>
AuthorDate: Fri May 31 15:47:51 2019 +0300

    GG-19180 [GG-19116] Backport: Fix CacheContinuousQueryAsyncFailoverAtomicSelfTest.testFailoverStartStopBackup (#73)
---
 .../CacheContinuousQueryFailoverAbstractSelfTest.java     | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryFailoverAbstractSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryFailoverAbstractSelfTest.java
index cd1ae10..696ae8a 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryFailoverAbstractSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryFailoverAbstractSelfTest.java
@@ -1755,11 +1755,22 @@ public abstract class CacheContinuousQueryFailoverAbstractSelfTest extends GridC
                 if (System.currentTimeMillis() > startFilterTime) {
                     // Stop filter and check events.
                     if (dinQry != null) {
-                        dinQry.close();
+                        // If sync callback is used then we can close a query before checking notifications
+                        // because CQ listeners on a server side have a pending notification upon each
+                        // successfull cache update operations completion.
+                        if (!asyncCallback())
+                            dinQry.close();
 
-                        log.info("Continuous query listener closed. Await events: " + expEvtsNewLsnr.size());
+                        log.info("Await events: " + expEvtsNewLsnr.size());
 
                         checkEvents(expEvtsNewLsnr, dinLsnr, backups == 0);
+
+                        // If async callback is used and we close a query before checking notifications then
+                        // some updates can be missed because a callback submitted in parallel can be executed
+                        // after CQ is closed and no notification will be sent as a result.
+                        // So, we close CQ after the check.
+                        if (asyncCallback())
+                            dinQry.close();
                     }
 
                     dinLsnr = new CacheEventListener2();


[ignite] 11/31: GG-18670 [IGNITE-11749] Implement automatic pages history dump on CorruptedTreeException. Contributors: Anton Kalashnikov Ivan Bessonov

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch gg-19225
in repository https://gitbox.apache.org/repos/asf/ignite.git

commit 4af7b7dcd779ddc9f8308465a234d46bf188bda4
Author: Anton Kalashnikov <ka...@yandex.ru>
AuthorDate: Fri May 31 00:04:37 2019 +0300

    GG-18670 [IGNITE-11749] Implement automatic pages history dump on CorruptedTreeException.
    Contributors:
    Anton Kalashnikov <ka...@yandex.ru>
    Ivan Bessonov <be...@gmail.com>
    
    Signed-off-by: Dmitriy Govorukhin <dm...@gmail.com>
---
 .../apache/ignite/internal/GridKernalContext.java  |   8 +
 .../ignite/internal/GridKernalContextImpl.java     |  12 +
 .../org/apache/ignite/internal/IgniteKernal.java   |   3 +
 .../cache/persistence/CacheDataRowAdapter.java     | 141 ++++++--
 .../cache/persistence/tree/BPlusTree.java          | 143 ++++++--
 .../tree/BPlusTreeRuntimeException.java            |  52 +++
 .../persistence/tree/CorruptedTreeException.java   |  81 ++++-
 .../persistence/wal/FileWriteAheadLogManager.java  |   7 +
 .../cache/persistence/wal/SegmentRouter.java       |  21 ++
 .../wal/reader/FilteredWalIterator.java            | 109 ++++++
 .../wal/reader/IgniteWalIteratorFactory.java       |  47 ++-
 .../wal/reader/StandaloneGridKernalContext.java    |   6 +
 .../cache/persistence/wal/reader/WalFilters.java   |  89 +++++
 .../wal/scanner/PrintRawToFileHandler.java         |  74 ++++
 .../wal/scanner/PrintToFileHandler.java            | 133 +++++++
 .../persistence/wal/scanner/PrintToLogHandler.java |  71 ++++
 .../persistence/wal/scanner/ScannerHandler.java    |  69 ++++
 .../persistence/wal/scanner/ScannerHandlers.java   |  64 ++++
 .../cache/persistence/wal/scanner/WalScanner.java  | 164 +++++++++
 .../processors/diagnostic/DiagnosticProcessor.java | 196 +++++++++++
 .../diagnostic/PageHistoryDiagnoster.java          | 381 +++++++++++++++++++++
 .../processors/failure/FailureProcessor.java       |   6 +
 .../ignite/internal/util/IgniteStopwatch.java      |  33 ++
 .../util/lang/IgniteThrowableConsumer.java         |  10 +-
 ...eConsumer.java => IgniteThrowableSupplier.java} |  26 +-
 .../org/apache/ignite/lang/IgniteBiPredicate.java  |  25 +-
 .../CorruptedTreeFailureHandlingTest.java          | 255 ++++++++++++++
 .../wal/reader/FilteredWalIteratorTest.java        | 214 ++++++++++++
 .../persistence/wal/scanner/WalScannerTest.java    | 337 ++++++++++++++++++
 .../diagnostic/DiagnosticProcessorTest.java        | 269 +++++++++++++++
 .../ignite/testsuites/IgnitePdsTestSuite.java      |   4 +
 .../ignite/testsuites/IgnitePdsTestSuite2.java     |   6 +
 .../ignite/testsuites/IgnitePdsTestSuite4.java     |   2 +
 .../visor/verify/ValidateIndexesClosure.java       |  16 +-
 34 files changed, 2982 insertions(+), 92 deletions(-)

diff --git a/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContext.java b/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContext.java
index c1f5ea4..d95e44f 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContext.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContext.java
@@ -45,6 +45,7 @@ import org.apache.ignite.internal.processors.cluster.GridClusterStateProcessor;
 import org.apache.ignite.internal.processors.continuous.GridContinuousProcessor;
 import org.apache.ignite.internal.processors.datastreamer.DataStreamProcessor;
 import org.apache.ignite.internal.processors.datastructures.DataStructuresProcessor;
+import org.apache.ignite.internal.processors.diagnostic.DiagnosticProcessor;
 import org.apache.ignite.internal.processors.failure.FailureProcessor;
 import org.apache.ignite.internal.processors.hadoop.HadoopHelper;
 import org.apache.ignite.internal.processors.hadoop.HadoopProcessorAdapter;
@@ -453,6 +454,13 @@ public interface GridKernalContext extends Iterable<GridComponent> {
     public LongJVMPauseDetector longJvmPauseDetector();
 
     /**
+     * Gets diagnostic processor.
+     *
+     * @return Diagnostic processor.
+     */
+    public DiagnosticProcessor diagnostic();
+
+    /**
      * Checks whether this node is invalid due to a critical error or not.
      *
      * @return {@code True} if this node is invalid, {@code false} otherwise.
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContextImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContextImpl.java
index 360bef8..8fa16f5 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContextImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContextImpl.java
@@ -49,6 +49,7 @@ import org.apache.ignite.internal.managers.indexing.GridIndexingManager;
 import org.apache.ignite.internal.managers.loadbalancer.GridLoadBalancerManager;
 import org.apache.ignite.internal.processors.cache.mvcc.MvccProcessor;
 import org.apache.ignite.internal.worker.WorkersRegistry;
+import org.apache.ignite.internal.processors.diagnostic.DiagnosticProcessor;
 import org.apache.ignite.internal.processors.affinity.GridAffinityProcessor;
 import org.apache.ignite.internal.processors.authentication.IgniteAuthenticationProcessor;
 import org.apache.ignite.internal.processors.cache.CacheConflictResolutionManager;
@@ -303,6 +304,10 @@ public class GridKernalContextImpl implements GridKernalContext, Externalizable
     @GridToStringExclude
     private IgniteAuthenticationProcessor authProc;
 
+    /** Diagnostic processor. */
+    @GridToStringInclude
+    private DiagnosticProcessor diagnosticProcessor;
+
     /** */
     @GridToStringExclude
     private List<GridComponent> comps = new LinkedList<>();
@@ -645,6 +650,8 @@ public class GridKernalContextImpl implements GridKernalContext, Externalizable
             internalSubscriptionProc = (GridInternalSubscriptionProcessor)comp;
         else if (comp instanceof IgniteAuthenticationProcessor)
             authProc = (IgniteAuthenticationProcessor)comp;
+        else if (comp instanceof DiagnosticProcessor)
+            diagnosticProcessor = (DiagnosticProcessor)comp;
         else if (!(comp instanceof DiscoveryNodeValidationProcessor
             || comp instanceof PlatformPluginProcessor))
             assert (comp instanceof GridPluginComponent) : "Unknown manager class: " + comp.getClass();
@@ -944,6 +951,11 @@ public class GridKernalContextImpl implements GridKernalContext, Externalizable
     }
 
     /** {@inheritDoc} */
+    @Override public DiagnosticProcessor diagnostic() {
+        return diagnosticProcessor;
+    }
+
+    /** {@inheritDoc} */
     @Override public void printMemoryStats() {
         X.println(">>> ");
         X.println(">>> Grid memory stats [igniteInstanceName=" + igniteInstanceName() + ']');
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java b/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
index e68b4bd..c3dbf07 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
@@ -136,6 +136,7 @@ import org.apache.ignite.internal.processors.cluster.IGridClusterStateProcessor;
 import org.apache.ignite.internal.processors.continuous.GridContinuousProcessor;
 import org.apache.ignite.internal.processors.datastreamer.DataStreamProcessor;
 import org.apache.ignite.internal.processors.datastructures.DataStructuresProcessor;
+import org.apache.ignite.internal.processors.diagnostic.DiagnosticProcessor;
 import org.apache.ignite.internal.processors.failure.FailureProcessor;
 import org.apache.ignite.internal.processors.hadoop.Hadoop;
 import org.apache.ignite.internal.processors.hadoop.HadoopProcessorAdapter;
@@ -911,6 +912,8 @@ public class IgniteKernal implements IgniteEx, IgniteMXBean, Externalizable {
                 longJVMPauseDetector
             );
 
+            startProcessor(new DiagnosticProcessor(ctx));
+
             mBeansMgr = new IgniteMBeansManager(this);
 
             cfg.getMarshaller().setContext(ctx.marshallerContext());
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/CacheDataRowAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/CacheDataRowAdapter.java
index 8670a1d..b3e946d 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/CacheDataRowAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/CacheDataRowAdapter.java
@@ -30,10 +30,12 @@ import org.apache.ignite.internal.processors.cache.IncompleteCacheObject;
 import org.apache.ignite.internal.processors.cache.IncompleteObject;
 import org.apache.ignite.internal.processors.cache.KeyCacheObject;
 import org.apache.ignite.internal.processors.cache.mvcc.txlog.TxState;
+import org.apache.ignite.internal.processors.cache.persistence.tree.BPlusTreeRuntimeException;
 import org.apache.ignite.internal.processors.cache.persistence.tree.io.CacheVersionIO;
 import org.apache.ignite.internal.processors.cache.persistence.tree.io.DataPageIO;
 import org.apache.ignite.internal.processors.cache.persistence.tree.io.DataPagePayload;
 import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
+import org.apache.ignite.internal.util.GridLongList;
 import org.apache.ignite.internal.util.tostring.GridToStringExclude;
 import org.apache.ignite.internal.util.tostring.GridToStringInclude;
 import org.apache.ignite.internal.util.typedef.internal.S;
@@ -142,62 +144,79 @@ public class CacheDataRowAdapter implements CacheDataRow {
 
             int grpId = grp != null ? grp.groupId() : 0;
 
-            final long page = pageMem.acquirePage(grpId, pageId);
-
             try {
-                long pageAddr = pageMem.readLock(grpId, pageId, page); // Non-empty data page must not be recycled.
-
-                assert pageAddr != 0L : nextLink;
+                final long page = pageMem.acquirePage(grpId, pageId);
 
                 try {
-                    DataPageIO io = DataPageIO.VERSIONS.forPage(pageAddr);
+                    long pageAddr = pageMem.readLock(grpId, pageId, page); // Non-empty data page must not be recycled.
 
-                    DataPagePayload data = io.readPayload(pageAddr,
-                        itemId(nextLink),
-                        pageMem.realPageSize(grpId));
+                    assert pageAddr != 0L : nextLink;
 
-                    nextLink = data.nextLink();
+                    try {
+                        DataPageIO io = DataPageIO.VERSIONS.forPage(pageAddr);
 
-                    int hdrLen = 0;
+                        DataPagePayload data = io.readPayload(pageAddr,
+                            itemId(nextLink),
+                            pageMem.realPageSize(grpId));
 
-                    if (first) {
-                        if (nextLink == 0) {
-                            // Fast path for a single page row.
-                            readFullRow(sharedCtx, coctx, pageAddr + data.offset(), rowData, readCacheId);
+                        nextLink = data.nextLink();
 
-                            return;
-                        }
+                        int hdrLen = 0;
 
-                        first = false;
+                        if (first) {
+                            if (nextLink == 0) {
+                                // Fast path for a single page row.
+                                readFullRow(sharedCtx, coctx, pageAddr + data.offset(), rowData, readCacheId);
 
-                        // Assume that row header is always located entirely on the very first page.
-                        hdrLen = readHeader(sharedCtx, pageAddr, data.offset(), rowData);
+                                return;
+                            }
 
-                        if (rowData == LINK_WITH_HEADER)
-                            return;
-                    }
+                            first = false;
+
+                            // Assume that row header is always located entirely on the very first page.
+                            hdrLen = readHeader(sharedCtx, pageAddr, data.offset(), rowData);
+
+                            if (rowData == LINK_WITH_HEADER)
+                                return;
+                        }
 
-                    ByteBuffer buf = pageMem.pageBuffer(pageAddr);
+                        ByteBuffer buf = pageMem.pageBuffer(pageAddr);
 
-                    int off = data.offset() + hdrLen;
-                    int payloadSize = data.payloadSize() - hdrLen;
+                        int off = data.offset() + hdrLen;
+                        int payloadSize = data.payloadSize() - hdrLen;
 
-                    buf.position(off);
-                    buf.limit(off + payloadSize);
+                        buf.position(off);
+                        buf.limit(off + payloadSize);
 
-                    boolean keyOnly = rowData == RowData.KEY_ONLY;
+                        boolean keyOnly = rowData == RowData.KEY_ONLY;
 
-                    incomplete = readFragment(sharedCtx, coctx, buf, keyOnly, readCacheId, incomplete);
+                        incomplete = readFragment(sharedCtx, coctx, buf, keyOnly, readCacheId, incomplete);
 
-                    if (keyOnly && key != null)
-                        return;
+                        if (keyOnly && key != null)
+                            return;
+                    }
+                    finally {
+                        pageMem.readUnlock(grpId, pageId, page);
+                    }
                 }
                 finally {
-                    pageMem.readUnlock(grpId, pageId, page);
+                    pageMem.releasePage(grpId, pageId, page);
                 }
             }
-            finally {
-                pageMem.releasePage(grpId, pageId, page);
+            catch (RuntimeException | AssertionError e) {
+                // Collect all pages from first link to pageId.
+                long[] pageIds;
+
+                try {
+                    pageIds = relatedPageIds(grpId, link, pageId, pageMem);
+
+                }
+                catch (IgniteCheckedException e0) {
+                    // Ignore exception if failed to resolve related page ids.
+                    pageIds = new long[] {pageId};
+                }
+
+                throw new BPlusTreeRuntimeException(e, grpId, pageIds);
             }
         }
         while(nextLink != 0);
@@ -542,6 +561,58 @@ public class CacheDataRowAdapter implements CacheDataRow {
     }
 
     /**
+     *
+     * @param grpId Group id.
+     * @param link Link.
+     * @param pageId PageId.
+     * @param pageMem Page memory.
+     * @return Array of page ids from link to pageId.
+     * @throws IgniteCheckedException If failed.
+     */
+    private long[] relatedPageIds(
+        int grpId,
+        long link,
+        long pageId,
+        PageMemory pageMem
+    ) throws IgniteCheckedException {
+        GridLongList pageIds = new GridLongList();
+
+        long nextLink = link;
+        long nextLinkPageId = pageId(nextLink);
+
+        while (nextLinkPageId != pageId) {
+            pageIds.add(nextLinkPageId);
+
+            long page = pageMem.acquirePage(grpId, nextLinkPageId);
+
+            try {
+                long pageAddr = pageMem.readLock(grpId, nextLinkPageId, page);
+
+                try {
+                    DataPageIO io = DataPageIO.VERSIONS.forPage(pageAddr);
+
+                    int itemId = itemId(nextLink);
+
+                    DataPagePayload data = io.readPayload(pageAddr, itemId, pageMem.realPageSize(grpId));
+
+                    nextLink = data.nextLink();
+                    nextLinkPageId = pageId(nextLink);
+                }
+                finally {
+                    pageMem.readUnlock(grpId, nextLinkPageId, page);
+                }
+            }
+            finally {
+                pageMem.releasePage(grpId, nextLinkPageId, page);
+            }
+        }
+
+        pageIds.add(pageId);
+
+        return pageIds.array();
+    }
+
+    /**
      * @return {@code True} if entry is ready.
      */
     public boolean isReady() {
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/BPlusTree.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/BPlusTree.java
index d5d93b7..03524e8 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/BPlusTree.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/BPlusTree.java
@@ -23,6 +23,7 @@ import java.util.Comparator;
 import java.util.List;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.Supplier;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.IgniteException;
 import org.apache.ignite.IgniteSystemProperties;
@@ -947,20 +948,25 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements
             releasePage(metaPageId, metaPage);
         }
 
-        long firstPage = acquirePage(firstPageId);
-
         try {
-            long pageAddr = readLock(firstPageId, firstPage); // We always merge pages backwards, the first page is never removed.
+            long firstPage = acquirePage(firstPageId);
 
             try {
-                cursor.init(pageAddr, io(pageAddr), -1);
+                long pageAddr = readLock(firstPageId, firstPage); // We always merge pages backwards, the first page is never removed.
+
+                try {
+                    cursor.init(pageAddr, io(pageAddr), -1);
+                }
+                finally {
+                    readUnlock(firstPageId, firstPage, pageAddr);
+                }
             }
             finally {
-                readUnlock(firstPageId, firstPage, pageAddr);
+                releasePage(firstPageId, firstPage);
             }
         }
-        finally {
-            releasePage(firstPageId, firstPage);
+        catch (RuntimeException | AssertionError e) {
+            throw new BPlusTreeRuntimeException(e, grpId, metaPageId, firstPageId);
         }
 
         return cursor;
@@ -995,12 +1001,12 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements
     public final GridCursor<T> find(L lower, L upper, TreeRowClosure<L, T> c, Object x) throws IgniteCheckedException {
         checkDestroyed();
 
+        ForwardCursor cursor = new ForwardCursor(lower, upper, c, x);
+
         try {
             if (lower == null)
                 return findLowerUnbounded(upper, c, x);
 
-            ForwardCursor cursor = new ForwardCursor(lower, upper, c, x);
-
             cursor.find();
 
             return cursor;
@@ -1009,7 +1015,15 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements
             throw new IgniteCheckedException("Runtime failure on bounds: [lower=" + lower + ", upper=" + upper + "]", e);
         }
         catch (RuntimeException | AssertionError e) {
-            throw new CorruptedTreeException("Runtime failure on bounds: [lower=" + lower + ", upper=" + upper + "]", e);
+            long[] pageIds = pages(
+                lower == null || cursor == null || cursor.getCursor == null,
+                () -> new long[]{cursor.getCursor.pageId}
+            );
+
+            throw corruptedTreeException(
+                formatMsg("Runtime failure on bounds: [lower=%s, upper=%s]", lower, upper),
+                e, grpId, pageIds
+            );
         }
         finally {
             checkDestroyed();
@@ -1025,19 +1039,19 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements
     public void iterate(L lower, L upper, TreeRowClosure<L, T> c) throws IgniteCheckedException {
         checkDestroyed();
 
-        try {
-            ClosureCursor cursor = new ClosureCursor(lower, upper, c);
+        ClosureCursor cursor = new ClosureCursor(lower, upper, c);
 
+        try {
             cursor.iterate();
         }
         catch (IgniteCheckedException e) {
             throw new IgniteCheckedException("Runtime failure on bounds: [lower=" + lower + ", upper=" + upper + "]", e);
         }
-        catch (RuntimeException e) {
-            throw new IgniteException("Runtime failure on bounds: [lower=" + lower + ", upper=" + upper + "]", e);
-        }
-        catch (AssertionError e) {
-            throw new AssertionError("Assertion error on bounds: [lower=" + lower + ", upper=" + upper + "]", e);
+        catch (RuntimeException | AssertionError e) {
+            throw corruptedTreeException(
+                "Runtime failure on bounds: [lower=" + lower + ", upper=" + upper + "]",
+                e, grpId, pages(cursor.getCursor != null, () -> new long[]{cursor.getCursor.pageId})
+            );
         }
         finally {
             checkDestroyed();
@@ -1084,9 +1098,11 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements
     public T findFirst(TreeRowClosure<L, T> filter) throws IgniteCheckedException {
         checkDestroyed();
 
+        long curPageId = 0L;
+        long nextPageId = 0L;
+
         try {
             for (;;) {
-                long curPageId;
 
                 long metaPage = acquirePage(metaPageId);
 
@@ -1117,7 +1133,7 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements
                                     return getRow(io, curPageAddr, i);
                             }
 
-                            long nextPageId = io.getForward(curPageAddr);
+                            nextPageId = io.getForward(curPageAddr);
 
                             if (nextPageId == 0)
                                 return null;
@@ -1174,7 +1190,7 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements
             throw new IgniteCheckedException("Runtime failure on first row lookup", e);
         }
         catch (RuntimeException | AssertionError e) {
-            throw new CorruptedTreeException("Runtime failure on first row lookup", e);
+            throw corruptedTreeException("Runtime failure on first row lookup", e, grpId, curPageId, nextPageId);
         }
         finally {
             checkDestroyed();
@@ -1196,20 +1212,33 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements
     public T findLast(final TreeRowClosure<L, T> c) throws IgniteCheckedException {
         checkDestroyed();
 
+        Get g = null;
+
         try {
             if (c == null) {
-                GetOne g = new GetOne(null, null, null, true);
+                g = new GetOne(null, null, null, true);
+
                 doFind(g);
 
                 return (T)g.row;
-            } else
-                return new GetLast(c).find();
+            }
+            else {
+                GetLast gLast = new GetLast(c);
+
+                g = gLast;
+
+                return gLast.find();
+            }
         }
         catch (IgniteCheckedException e) {
             throw new IgniteCheckedException("Runtime failure on last row lookup", e);
         }
         catch (RuntimeException | AssertionError e) {
-            throw new IgniteException("Runtime failure on last row lookup", e);
+            Get g0 = g;
+
+            long[] pageIds = pages(g == null, () -> new long[]{g0.pageId});
+
+            throw corruptedTreeException("Runtime failure on last row lookup", e, grpId, pageIds);
         }
         finally {
             checkDestroyed();
@@ -1236,9 +1265,9 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements
     public final <R> R findOne(L row, TreeRowClosure<L, T> c, Object x) throws IgniteCheckedException {
         checkDestroyed();
 
-        try {
-            GetOne g = new GetOne(row, c, x, false);
+        GetOne g = new GetOne(row, c, x, false);
 
+        try {
             doFind(g);
 
             return (R)g.row;
@@ -1247,7 +1276,7 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements
             throw new IgniteCheckedException("Runtime failure on lookup row: " + row, e);
         }
         catch (RuntimeException | AssertionError e) {
-            throw new CorruptedTreeException("Runtime failure on lookup row: " + row, e);
+            throw corruptedTreeException(formatMsg("Runtime failure on lookup row: %s", row), e, grpId, g.pageId);
         }
         finally {
             checkDestroyed();
@@ -1808,7 +1837,7 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements
             throw new IgniteCheckedException("Runtime failure on search row: " + row, e);
         }
         catch (RuntimeException | AssertionError e) {
-            throw new CorruptedTreeException("Runtime failure on search row: " + row, e);
+            throw corruptedTreeException(formatMsg("Runtime failure on search row: %s", row), e, grpId, x.pageId);
         }
         finally {
             x.releaseAll();
@@ -1965,7 +1994,7 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements
             throw new IgniteCheckedException("Runtime failure on search row: " + row, e);
         }
         catch (RuntimeException | AssertionError e) {
-            throw new CorruptedTreeException("Runtime failure on search row: " + row, e);
+            throw corruptedTreeException(formatMsg("Runtime failure on search row: %s", row), e, grpId, r.pageId);
         }
         finally {
             r.releaseAll();
@@ -2317,7 +2346,7 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements
             throw new IgniteCheckedException("Runtime failure on row: " + row, e);
         }
         catch (RuntimeException | AssertionError e) {
-            throw new CorruptedTreeException("Runtime failure on row: " + row, e);
+            throw corruptedTreeException(formatMsg("Runtime failure on row: %s", row), e, grpId, p.pageId);
         }
         finally {
             checkDestroyed();
@@ -5182,6 +5211,9 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements
         /** */
         final L upperBound;
 
+        /** Cached value for retrieving diagnosting info in case of failure. */
+        public GetCursor getCursor;
+
         /**
          * @param lowerBound Lower bound.
          * @param upperBound Upper bound.
@@ -5321,7 +5353,7 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements
         final void find() throws IgniteCheckedException {
             assert lowerBound != null;
 
-            doFind(new GetCursor(lowerBound, lowerShift, this));
+            doFind(getCursor = new GetCursor(lowerBound, lowerShift, this));
         }
 
         /**
@@ -5373,6 +5405,9 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements
                         readUnlock(pageId, page, pageAddr);
                     }
                 }
+                catch (RuntimeException | AssertionError e) {
+                    throw corruptedTreeException("Runtime failure on cursor iteration", e, grpId, pageId);
+                }
                 finally {
                     releasePage(pageId, page);
                 }
@@ -5789,4 +5824,50 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements
     protected int getLockRetries() {
         return LOCK_RETRIES;
     }
+
+    /**
+     * PageIds converter with empty check.
+     *
+     * @param empty Flag for empty array result.
+     * @param pages Pages supplier.
+     * @return Array of page ids.
+     */
+    private long[] pages(boolean empty, Supplier<long[]> pages) {
+        return empty ? GridLongList.EMPTY_ARRAY : pages.get();
+    }
+
+    /**
+     * Construct the exception and invoke failure processor.
+     *
+     * @param msg Message.
+     * @param cause Cause.
+     * @param grpId Group id.
+     * @param pageIds Pages ids.
+     * @return New CorruptedTreeException instance.
+     */
+    private CorruptedTreeException corruptedTreeException(String msg, Throwable cause, int grpId, long... pageIds) {
+        CorruptedTreeException e = new CorruptedTreeException(msg, cause, grpId, pageIds);
+
+        if (failureProcessor != null)
+            failureProcessor.process(new FailureContext(FailureType.CRITICAL_ERROR, e));
+
+        return e;
+    }
+
+    /**
+     * Creates a formatted message even if "toString" of optioanl parameters failed.
+     *
+     * @param msg Detailed error message.
+     * @param rows Optional parameters.
+     * @return New instance of {@link CorruptedTreeException}.
+     */
+    private String formatMsg(String msg, Object... rows) {
+        try {
+            return String.format(msg, rows);
+        }
+        catch (Throwable ignored) {
+            // Failed to create string representation of optional parameters.
+            return msg + " <failed to create rows string representation>";
+        }
+    }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/BPlusTreeRuntimeException.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/BPlusTreeRuntimeException.java
new file mode 100644
index 0000000..073e629
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/BPlusTreeRuntimeException.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.persistence.tree;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.ignite.internal.util.typedef.T2;
+
+/**
+ * This exception indicates that there's something wrong with B+Tree data integrity. Additional info about corrupted
+ * pages is present in fields.
+ */
+public class BPlusTreeRuntimeException extends RuntimeException {
+    /** */
+    private static final long serialVersionUID = 0L;
+    /** Group id common for all potentially corrupted pages. */
+    private final int grpId;
+    /** Ids of potentially corrupted pages. */
+    private final long[] pageIds;
+
+    /** */
+    public BPlusTreeRuntimeException(Throwable cause, int grpId, long... pageIds) {
+        super(cause);
+
+        this.grpId = grpId;
+        this.pageIds = pageIds;
+    }
+
+    /** Pairs of (groupId, pageId). */
+    public List<T2<Integer, Long>> pages() {
+        List<T2<Integer, Long>> res = new ArrayList<>(pageIds.length);
+
+        for (long pageId : pageIds)
+            res.add(new T2<>(grpId, pageId));
+
+        return res;
+    }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/CorruptedTreeException.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/CorruptedTreeException.java
index 12a9f49..9c97a29 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/CorruptedTreeException.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/CorruptedTreeException.java
@@ -16,10 +16,21 @@
 
 package org.apache.ignite.internal.processors.cache.persistence.tree;
 
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.stream.Collectors;
 import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.internal.pagemem.PageIdAllocator;
+import org.apache.ignite.internal.pagemem.PageIdUtils;
 import org.apache.ignite.internal.processors.cache.persistence.CorruptedPersistenceException;
+import org.apache.ignite.internal.util.typedef.T2;
+import org.apache.ignite.internal.util.typedef.X;
+import org.apache.ignite.internal.util.typedef.internal.S;
 import org.jetbrains.annotations.Nullable;
 
+import static java.util.Arrays.asList;
+
 /**
  * Exception to distinguish {@link BPlusTree} tree broken invariants.
  */
@@ -27,11 +38,77 @@ public class CorruptedTreeException extends IgniteCheckedException implements Co
     /** */
     private static final long serialVersionUID = 0L;
 
+    /** */
+    private final T2<Integer, Long>[] pages;
+
+    /**
+     * @param msg Message.
+     * @param cause Cause.
+     * @param grpId Group id of potentially corrupted pages.
+     * @param pageIds Potentially corrupted pages.
+     */
+    public CorruptedTreeException(String msg, @Nullable Throwable cause, int grpId, long... pageIds) {
+        this(msg, cause, toPagesArray(grpId, pageIds));
+    }
+
     /**
      * @param msg Message.
      * @param cause Cause.
+     * @param pages (groupId, pageId) pairs for pages that might be corrupted.
+     */
+    public CorruptedTreeException(String msg, @Nullable Throwable cause, T2<Integer, Long>... pages) {
+        super(getMsg(msg, pages), cause);
+
+        this.pages = expandPagesArray(pages, cause);
+    }
+
+    /** */
+    private static T2<Integer, Long>[] toPagesArray(int grpId, long[] pageIds) {
+        T2<Integer, Long>[] res = (T2<Integer, Long>[])new T2[pageIds.length];
+
+        for (int i = 0; i < pageIds.length; i++)
+            res[i] = new T2<>(grpId, pageIds[i]);
+
+        return res;
+    }
+
+    /** */
+    private static T2<Integer, Long>[] expandPagesArray(T2<Integer, Long>[] pages, Throwable cause) {
+        Set<T2<Integer, Long>> res = new HashSet<>(asList(pages));
+
+        BPlusTreeRuntimeException treeRuntimeException = X.cause(cause, BPlusTreeRuntimeException.class);
+
+        // Add root exception pages ids if we have.
+        if (treeRuntimeException != null)
+            res.addAll(treeRuntimeException.pages());
+
+        Set<T2<Integer, Long>> partMetaPages = res.stream().map(page -> {
+            int grpId = page.get1();
+            int partId = PageIdUtils.partId(page.get2());
+
+            final long partMetaPageId = PageIdUtils.pageId(partId, PageIdAllocator.FLAG_DATA, 0);
+
+            return new T2<>(grpId, partMetaPageId);
+        }).collect(Collectors.toSet());
+
+        // Add meta pages for all (group,partition) pairs.
+        res.addAll(partMetaPages);
+
+        return (T2<Integer, Long>[])res.toArray(new T2[0]);
+    }
+
+    /** */
+    private static String getMsg(String msg, T2<Integer, Long>... pages) {
+        return S.toString("B+Tree is corrupted",
+            "pages(groupId, pageId)", Arrays.toString(pages), false,
+            "msg", msg, false
+        );
+    }
+
+    /**
+     * @return (groupId, pageId) pairs for pages that might be corrupted.
      */
-    public CorruptedTreeException(String msg, @Nullable Throwable cause) {
-        super(msg, cause);
+    public T2<Integer, Long>[] pages() {
+        return pages;
     }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/FileWriteAheadLogManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/FileWriteAheadLogManager.java
index 23c6124..ab6dc2f 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/FileWriteAheadLogManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/FileWriteAheadLogManager.java
@@ -482,6 +482,13 @@ public class FileWriteAheadLogManager extends GridCacheSharedManagerAdapter impl
     }
 
     /**
+     * @return Info about of WAL paths.
+     */
+    public SegmentRouter getSegmentRouter() {
+        return segmentRouter;
+    }
+
+    /**
      *
      */
     private void startArchiverAndCompressor() {
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/SegmentRouter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/SegmentRouter.java
index 322705f..f62cca6 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/SegmentRouter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/SegmentRouter.java
@@ -88,6 +88,27 @@ public class SegmentRouter {
     }
 
     /**
+     * @return {@code true} If archive folder exists.
+     */
+    public boolean hasArchive() {
+        return !walWorkDir.getAbsolutePath().equals(walArchiveDir.getAbsolutePath());
+    }
+
+    /**
+     * @return WAL working directory.
+     */
+    public File getWalWorkDir() {
+        return walWorkDir;
+    }
+
+    /**
+     * @return WAL archive directory.
+     */
+    public File getWalArchiveDir() {
+        return walArchiveDir;
+    }
+
+    /**
      * Returns {@code true} if archiver is enabled.
      */
     private boolean isArchiverEnabled() {
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/FilteredWalIterator.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/FilteredWalIterator.java
new file mode 100644
index 0000000..1cd2999
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/FilteredWalIterator.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.persistence.wal.reader;
+
+import java.util.NoSuchElementException;
+import java.util.Optional;
+import java.util.function.Predicate;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.internal.pagemem.wal.WALIterator;
+import org.apache.ignite.internal.pagemem.wal.WALPointer;
+import org.apache.ignite.internal.pagemem.wal.record.WALRecord;
+import org.apache.ignite.internal.util.lang.GridIteratorAdapter;
+import org.apache.ignite.lang.IgniteBiTuple;
+
+/**
+ * Decorator of {@link WALIterator} which allow filter record by {@link WALPointer} and {@link WALRecord}.
+ */
+public class FilteredWalIterator extends GridIteratorAdapter<IgniteBiTuple<WALPointer, WALRecord>>
+    implements WALIterator {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /** Source WAL iterator which provide data for filtering. */
+    private final WALIterator delegateWalIter;
+
+    /** Filter for filtering iterated data. */
+    private final Predicate<IgniteBiTuple<WALPointer, WALRecord>> filter;
+
+    /** Next record in iterator for supporting iterator pattern. */
+    private IgniteBiTuple<WALPointer, WALRecord> next;
+
+    /**
+     * @param walIterator Source WAL iterator which provide data for filtering.
+     * @param filter Filter for filtering iterated data.
+     */
+    public FilteredWalIterator(WALIterator walIterator,
+        Predicate<IgniteBiTuple<WALPointer, WALRecord>> filter) throws IgniteCheckedException {
+        this.filter = filter == null ? (r) -> true : filter;
+        this.delegateWalIter = walIterator;
+
+        // Initiate iterator by first record.
+        next = nextFilteredRecord();
+    }
+
+    /** {@inheritDoc} **/
+    @Override public Optional<WALPointer> lastRead() {
+        return Optional.ofNullable(next == null ? null : next.get1());
+    }
+
+    /**
+     * @return Next filtered record.
+     */
+    private IgniteBiTuple<WALPointer, WALRecord> nextFilteredRecord() {
+        while (delegateWalIter.hasNext()) {
+            IgniteBiTuple<WALPointer, WALRecord> next = delegateWalIter.next();
+
+            if (filter.test(next))
+                return next;
+        }
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteBiTuple<WALPointer, WALRecord> nextX() throws IgniteCheckedException {
+        if (!hasNextX())
+            throw new NoSuchElementException();
+
+        IgniteBiTuple<WALPointer, WALRecord> cur = next;
+
+        next = nextFilteredRecord();
+
+        return cur;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean hasNextX() throws IgniteCheckedException {
+        return next != null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void removeX() throws IgniteCheckedException {
+        throw new UnsupportedOperationException();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void close() throws IgniteCheckedException {
+        delegateWalIter.close();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isClosed() {
+        return delegateWalIter.isClosed();
+    }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/IgniteWalIteratorFactory.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/IgniteWalIteratorFactory.java
index e3f1499..6dd565e 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/IgniteWalIteratorFactory.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/IgniteWalIteratorFactory.java
@@ -172,7 +172,8 @@ public class IgniteWalIteratorFactory {
     ) throws IgniteCheckedException, IllegalArgumentException {
         iteratorParametersBuilder.validate();
 
-        return new StandaloneWalRecordsIterator(log,
+        return new StandaloneWalRecordsIterator(
+            iteratorParametersBuilder.log == null ? log : iteratorParametersBuilder.log,
             iteratorParametersBuilder.sharedCtx == null ? prepareSharedCtx(iteratorParametersBuilder) :
                 iteratorParametersBuilder.sharedCtx,
             iteratorParametersBuilder.ioFactory,
@@ -223,9 +224,18 @@ public class IgniteWalIteratorFactory {
     ) throws IllegalArgumentException {
         iteratorParametersBuilder.validate();
 
-        List<T2<Long, Long>> gaps = new ArrayList<>();
+        return hasGaps(resolveWalFiles(iteratorParametersBuilder));
+    }
 
-        List<FileDescriptor> descriptors = resolveWalFiles(iteratorParametersBuilder);
+    /**
+     * @param descriptors File descriptors.
+     * @return List of tuples, low and high index segments with gap.
+     */
+    public List<T2<Long, Long>> hasGaps(
+         @NotNull  List<FileDescriptor> descriptors
+    ) throws IllegalArgumentException {
+
+        List<T2<Long, Long>> gaps = new ArrayList<>();
 
         Iterator<FileDescriptor> it = descriptors.iterator();
 
@@ -376,6 +386,8 @@ public class IgniteWalIteratorFactory {
      * Wal iterator parameter builder.
      */
     public static class IteratorParametersBuilder {
+        /** Logger. */
+        private IgniteLogger log;
         /** */
         public static final FileWALPointer DFLT_LOW_BOUND = new FileWALPointer(Long.MIN_VALUE, 0, 0);
 
@@ -431,6 +443,25 @@ public class IgniteWalIteratorFactory {
         private boolean strictBoundsCheck;
 
         /**
+         * Factory method for {@link IgniteWalIteratorFactory.IteratorParametersBuilder}.
+         *
+         * @return Instance of {@link IgniteWalIteratorFactory.IteratorParametersBuilder}.
+         */
+        public static IteratorParametersBuilder withIteratorParameters() {
+            return new IteratorParametersBuilder();
+        }
+
+        /**
+         * @param log Logger.
+         * @return IteratorParametersBuilder Self reference.
+         */
+        public IteratorParametersBuilder log(IgniteLogger log){
+            this.log = log;
+
+            return this;
+        }
+
+        /**
          * @param filesOrDirs Paths to files or directories.
          * @return IteratorParametersBuilder Self reference.
          */
@@ -537,6 +568,16 @@ public class IgniteWalIteratorFactory {
         }
 
         /**
+         * @param filter Record filter for skip records during iteration.
+         * @return IteratorParametersBuilder Self reference.
+         */
+        public IteratorParametersBuilder addFilter(IgniteBiPredicate<RecordType, WALPointer> filter) {
+            this.filter = this.filter == null ? filter : this.filter.and(filter);
+
+            return this;
+        }
+
+        /**
          * @param lowBound WAL pointer to start from.
          * @return IteratorParametersBuilder Self reference.
          */
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/StandaloneGridKernalContext.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/StandaloneGridKernalContext.java
index 4efa337..c2ec57a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/StandaloneGridKernalContext.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/StandaloneGridKernalContext.java
@@ -60,6 +60,7 @@ import org.apache.ignite.internal.processors.cluster.GridClusterStateProcessor;
 import org.apache.ignite.internal.processors.continuous.GridContinuousProcessor;
 import org.apache.ignite.internal.processors.datastreamer.DataStreamProcessor;
 import org.apache.ignite.internal.processors.datastructures.DataStructuresProcessor;
+import org.apache.ignite.internal.processors.diagnostic.DiagnosticProcessor;
 import org.apache.ignite.internal.processors.failure.FailureProcessor;
 import org.apache.ignite.internal.processors.hadoop.HadoopHelper;
 import org.apache.ignite.internal.processors.hadoop.HadoopProcessorAdapter;
@@ -676,4 +677,9 @@ public class StandaloneGridKernalContext implements GridKernalContext {
     @Override public LongJVMPauseDetector longJvmPauseDetector() {
         return new LongJVMPauseDetector(log);
     }
+
+    /** {@inheritDoc} */
+    @Override public DiagnosticProcessor diagnostic() {
+        return null;
+    }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/WalFilters.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/WalFilters.java
new file mode 100644
index 0000000..3df54e7
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/WalFilters.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.persistence.wal.reader;
+
+import java.util.Set;
+import java.util.function.Predicate;
+import org.apache.ignite.internal.pagemem.wal.WALPointer;
+import org.apache.ignite.internal.pagemem.wal.record.CheckpointRecord;
+import org.apache.ignite.internal.pagemem.wal.record.PageSnapshot;
+import org.apache.ignite.internal.pagemem.wal.record.WALRecord;
+import org.apache.ignite.internal.pagemem.wal.record.delta.PageDeltaRecord;
+import org.apache.ignite.internal.pagemem.wal.record.delta.PartitionMetaStateRecord;
+import org.apache.ignite.internal.util.typedef.T2;
+import org.apache.ignite.lang.IgniteBiTuple;
+
+/**
+ * Class for holding only very basic WAL filters for using in {@link FilteredWalIterator}. *
+ */
+public class WalFilters {
+    /**
+     * Filtering all checkpoint records.
+     *
+     * @return Predicate for filtering checkpoint records.
+     */
+    public static Predicate<IgniteBiTuple<WALPointer, WALRecord>> checkpoint() {
+        return record -> record.get2() instanceof CheckpointRecord;
+    }
+
+    /**
+     * Filtering all records whose pageId is contained in pageOwnerIds.
+     *
+     * @param pageOwnerIds Page id for filtering.
+     * @return Predicate for filtering record from pageOwnerIds.
+     */
+    public static Predicate<IgniteBiTuple<WALPointer, WALRecord>> pageOwner(Set<T2<Integer, Long>> pageOwnerIds) {
+        return record -> {
+            WALRecord walRecord = record.get2();
+
+            if (walRecord instanceof PageDeltaRecord) {
+                PageDeltaRecord rec0 = (PageDeltaRecord)walRecord;
+
+                return pageOwnerIds.contains(new T2<>(rec0.groupId(), rec0.pageId()));
+            }
+            else if (walRecord instanceof PageSnapshot) {
+                PageSnapshot rec0 = (PageSnapshot)walRecord;
+
+                return pageOwnerIds.contains(new T2<>(rec0.groupId(), rec0.fullPageId().pageId()));
+            }
+
+            return false;
+        };
+    }
+
+    /**
+     * Filtering all records whose partitionId is contained in partsMetaupdate.
+     *
+     * @param partsMetaupdate Partition id for filtering.
+     * @return Predicate for filtering record from pageOwnerIds.
+     */
+    public static Predicate<IgniteBiTuple<WALPointer, WALRecord>> partitionMetaStateUpdate(
+        Set<T2<Integer, Integer>> partsMetaupdate
+    ) {
+        return record -> {
+            WALRecord walRecord = record.get2();
+
+            if (walRecord instanceof PartitionMetaStateRecord) {
+                PartitionMetaStateRecord rec0 = (PartitionMetaStateRecord)walRecord;
+
+                return partsMetaupdate.contains(new T2<>(rec0.groupId(), rec0.partitionId()));
+            }
+
+            return false;
+        };
+    }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/scanner/PrintRawToFileHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/scanner/PrintRawToFileHandler.java
new file mode 100644
index 0000000..7e968f1
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/scanner/PrintRawToFileHandler.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.persistence.wal.scanner;
+
+import java.io.File;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.internal.pagemem.wal.WALPointer;
+import org.apache.ignite.internal.pagemem.wal.record.WALRecord;
+import org.apache.ignite.internal.processors.cache.persistence.wal.FileWriteAheadLogManager;
+import org.apache.ignite.internal.processors.cache.persistence.wal.serializer.RecordSerializer;
+import org.apache.ignite.internal.processors.cache.persistence.wal.serializer.RecordV1Serializer;
+import org.apache.ignite.lang.IgniteBiTuple;
+
+/**
+ * Handler to print raw pages data into file for further diagnostic.
+ */
+public class PrintRawToFileHandler extends PrintToFileHandler {
+    /** */
+    private final RecordSerializer serializer;
+
+    /**
+     * @param file Output file.
+     * @param serializer Serializer for WAL records.
+     */
+    public PrintRawToFileHandler(File file, RecordSerializer serializer) {
+        super(file, null);
+
+        this.serializer = serializer;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected byte[] getBytes(IgniteBiTuple<WALPointer, WALRecord> record) {
+        try {
+            WALRecord walRec = record.get2();
+
+            ByteBuffer buf = ByteBuffer.allocate(serializer.size(walRec));
+
+            serializer.writeRecord(walRec, buf);
+
+            return buf.array();
+        }
+        catch (IgniteCheckedException e) {
+            throw new IgniteException(e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override protected byte[] getHeader() {
+        ByteBuffer buf = ByteBuffer.allocate(RecordV1Serializer.HEADER_RECORD_SIZE);
+
+        buf.order(ByteOrder.nativeOrder());
+
+        FileWriteAheadLogManager.prepareSerializerVersionBuffer(0L, serializer.version(), false, buf);
+
+        return buf.array();
+    }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/scanner/PrintToFileHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/scanner/PrintToFileHandler.java
new file mode 100644
index 0000000..4693700
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/scanner/PrintToFileHandler.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.persistence.wal.scanner;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.StandardOpenOption;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.configuration.DataStorageConfiguration;
+import org.apache.ignite.internal.pagemem.wal.WALPointer;
+import org.apache.ignite.internal.pagemem.wal.record.WALRecord;
+import org.apache.ignite.internal.processors.cache.persistence.file.FileIO;
+import org.apache.ignite.internal.processors.cache.persistence.file.FileIOFactory;
+import org.apache.ignite.lang.IgniteBiTuple;
+import org.jetbrains.annotations.Nullable;
+
+import static org.apache.ignite.internal.processors.cache.persistence.wal.scanner.ScannerHandlers.DEFAULT_WAL_RECORD_PREFIX;
+
+/**
+ * Handler which print record to file.
+ *
+ * This is not thread safe. Can be used only one time.
+ */
+class PrintToFileHandler implements ScannerHandler {
+    /** */
+    private final FileIOFactory ioFactory;
+
+    /** Target file. */
+    private final File file;
+
+    /** Open file to write. */
+    private FileIO fileToWrite;
+
+    /**
+     * @param file File to write.
+     * @param ioFactory File IO factory.
+     */
+    public PrintToFileHandler(File file, FileIOFactory ioFactory) {
+        this.file = file;
+        this.ioFactory = ioFactory != null ? ioFactory : new DataStorageConfiguration().getFileIOFactory();
+    }
+
+    /** {@inheritDoc} */
+    @Override public final void handle(IgniteBiTuple<WALPointer, WALRecord> record) {
+        initIfRequired();
+
+        writeFully(getBytes(record));
+    }
+
+    /**
+     * @param record WAL record with its pointer.
+     * @return Bytes repersentation of data to be written in dump file.
+     */
+    protected byte[] getBytes(IgniteBiTuple<WALPointer, WALRecord> record) {
+        return (DEFAULT_WAL_RECORD_PREFIX + record.get2() + "\n").getBytes(StandardCharsets.UTF_8);
+    }
+
+    /**
+     * @return Optional header for the diagnostic file. {@code null} if there should be no header.
+     */
+    @Nullable protected byte[] getHeader() {
+        return null;
+    }
+
+    /**
+     * Initialize fileToWrite if it required.
+     */
+    private void initIfRequired() {
+        if (fileToWrite == null) {
+            try {
+                fileToWrite = ioFactory.create(file, StandardOpenOption.CREATE, StandardOpenOption.WRITE);
+            }
+            catch (IOException e) {
+                throw new IgniteException(e);
+            }
+        }
+
+        byte[] hdr = getHeader();
+
+        if (hdr != null)
+            writeFully(hdr);
+    }
+
+    /**
+     * Write byte array into file.
+     *
+     * @param bytes Data.
+     * @throws IgniteException If write failed.
+     */
+    private void writeFully(byte[] bytes) {
+        int written = 0;
+
+        try {
+            while ((written += fileToWrite.writeFully(bytes, written, bytes.length - written)) < bytes.length);
+        }
+        catch (IOException ex) {
+            throw new IgniteException(ex);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public void finish() {
+        if (fileToWrite == null)
+            return;
+
+        try {
+            try {
+                fileToWrite.force();
+            }
+            finally {
+                fileToWrite.close();
+            }
+        }
+        catch (IOException ex) {
+            throw new IgniteException(ex);
+        }
+    }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/scanner/PrintToLogHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/scanner/PrintToLogHandler.java
new file mode 100644
index 0000000..2d1af63
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/scanner/PrintToLogHandler.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.persistence.wal.scanner;
+
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.internal.pagemem.wal.WALPointer;
+import org.apache.ignite.internal.pagemem.wal.record.WALRecord;
+import org.apache.ignite.lang.IgniteBiTuple;
+
+import static org.apache.ignite.internal.processors.cache.persistence.wal.scanner.ScannerHandlers.DEFAULT_WAL_RECORD_PREFIX;
+
+/**
+ * Handler which print record to log.
+ *
+ * This is not thread safe. Can be used only one time.
+ */
+class PrintToLogHandler implements ScannerHandler {
+    /** */
+    private final IgniteLogger log;
+
+    /** */
+    private StringBuilder resultString = new StringBuilder();
+
+    /**
+     * @param log Logger.
+     */
+    public PrintToLogHandler(IgniteLogger log) {
+        this.log = log;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void handle(IgniteBiTuple<WALPointer, WALRecord> record) {
+        ensureNotFinished();
+
+        resultString.append(DEFAULT_WAL_RECORD_PREFIX).append(record.get2()).append("\n");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void finish() {
+        ensureNotFinished();
+
+        String msg = resultString.toString();
+
+        resultString = null;
+
+        log.info(msg);
+    }
+
+    /**
+     *
+     */
+    private void ensureNotFinished() {
+        if (resultString == null)
+            throw new IgniteException("This handler has been already finished.");
+    }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/scanner/ScannerHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/scanner/ScannerHandler.java
new file mode 100644
index 0000000..f88815c
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/scanner/ScannerHandler.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.persistence.wal.scanner;
+
+import org.apache.ignite.internal.pagemem.wal.WALPointer;
+import org.apache.ignite.internal.pagemem.wal.record.WALRecord;
+import org.apache.ignite.lang.IgniteBiTuple;
+
+/**
+ * Scanner handler which provide ability to do some handling on each record during iteration.
+ */
+public interface ScannerHandler {
+    /**
+     * Handling one more record during iteration over WAL.
+     *
+     * @param record One more record from WAL.
+     */
+    void handle(IgniteBiTuple<WALPointer, WALRecord> record);
+
+    /**
+     * Method which called after all iteration would be finished.
+     */
+    default void finish() {
+    }
+
+    /**
+     * Execute 'then' handler after 'this'.
+     *
+     * @param then Next handler for execution.
+     * @return Composite handler.
+     */
+    default ScannerHandler andThen(ScannerHandler then) {
+        ScannerHandler thiz = this;
+
+        return new ScannerHandler() {
+            @Override public void handle(IgniteBiTuple<WALPointer, WALRecord> record) {
+                try {
+                    thiz.handle(record);
+                }
+                finally {
+                    then.handle(record);
+                }
+            }
+
+            @Override public void finish() {
+                try {
+                    thiz.finish();
+                }
+                finally {
+                    then.finish();
+                }
+            }
+        };
+    }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/scanner/ScannerHandlers.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/scanner/ScannerHandlers.java
new file mode 100644
index 0000000..0d69fa4
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/scanner/ScannerHandlers.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.persistence.wal.scanner;
+
+import java.io.File;
+import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.internal.processors.cache.persistence.file.FileIOFactory;
+import org.apache.ignite.internal.processors.cache.persistence.wal.serializer.RecordSerializer;
+
+/**
+ * Holder of {@link ScannerHandlers}.
+ */
+public class ScannerHandlers {
+    /** */
+    public static final String DEFAULT_WAL_RECORD_PREFIX = "Next WAL record :: ";
+
+    /**
+     * @param log Logger.
+     * @return Handler which write record to log.
+     */
+    public static ScannerHandler printToLog(IgniteLogger log) {
+        return new PrintToLogHandler(log);
+    }
+
+    /**
+     * @param file File to write.
+     * @return Handler which write record to file.
+     */
+    public static ScannerHandler printToFile(File file) {
+        return new PrintToFileHandler(file, null);
+    }
+
+    /**
+     * @param file File to write.
+     * @param ioFactory IO factory.
+     * @return Handler which write record to file.
+     */
+    public static ScannerHandler printToFile(File file, FileIOFactory ioFactory) {
+        return new PrintToFileHandler(file, ioFactory);
+    }
+
+    /**
+     * @param file File to write.
+     * @param serializer WAL records serializer.
+     * @return Handler which write record to file.
+     */
+    public static ScannerHandler printRawToFile(File file, RecordSerializer serializer) {
+        return new PrintRawToFileHandler(file, serializer);
+    }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/scanner/WalScanner.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/scanner/WalScanner.java
new file mode 100644
index 0000000..fe133a0
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/scanner/WalScanner.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.persistence.wal.scanner;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.internal.pagemem.PageIdUtils;
+import org.apache.ignite.internal.pagemem.wal.WALIterator;
+import org.apache.ignite.internal.pagemem.wal.WALPointer;
+import org.apache.ignite.internal.pagemem.wal.record.WALRecord;
+import org.apache.ignite.internal.processors.cache.persistence.wal.reader.FilteredWalIterator;
+import org.apache.ignite.internal.processors.cache.persistence.wal.reader.IgniteWalIteratorFactory;
+import org.apache.ignite.internal.processors.cache.persistence.wal.reader.IgniteWalIteratorFactory.IteratorParametersBuilder;
+import org.apache.ignite.internal.util.lang.IgniteThrowableSupplier;
+import org.apache.ignite.internal.util.typedef.T2;
+import org.apache.ignite.lang.IgniteBiTuple;
+import org.jetbrains.annotations.NotNull;
+
+import static java.util.Objects.requireNonNull;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordPurpose.MIXED;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordPurpose.PHYSICAL;
+import static org.apache.ignite.internal.processors.cache.persistence.wal.reader.WalFilters.checkpoint;
+import static org.apache.ignite.internal.processors.cache.persistence.wal.reader.WalFilters.pageOwner;
+import static org.apache.ignite.internal.processors.cache.persistence.wal.reader.WalFilters.partitionMetaStateUpdate;
+
+/**
+ * Scanning WAL by specific condition.
+ */
+public class WalScanner {
+    /** Parameters for iterator. */
+    private final IteratorParametersBuilder parametersBuilder;
+    /** Wal iterator factory. */
+    private final IgniteWalIteratorFactory iteratorFactory;
+
+    /**
+     * @param parametersBuilder Parameters for iterator.
+     * @param factory Factory of iterator.
+     */
+    WalScanner(
+        IteratorParametersBuilder parametersBuilder,
+        IgniteWalIteratorFactory factory
+    ) {
+        this.parametersBuilder = parametersBuilder;
+        iteratorFactory = factory == null ? new IgniteWalIteratorFactory() : factory;
+    }
+
+    /**
+     * Finding all page physical records whose pageId is contained in given collection.
+     *
+     * @param groupAndPageIds Search pages.
+     * @return Final step for execution some action on result.
+     */
+    @NotNull public WalScanner.ScanTerminateStep findAllRecordsFor(
+        @NotNull Collection<T2<Integer, Long>> groupAndPageIds
+    ) {
+        requireNonNull(groupAndPageIds);
+
+        HashSet<T2<Integer, Long>> groupAndPageIds0 = new HashSet<>(groupAndPageIds);
+
+        // Collect all (group, partition) partition pairs.
+        Set<T2<Integer, Integer>> groupAndParts = groupAndPageIds0.stream()
+            .map((tup) -> new T2<>(tup.get1(), PageIdUtils.partId(tup.get2())))
+            .collect(Collectors.toSet());
+
+        // Build WAL filter. (Checkoint, Page, Partition meta)
+        Predicate<IgniteBiTuple<WALPointer, WALRecord>> filter = checkpoint()
+            .or(pageOwner(groupAndPageIds0))
+            .or(partitionMetaStateUpdate(groupAndParts));
+
+        return new ScanTerminateStep(() -> iterator(filter,
+            parametersBuilder.copy().addFilter((type, pointer) ->
+                // PHYSICAL need fo page shanpshot or delta record.
+                // MIXED need for partiton meta state update.
+                type.purpose() == PHYSICAL || type.purpose() == MIXED
+            )
+        ));
+    }
+
+    /**
+     * @param filter Record filter.
+     * @param parametersBuilder Iterator parameters for customization.
+     * @return Instance of {@link FilteredWalIterator}.
+     * @throws IgniteCheckedException If initialization of iterator will be failed.
+     */
+    @NotNull private FilteredWalIterator iterator(
+        Predicate<IgniteBiTuple<WALPointer, WALRecord>> filter,
+        IteratorParametersBuilder parametersBuilder
+    ) throws IgniteCheckedException {
+        return new FilteredWalIterator(iteratorFactory.iterator(parametersBuilder), filter);
+    }
+
+    /**
+     * Factory method of {@link WalScanner}.
+     *
+     * @param parametersBuilder Iterator parameters for customization.
+     * @return Instance of {@link WalScanner}.
+     */
+    public static WalScanner buildWalScanner(IteratorParametersBuilder parametersBuilder) {
+        return new WalScanner(parametersBuilder, null);
+    }
+
+    /**
+     * Factory method of {@link WalScanner}.
+     *
+     * @param parametersBuilder Iterator parameters for customization.
+     * @param factory Custom instance of {@link IgniteWalIteratorFactory}.
+     * @return Instance of {@link WalScanner}.
+     */
+    public static WalScanner buildWalScanner(
+        IteratorParametersBuilder parametersBuilder,
+        IgniteWalIteratorFactory factory
+    ) {
+        return new WalScanner(parametersBuilder, factory);
+    }
+
+    /**
+     * Terminate state of scanning of WAL for ability to do chaining flow.
+     */
+    public static class ScanTerminateStep {
+        /** WAL iteration supplier. */
+        final IgniteThrowableSupplier<WALIterator> iterSupplier;
+
+        /**
+         * @param iterSupplier WAL iteration supplier.
+         */
+        private ScanTerminateStep(IgniteThrowableSupplier<WALIterator> iterSupplier) {
+            this.iterSupplier = iterSupplier;
+        }
+
+        /**
+         * Execute given handler on each record.
+         *
+         * @param handler Single record handler.
+         * @throws IgniteCheckedException If iteration was failed.
+         */
+        public void forEach(@NotNull ScannerHandler handler) throws IgniteCheckedException {
+            try (WALIterator it = iterSupplier.get()) {
+                while (it.hasNext())
+                    handler.handle(it.next());
+            }
+            finally {
+                handler.finish();
+            }
+        }
+    }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/diagnostic/DiagnosticProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/diagnostic/DiagnosticProcessor.java
new file mode 100644
index 0000000..36cb248
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/diagnostic/DiagnosticProcessor.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.diagnostic;
+
+import java.io.File;
+import java.nio.file.Path;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.failure.FailureContext;
+import org.apache.ignite.internal.GridKernalContext;
+import org.apache.ignite.internal.processors.GridProcessorAdapter;
+import org.apache.ignite.internal.processors.cache.persistence.tree.CorruptedTreeException;
+import org.apache.ignite.internal.util.typedef.T2;
+import org.apache.ignite.internal.util.typedef.X;
+import org.apache.ignite.internal.util.typedef.internal.SB;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.jetbrains.annotations.NotNull;
+
+import static org.apache.ignite.internal.processors.diagnostic.DiagnosticProcessor.DiagnosticAction.PRINT_TO_FILE;
+import static org.apache.ignite.internal.processors.diagnostic.DiagnosticProcessor.DiagnosticAction.PRINT_TO_LOG;
+import static org.apache.ignite.internal.processors.diagnostic.DiagnosticProcessor.DiagnosticAction.PRINT_TO_RAW_FILE;
+import static org.apache.ignite.internal.util.IgniteStopwatch.logTime;
+
+/**
+ * Processor which contained helper methods for different diagnostic cases.
+ */
+public class DiagnosticProcessor extends GridProcessorAdapter {
+    /** Time formatter for dump file name. */
+    private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH-mm-ss_SSS");
+    /** Folder name for store diagnostic info. **/
+    static final String DEFAULT_TARGET_FOLDER = "diagnostic";
+    /** File format. */
+    static final String FILE_FORMAT = ".txt";
+    /** Raw file format. */
+    static final String RAW_FILE_FORMAT = ".raw";
+    /** Full path for store dubug info. */
+    private final Path diagnosticPath;
+
+    private final PageHistoryDiagnoster pageHistoryDiagnoster;
+
+    /**
+     * @param ctx Kernal context.
+     */
+    public DiagnosticProcessor(GridKernalContext ctx) throws IgniteCheckedException {
+        super(ctx);
+
+        diagnosticPath = U.resolveWorkDirectory(ctx.config().getWorkDirectory(), DEFAULT_TARGET_FOLDER, false).toPath();
+
+        pageHistoryDiagnoster = new PageHistoryDiagnoster(ctx, this::diagnosticFile);
+
+    }
+
+    /** {@inheritDoc} */
+    @Override public void onKernalStart(boolean active) throws IgniteCheckedException {
+        super.onKernalStart(active);
+
+        pageHistoryDiagnoster.onStart();
+    }
+
+    /**
+     * Dump all history caches of given page.
+     *
+     * @param builder Parameters of dumping.
+     * @throws IgniteCheckedException If scanning was failed.
+     */
+    public void dumpPageHistory(
+        @NotNull PageHistoryDiagnoster.DiagnosticPageBuilder builder
+    ) throws IgniteCheckedException {
+        logTime(log, "DiagnosticPageHistory", () -> pageHistoryDiagnoster.dumpPageHistory(builder));
+    }
+
+    /**
+     * Print diagnostic info about failure occurred on {@code ignite} instance.
+     * Failure details is contained in {@code failureCtx}.
+     *
+     * @param ignite Ignite instance.
+     * @param failureCtx Failure context.
+     */
+    public void onFailure(Ignite ignite, FailureContext failureCtx) {
+        // If we have some corruption in data structure,
+        // we should scan WAL and print to log and save to file all pages related to corruption for
+        // future investigation.
+        if (X.hasCause(failureCtx.error(), CorruptedTreeException.class)) {
+            CorruptedTreeException corruptedTreeException = X.cause(failureCtx.error(), CorruptedTreeException.class);
+
+            T2<Integer, Long>[] pageIds = corruptedTreeException.pages();
+
+            try {
+                dumpPageHistory(
+                    new PageHistoryDiagnoster.DiagnosticPageBuilder()
+                        .pageIds(pageIds)
+                        .addAction(PRINT_TO_LOG)
+                        .addAction(PRINT_TO_FILE)
+                        .addAction(PRINT_TO_RAW_FILE)
+                );
+            }
+            catch (IgniteCheckedException e) {
+                SB sb = new SB();
+                sb.a("[");
+
+                for (int i = 0; i < pageIds.length; i++)
+                    sb.a("(").a(pageIds[i].get1()).a(",").a(pageIds[i].get2()).a(")");
+
+                sb.a("]");
+
+                ignite.log().error(
+                    "Failed to dump diagnostic info on tree corruption. PageIds=" + sb, e);
+            }
+        }
+    }
+
+    /**
+     * Resolve file to store diagnostic info.
+     *
+     * @param customFile Custom file if customized.
+     * @param writeMode Diagnostic file write mode.
+     * @return File to store diagnostic info.
+     */
+    private File diagnosticFile(File customFile, DiagnosticFileWriteMode writeMode) {
+        if (customFile == null)
+            return finalizeFile(diagnosticPath, writeMode);
+
+        if (customFile.isAbsolute())
+            return finalizeFile(customFile.toPath(), writeMode);
+
+        return finalizeFile(diagnosticPath.resolve(customFile.toPath()), writeMode);
+    }
+
+    /**
+     * @param diagnosticPath Path to diagnostic file.
+     * @param writeMode Diagnostic file write mode.
+     * @return File to store diagnostic info.
+     */
+    private static File finalizeFile(Path diagnosticPath, DiagnosticFileWriteMode writeMode) {
+        diagnosticPath.toFile().mkdirs();
+
+        return diagnosticPath.resolve(LocalDateTime.now().format(TIME_FORMATTER) + getFileExtension(writeMode)).toFile();
+    }
+
+    /**
+     * Get file format for given write mode.
+     *
+     * @param writeMode Diagnostic file write mode.
+     * @return File extention with dot.
+     */
+    private static String getFileExtension(DiagnosticFileWriteMode writeMode) {
+        switch (writeMode) {
+            case HUMAN_READABLE:
+                return FILE_FORMAT;
+
+            case RAW:
+                return RAW_FILE_FORMAT;
+
+            default:
+                throw new IllegalArgumentException("writeMode=" + writeMode);
+        }
+    }
+
+    /**
+     * Possible action after WAL scanning.
+     */
+    public enum DiagnosticAction {
+        /** Print result to log. */
+        PRINT_TO_LOG,
+        /** Print result to file. */
+        PRINT_TO_FILE,
+        /** Print result to file in raw format. */
+        PRINT_TO_RAW_FILE
+    }
+
+    /**
+     * Mode of diagnostic dump file.
+     */
+    public enum DiagnosticFileWriteMode {
+        /** Use humanly readable data representation. */
+        HUMAN_READABLE,
+        /** Use raw data format. */
+        RAW
+    }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/diagnostic/PageHistoryDiagnoster.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/diagnostic/PageHistoryDiagnoster.java
new file mode 100644
index 0000000..3572fc8
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/diagnostic/PageHistoryDiagnoster.java
@@ -0,0 +1,381 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.diagnostic;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.function.BiFunction;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.internal.GridKernalContext;
+import org.apache.ignite.internal.pagemem.PageIdUtils;
+import org.apache.ignite.internal.pagemem.wal.WALIterator;
+import org.apache.ignite.internal.pagemem.wal.WALPointer;
+import org.apache.ignite.internal.pagemem.wal.record.WALRecord;
+import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
+import org.apache.ignite.internal.processors.cache.persistence.wal.FileDescriptor;
+import org.apache.ignite.internal.processors.cache.persistence.wal.FileWALPointer;
+import org.apache.ignite.internal.processors.cache.persistence.wal.FileWriteAheadLogManager;
+import org.apache.ignite.internal.processors.cache.persistence.wal.SegmentRouter;
+import org.apache.ignite.internal.processors.cache.persistence.wal.reader.IgniteWalIteratorFactory;
+import org.apache.ignite.internal.processors.cache.persistence.wal.reader.IgniteWalIteratorFactory.IteratorParametersBuilder;
+import org.apache.ignite.internal.processors.cache.persistence.wal.scanner.ScannerHandler;
+import org.apache.ignite.internal.processors.cache.persistence.wal.scanner.WalScanner.ScanTerminateStep;
+import org.apache.ignite.internal.processors.cache.persistence.wal.serializer.RecordSerializer;
+import org.apache.ignite.internal.processors.cache.persistence.wal.serializer.RecordSerializerFactoryImpl;
+import org.apache.ignite.internal.processors.diagnostic.DiagnosticProcessor.DiagnosticFileWriteMode;
+import org.apache.ignite.internal.util.tostring.GridToStringExclude;
+import org.apache.ignite.internal.util.typedef.T2;
+import org.apache.ignite.lang.IgniteBiTuple;
+import org.jetbrains.annotations.NotNull;
+
+import static java.util.Objects.requireNonNull;
+import static org.apache.ignite.internal.processors.cache.persistence.wal.reader.IgniteWalIteratorFactory.IteratorParametersBuilder.withIteratorParameters;
+import static org.apache.ignite.internal.processors.cache.persistence.wal.reader.WalFilters.checkpoint;
+import static org.apache.ignite.internal.processors.cache.persistence.wal.reader.WalFilters.pageOwner;
+import static org.apache.ignite.internal.processors.cache.persistence.wal.reader.WalFilters.partitionMetaStateUpdate;
+import static org.apache.ignite.internal.processors.cache.persistence.wal.scanner.ScannerHandlers.printToFile;
+import static org.apache.ignite.internal.processors.cache.persistence.wal.scanner.ScannerHandlers.printToLog;
+import static org.apache.ignite.internal.processors.cache.persistence.wal.scanner.ScannerHandlers.printRawToFile;
+import static org.apache.ignite.internal.processors.cache.persistence.wal.scanner.WalScanner.buildWalScanner;
+
+/**
+ * Diagnostic WAL page history.
+ */
+public class PageHistoryDiagnoster {
+    /** Kernal context. */
+    @GridToStringExclude
+    protected final GridKernalContext ctx;
+    /** Diagnostic logger. */
+    @GridToStringExclude
+    protected final IgniteLogger log;
+
+    /** Wal folders to scan. */
+    private File[] walFolders;
+
+    /** Function to provide target end file to store diagnostic info. */
+    private final BiFunction<File, DiagnosticFileWriteMode, File> targetFileSupplier;
+
+    private final IgniteWalIteratorFactory iteratorFactory = new IgniteWalIteratorFactory();
+
+    /** */
+    private volatile FileWriteAheadLogManager wal;
+
+    /**
+     * @param ctx Kernal context.
+     * @param supplier Function to provide target end file to store diagnostic info.
+     */
+    public PageHistoryDiagnoster(GridKernalContext ctx, BiFunction<File, DiagnosticFileWriteMode, File> supplier) {
+        log = ctx.log(getClass());
+        this.ctx = ctx;
+        targetFileSupplier = supplier;
+    }
+
+    /**
+     * Do action on start.
+     */
+    public void onStart() {
+        FileWriteAheadLogManager wal = (FileWriteAheadLogManager)ctx.cache().context().wal();
+
+        if (wal == null)
+            return;
+
+        this.wal = wal;
+
+        SegmentRouter segmentRouter = wal.getSegmentRouter();
+
+        if (segmentRouter.hasArchive())
+            walFolders = new File[] {segmentRouter.getWalArchiveDir(), segmentRouter.getWalWorkDir()};
+        else
+            walFolders = new File[] {segmentRouter.getWalWorkDir()};
+    }
+
+    /**
+     * Dump all history caches of given page.
+     *
+     * @param builder Parameters of dumping.
+     * @throws IgniteCheckedException If scanning was failed.
+     */
+    public void dumpPageHistory(
+        @NotNull PageHistoryDiagnoster.DiagnosticPageBuilder builder
+    ) throws IgniteCheckedException {
+        if (walFolders == null) {
+            log.info("Skipping dump page history due to WAL not configured");
+
+            return;
+        }
+
+        ScannerHandler action = null;
+
+        for (DiagnosticProcessor.DiagnosticAction act : builder.actions) {
+            if (action == null)
+                action = toHandler(act, builder.dumpFolder);
+            else
+                action = action.andThen(toHandler(act, builder.dumpFolder));
+        }
+
+        requireNonNull(action, "Should be configured at least one action");
+
+        IteratorParametersBuilder params = withIteratorParameters()
+            .log(log)
+            .filesOrDirs(walFolders);
+
+        // Resolve available WAL segment files.
+        List<FileDescriptor> descs = iteratorFactory.resolveWalFiles(params);
+
+        int descIdx = -1;
+        FileWALPointer reserved = null;
+
+        for (int i = 0; i < descs.size(); i++) {
+            // Try resever minimal available segment.
+            if (wal.reserve(reserved = new FileWALPointer(descs.get(i).idx(), 0, 0))) {
+                descIdx = i;
+
+                break;
+            }
+        }
+
+        if (descIdx == -1) {
+            log.info("Skipping dump page history due to can not reserve WAL segments: " + descToString(descs));
+
+            return;
+        }
+
+        if (log.isDebugEnabled())
+            log.debug("Reserverd WAL segment idx: " + reserved.index());
+
+        // Check gaps in the reserved interval.
+        List<T2<Long, Long>> gaps = iteratorFactory.hasGaps(descs.subList(descIdx, descs.size()));
+
+        if (!gaps.isEmpty())
+            log.warning("Potentialy missed record because WAL has gaps: " + gapsToString(gaps));
+
+        try {
+            scan(builder, params, action, reserved);
+        }
+        finally {
+            assert reserved != null;
+
+            wal.release(reserved);
+
+            if (log.isDebugEnabled())
+                log.debug("Release WAL segment idx:" + reserved.index());
+        }
+    }
+
+    /**
+     * @param builder Diagnostic parameter builder.
+     * @param params Iterator parameter builder.
+     * @param action Action.
+     * @param from Pointer from replay.
+     */
+    private void scan(
+        PageHistoryDiagnoster.DiagnosticPageBuilder builder,
+        IteratorParametersBuilder params,
+        ScannerHandler action,
+        FileWALPointer from
+    ) throws IgniteCheckedException {
+        IgniteBiTuple<WALPointer, WALRecord> lastReadRec = null;
+        // Try scan via WAL manager. More safety way on working node.
+        try {
+            Set<T2<Integer, Long>> groupAndPageIds0 = new HashSet<>(builder.pageIds);
+
+            // Collect all (group, partition) partition pairs.
+            Set<T2<Integer, Integer>> groupAndParts = groupAndPageIds0.stream()
+                .map((tup) -> new T2<>(tup.get1(), PageIdUtils.partId(tup.get2())))
+                .collect(Collectors.toSet());
+
+            // Build WAL filter. (Checkoint, Page, Partition meta)
+            Predicate<IgniteBiTuple<WALPointer, WALRecord>> filter = checkpoint()
+                .or(pageOwner(groupAndPageIds0))
+                .or(partitionMetaStateUpdate(groupAndParts));
+
+            try (WALIterator it = wal.replay(from)) {
+                while (it.hasNext()) {
+                    IgniteBiTuple<WALPointer, WALRecord> recTup = lastReadRec = it.next();
+
+                    if (filter.test(recTup))
+                        action.handle(recTup);
+                }
+            }
+            finally {
+                action.finish();
+            }
+
+            return;
+
+        }
+        catch (IgniteCheckedException e) {
+            if (lastReadRec != null) {
+                log.warning("Failed to diagnosric scan via WAL manager, lastReadRec:["
+                    + lastReadRec.get1() + ", " + lastReadRec.get2() + "]",e);
+            }
+            else
+                log.warning("Failed to diagnosric scan via WAL manager", e);
+        }
+
+        // Try scan via stand alone iterator is not safety if wal still generated and moving to archive.
+        // Build scanner for pageIds from reserved pointer.
+        ScanTerminateStep scanner = buildWalScanner(params.from(from)).findAllRecordsFor(builder.pageIds);
+
+        scanner.forEach(action);
+    }
+
+    /**
+     * @param descs WAL file descriptors.
+     * @return String representation.
+     */
+    private String descToString(List<FileDescriptor> descs) {
+        StringBuilder sb = new StringBuilder();
+
+        sb.append("[");
+
+        Iterator<FileDescriptor> iter = descs.iterator();
+
+        while (iter.hasNext()) {
+            FileDescriptor desc = iter.next();
+
+            sb.append(desc.idx());
+
+            if (!iter.hasNext())
+                sb.append(", ");
+        }
+
+        sb.append("]");
+
+        return sb.toString();
+    }
+
+    /**
+     * @param gaps WAL file gaps.
+     * @return String representation.
+     */
+    private String gapsToString(Collection<T2<Long, Long>> gaps) {
+        StringBuilder sb = new StringBuilder();
+
+        sb.append("[");
+
+        Iterator<T2<Long, Long>> iter = gaps.iterator();
+
+        while (iter.hasNext()) {
+            T2<Long, Long> gap = iter.next();
+
+            sb.append("(").append(gap.get1()).append("..").append(gap.get2()).append(")");
+
+            if (!iter.hasNext())
+                sb.append(", ");
+        }
+
+        sb.append("]");
+
+        return sb.toString();
+    }
+
+    /**
+     * @param action Action for converting.
+     * @param customFile File to store diagnostic info.
+     * @return {@link ScannerHandler} for handle records.
+     */
+    private ScannerHandler toHandler(DiagnosticProcessor.DiagnosticAction action, File customFile) {
+        switch (action) {
+            case PRINT_TO_LOG:
+                return printToLog(log);
+
+            case PRINT_TO_FILE:
+                return printToFile(targetFileSupplier.apply(customFile, DiagnosticFileWriteMode.HUMAN_READABLE));
+
+            case PRINT_TO_RAW_FILE:
+                return printRawToFile(targetFileSupplier.apply(customFile, DiagnosticFileWriteMode.RAW), serializer());
+
+            default:
+                throw new IllegalArgumentException("Unknown diagnostic action : " + action);
+        }
+    }
+
+    /**
+     * @return WAL records serializer.
+     * @throws IgniteException If serializer initialization failed for some reason.
+     */
+    private RecordSerializer serializer() {
+        GridCacheSharedContext<?, ?> cctx = ctx.cache().context();
+
+        int serializerVer = cctx.wal().serializerVersion();
+
+        try {
+            return new RecordSerializerFactoryImpl(cctx).createSerializer(serializerVer);
+        }
+        catch (IgniteCheckedException e) {
+            log.error(
+                "Failed to create WAL records serializer for diagnostic purposes [serializerVer=" + serializerVer + "]"
+            );
+
+            throw new IgniteException(e);
+        }
+    }
+
+    /**
+     * Parameters for diagnostic pages.
+     */
+    public static class DiagnosticPageBuilder {
+        /** Pages for searching in WAL. */
+        List<T2<Integer, Long>> pageIds = new ArrayList<>();
+        /** Action after which should be executed after WAL scanning . */
+        Set<DiagnosticProcessor.DiagnosticAction> actions = EnumSet.noneOf(DiagnosticProcessor.DiagnosticAction.class);
+        /** Folder for dump diagnostic info. */
+        File dumpFolder;
+
+        /**
+         * @param pageIds Pages for searching in WAL.
+         * @return This instance for chaining.
+         */
+        public DiagnosticPageBuilder pageIds(T2<Integer, Long>... pageIds) {
+            this.pageIds.addAll(Arrays.asList(pageIds));
+
+            return this;
+        }
+
+        /**
+         * @param action Action after which should be executed after WAL scanning .
+         * @return This instance for chaining.
+         */
+        public DiagnosticPageBuilder addAction(@NotNull DiagnosticProcessor.DiagnosticAction action) {
+            this.actions.add(action);
+
+            return this;
+        }
+
+        /**
+         * @param file Folder for dump diagnostic info.
+         * @return This instance for chaining.
+         */
+        public DiagnosticPageBuilder folderForDump(@NotNull File file) {
+            this.dumpFolder = file;
+
+            return this;
+        }
+    }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/failure/FailureProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/failure/FailureProcessor.java
index 866351c..1fb55e4 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/failure/FailureProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/failure/FailureProcessor.java
@@ -28,6 +28,7 @@ import org.apache.ignite.failure.StopNodeOrHaltFailureHandler;
 import org.apache.ignite.internal.GridKernalContext;
 import org.apache.ignite.internal.processors.GridProcessorAdapter;
 import org.apache.ignite.internal.processors.cache.persistence.CorruptedPersistenceException;
+import org.apache.ignite.internal.processors.diagnostic.DiagnosticProcessor;
 import org.apache.ignite.internal.util.typedef.X;
 import org.apache.ignite.internal.util.typedef.internal.U;
 
@@ -142,6 +143,11 @@ public class FailureProcessor extends GridProcessorAdapter {
         if (IGNITE_DUMP_THREADS_ON_FAILURE)
             U.dumpThreads(log);
 
+        DiagnosticProcessor diagnosticProcessor = ctx.diagnostic();
+
+        if (diagnosticProcessor != null)
+            diagnosticProcessor.onFailure(ignite, failureCtx);
+
         boolean invalidated = hnd.onFailure(ignite, failureCtx);
 
         if (invalidated) {
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteStopwatch.java b/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteStopwatch.java
index 0cad3c4..51ef932 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteStopwatch.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteStopwatch.java
@@ -22,6 +22,9 @@ package org.apache.ignite.internal.util;
 
 import java.time.Duration;
 import java.util.concurrent.TimeUnit;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.internal.util.lang.IgniteThrowableRunner;
 import org.jetbrains.annotations.NotNull;
 
 import static java.util.concurrent.TimeUnit.DAYS;
@@ -117,6 +120,36 @@ public final class IgniteStopwatch {
     }
 
     /**
+     * Execution given operation and calculation it time.
+     *
+     * @param log Logger fol logging.
+     * @param operationName Operation name for logging.
+     * @param operation Operation for execution.
+     * @throws IgniteCheckedException If failed.
+     */
+    public static void logTime(
+        IgniteLogger log,
+        String operationName,
+        IgniteThrowableRunner operation
+    ) throws IgniteCheckedException {
+        long start = System.currentTimeMillis();
+
+        log.info("Operation was started: operation = " + operationName);
+        try {
+            operation.run();
+        }
+        catch (Throwable ex) {
+            log.info("Operation was failed: operation = " + operationName
+                + ", elapsedTime = " + (System.currentTimeMillis() - start) + " ms");
+
+            throw ex;
+        }
+
+        log.info("Operation was success: operation = " + operationName
+            + ", elapsedTime = " + (System.currentTimeMillis() - start) + " ms");
+    }
+
+    /**
      * Default constructor.
      */
     IgniteStopwatch() {
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/lang/IgniteThrowableConsumer.java b/modules/core/src/main/java/org/apache/ignite/internal/util/lang/IgniteThrowableConsumer.java
index b151841..40584af 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/util/lang/IgniteThrowableConsumer.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/lang/IgniteThrowableConsumer.java
@@ -22,15 +22,17 @@ import org.apache.ignite.IgniteCheckedException;
 /**
  * Represents an operation that accepts a single input argument and returns no result. Unlike most other functional
  * interfaces, {@code IgniteThrowableConsumer} is expected to operate via side-effects.
- * Also it is able to throw {@link IgniteCheckedException} unlike {@link java.util.function.Function}.
  *
- * @param <E> Type of closure parameter.
+ * Also it is able to throw {@link IgniteCheckedException} unlike {@link java.util.function.Consumer}.
+ *
+ * @param <E> The type of the input to the operation.
  */
+@FunctionalInterface
 public interface IgniteThrowableConsumer<E> extends Serializable {
     /**
-     * Consumer body.
+     * Performs this operation on the given argument.
      *
-     * @param e Consumer parameter.
+     * @param e the input argument
      * @throws IgniteCheckedException If body execution was failed.
      */
     public void accept(E e) throws IgniteCheckedException;
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/lang/IgniteThrowableConsumer.java b/modules/core/src/main/java/org/apache/ignite/internal/util/lang/IgniteThrowableSupplier.java
similarity index 62%
copy from modules/core/src/main/java/org/apache/ignite/internal/util/lang/IgniteThrowableConsumer.java
copy to modules/core/src/main/java/org/apache/ignite/internal/util/lang/IgniteThrowableSupplier.java
index b151841..36b8ce0 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/util/lang/IgniteThrowableConsumer.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/lang/IgniteThrowableSupplier.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
@@ -20,18 +20,20 @@ import java.io.Serializable;
 import org.apache.ignite.IgniteCheckedException;
 
 /**
- * Represents an operation that accepts a single input argument and returns no result. Unlike most other functional
- * interfaces, {@code IgniteThrowableConsumer} is expected to operate via side-effects.
- * Also it is able to throw {@link IgniteCheckedException} unlike {@link java.util.function.Function}.
+ * Represents a supplier of results. There is no requirement that a new or distinct result be returned each
+ * time the supplier is invoked.
+ *
+ * Also it is able to throw {@link IgniteCheckedException} unlike {@link java.util.function.Supplier}.
  *
- * @param <E> Type of closure parameter.
+ * @param <E> The type of results supplied by this supplier.
  */
-public interface IgniteThrowableConsumer<E> extends Serializable {
+@FunctionalInterface
+public interface IgniteThrowableSupplier<E> extends Serializable {
     /**
-     * Consumer body.
+     * Gets a result.
      *
-     * @param e Consumer parameter.
-     * @throws IgniteCheckedException If body execution was failed.
+     * @return a result
+     * @throws IgniteCheckedException If result calculation failed.
      */
-    public void accept(E e) throws IgniteCheckedException;
+    public E get() throws IgniteCheckedException;
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/lang/IgniteBiPredicate.java b/modules/core/src/main/java/org/apache/ignite/lang/IgniteBiPredicate.java
index cba385c..af76653 100644
--- a/modules/core/src/main/java/org/apache/ignite/lang/IgniteBiPredicate.java
+++ b/modules/core/src/main/java/org/apache/ignite/lang/IgniteBiPredicate.java
@@ -17,6 +17,7 @@
 package org.apache.ignite.lang;
 
 import java.io.Serializable;
+import java.util.Objects;
 
 /**
  * Defines a predicate which accepts two parameters and returns {@code true} or {@code false}.
@@ -33,4 +34,26 @@ public interface IgniteBiPredicate<E1, E2> extends Serializable {
      * @return Return value.
      */
     public boolean apply(E1 e1, E2 e2);
-}
\ No newline at end of file
+
+    /**
+     * Returns a composed predicate that represents a short-circuiting logical
+     * AND of this predicate and another.  When evaluating the composed
+     * predicate, if this predicate is {@code false}, then the {@code other}
+     * predicate is not evaluated.
+     *
+     * <p>Any exceptions thrown during evaluation of either predicate are relayed
+     * to the caller; if evaluation of this predicate throws an exception, the
+     * {@code other} predicate will not be evaluated.
+     *
+     * @param then a predicate that will be logically-ANDed with this
+     *              predicate
+     * @return a composed predicate that represents the short-circuiting logical
+     * AND of this predicate and the {@code other} predicate
+     * @throws NullPointerException if other is null
+     */
+    default IgniteBiPredicate<E1, E2> and(IgniteBiPredicate<E1, E2> then) {
+        Objects.requireNonNull(then);
+
+        return (p1, p2) -> apply(p1, p2) && then.apply(p1, p2);
+    }
+}
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/CorruptedTreeFailureHandlingTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/CorruptedTreeFailureHandlingTest.java
new file mode 100644
index 0000000..b25a618
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/CorruptedTreeFailureHandlingTest.java
@@ -0,0 +1,255 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.persistence;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.Serializable;
+import java.nio.ByteBuffer;
+import java.nio.file.OpenOption;
+import java.nio.file.StandardOpenOption;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.AtomicReference;
+import org.apache.commons.io.FileUtils;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.cache.affinity.rendezvous.RendezvousAffinityFunction;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.DataStorageConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.failure.FailureHandler;
+import org.apache.ignite.failure.StopNodeFailureHandler;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.pagemem.FullPageId;
+import org.apache.ignite.internal.pagemem.PageIdUtils;
+import org.apache.ignite.internal.pagemem.wal.record.PageSnapshot;
+import org.apache.ignite.internal.processors.cache.persistence.file.FileIO;
+import org.apache.ignite.internal.processors.cache.persistence.file.FileIODecorator;
+import org.apache.ignite.internal.processors.cache.persistence.file.FileIOFactory;
+import org.apache.ignite.internal.processors.cache.persistence.file.RandomAccessFileIO;
+import org.apache.ignite.internal.processors.cache.persistence.file.RandomAccessFileIOFactory;
+import org.apache.ignite.internal.processors.cache.persistence.tree.CorruptedTreeException;
+import org.apache.ignite.internal.processors.cache.persistence.tree.io.DataPageIO;
+import org.apache.ignite.internal.processors.cache.persistence.tree.io.PageIO;
+import org.apache.ignite.internal.processors.cache.persistence.wal.crc.FastCrc;
+import org.apache.ignite.internal.processors.cache.tree.AbstractDataLeafIO;
+import org.apache.ignite.internal.processors.cache.tree.DataLeafIO;
+import org.apache.ignite.internal.processors.cache.tree.mvcc.data.MvccDataLeafIO;
+import org.apache.ignite.internal.util.GridUnsafe;
+import org.apache.ignite.internal.util.typedef.G;
+import org.apache.ignite.internal.util.typedef.X;
+import org.apache.ignite.testframework.GridTestUtils;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/** */
+public class CorruptedTreeFailureHandlingTest extends GridCommonAbstractTest implements Serializable {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /** */
+    private static final int CACHE_ENTRIES = 10;
+
+    /** Partition file with corrupted page. */
+    private final AtomicReference<File> fileRef = new AtomicReference<>();
+
+    /** Link to corrupted page. */
+    private final AtomicLong linkRef = new AtomicLong();
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(gridName);
+
+        cfg.setConsistentId(gridName);
+
+        DataStorageConfiguration dataStorageConfiguration = new DataStorageConfiguration();
+
+        dataStorageConfiguration.getDefaultDataRegionConfiguration().setPersistenceEnabled(true);
+        dataStorageConfiguration.setFileIOFactory(new CollectLinkFileIOFactory());
+
+        cfg.setDataStorageConfiguration(dataStorageConfiguration);
+
+        cfg.setCacheConfiguration(new CacheConfiguration<>()
+            .setName(DEFAULT_CACHE_NAME)
+            .setAffinity(new RendezvousAffinityFunction().setPartitions(1))
+            .setAtomicityMode(CacheAtomicityMode.TRANSACTIONAL)
+        );
+
+        return cfg;
+    }
+
+    /** */
+    @Before
+    public void before() throws Exception {
+        stopAllGrids();
+
+        cleanPersistenceDir();
+    }
+
+    /** */
+    @After
+    public void after() throws Exception {
+        stopAllGrids();
+
+        cleanPersistenceDir();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected FailureHandler getFailureHandler(String igniteInstanceName) {
+        return new StopNodeFailureHandler();
+    }
+
+    /** */
+    @Test
+    public void testCorruptedPage() throws Exception {
+        IgniteEx srv = startGrid(0);
+
+        File diagnosticDir = new File(srv.context().config().getWorkDirectory(), "diagnostic");
+
+        FileUtils.deleteDirectory(diagnosticDir);
+
+        srv.cluster().active(true);
+
+        IgniteCache<Integer, Integer> cache = srv.getOrCreateCache(DEFAULT_CACHE_NAME);
+
+        for (int i = 0; i < 10; i++)
+            cache.put(i, i);
+
+        int pageSize = srv.configuration().getDataStorageConfiguration().getPageSize();
+
+        int grpId = srv.context().cache().cacheGroups().stream().filter(
+            context -> context.cacheOrGroupName().equals(DEFAULT_CACHE_NAME)
+        ).findAny().orElseThrow(() -> new RuntimeException("Cache group not found")).groupId();
+
+        stopGrid(0, false);
+
+        // Node is stopped, we're ready to corrupt partition data.
+        long link = linkRef.get();
+        long pageId = PageIdUtils.pageId(link);
+        int itemId = PageIdUtils.itemId(link);
+
+        ByteBuffer pageBuf = ByteBuffer.allocateDirect(pageSize);
+
+        OpenOption[] options = {StandardOpenOption.READ, StandardOpenOption.WRITE};
+        try (RandomAccessFileIO fileIO = new RandomAccessFileIO(fileRef.get(), options)) {
+            DataPageIO dataPageIO = DataPageIO.VERSIONS.latest();
+
+            long pageOff = pageSize + PageIdUtils.pageIndex(pageId) * pageSize;
+
+            // Read index page.
+            fileIO.position(pageOff);
+            fileIO.readFully(pageBuf);
+
+            long pageAddr = GridUnsafe.bufferAddress(pageBuf);
+
+            // Remove existing item from index page.
+            dataPageIO.removeRow(pageAddr, itemId, pageSize);
+
+            // Recalculate CRC.
+            PageIO.setCrc(pageAddr, 0);
+
+            pageBuf.rewind();
+            PageIO.setCrc(pageAddr, FastCrc.calcCrc(pageBuf, pageSize));
+
+            // Write it back.
+            pageBuf.rewind();
+            fileIO.position(pageOff);
+            fileIO.writeFully(pageBuf);
+        }
+
+        srv = startGrid(0);
+
+        // Add modified page to WAL so it won't be restored to previous (valid) state.
+        pageBuf.rewind();
+        ByteBuffer cpBuf = ByteBuffer.allocate(pageBuf.capacity());
+        cpBuf.put(pageBuf);
+
+        PageSnapshot pageSnapshot = new PageSnapshot(new FullPageId(pageId, grpId), cpBuf.array(), pageSize);
+
+        srv.context().cache().context().wal().log(pageSnapshot);
+
+        // Access cache.
+        cache = srv.cache(DEFAULT_CACHE_NAME);
+
+        try {
+            for (int i = 0; i < CACHE_ENTRIES; i++)
+                cache.get(i);
+
+            fail("Cache operations are expected to fail");
+        }
+        catch (Throwable e) {
+            assertTrue(X.hasCause(e, CorruptedTreeException.class));
+        }
+
+        assertTrue(GridTestUtils.waitForCondition(() -> G.allGrids().isEmpty(), 10_000L));
+
+        assertTrue(diagnosticDir.exists());
+        assertTrue(diagnosticDir.isDirectory());
+
+        File[] txtFiles = diagnosticDir.listFiles((dir, name) -> name.endsWith(".txt"));
+
+        assertTrue(txtFiles != null && txtFiles.length == 1);
+
+        File[] rawFiles = diagnosticDir.listFiles((dir, name) -> name.endsWith(".raw"));
+
+        assertTrue(rawFiles != null && rawFiles.length == 1);
+    }
+
+    /** */
+    private class CollectLinkFileIOFactory implements FileIOFactory {
+        /** */
+        private static final long serialVersionUID = 0L;
+
+        /** */
+        private final FileIOFactory delegateFactory = new RandomAccessFileIOFactory();
+
+        /** {@inheritDoc} */
+        @Override public FileIO create(File file, OpenOption... modes) throws IOException {
+            FileIO fileIO = delegateFactory.create(file, modes);
+
+            return new FileIODecorator(fileIO) {
+                @Override public int write(ByteBuffer srcBuf, long position) throws IOException {
+                    int type = PageIO.getType(srcBuf);
+
+                    AbstractDataLeafIO dataLeafIO = null;
+
+                    if (type == PageIO.T_DATA_REF_LEAF)
+                        dataLeafIO = DataLeafIO.VERSIONS.latest();
+
+                    if (type == PageIO.T_DATA_REF_MVCC_LEAF)
+                        dataLeafIO = MvccDataLeafIO.VERSIONS.latest();
+
+                    if (dataLeafIO != null) {
+                        long pageAddr = GridUnsafe.bufferAddress(srcBuf);
+
+                        int itemIdx = dataLeafIO.getCount(pageAddr) - 1;
+
+                        linkRef.set(dataLeafIO.getLink(pageAddr, itemIdx));
+
+                        fileRef.set(file);
+                    }
+
+                    srcBuf.rewind();
+
+                    return super.write(srcBuf, position);
+                }
+            };
+        }
+    }
+}
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/FilteredWalIteratorTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/FilteredWalIteratorTest.java
new file mode 100644
index 0000000..0877661
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/FilteredWalIteratorTest.java
@@ -0,0 +1,214 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.persistence.wal.reader;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Random;
+import java.util.function.Predicate;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.internal.pagemem.FullPageId;
+import org.apache.ignite.internal.pagemem.wal.WALIterator;
+import org.apache.ignite.internal.pagemem.wal.WALPointer;
+import org.apache.ignite.internal.pagemem.wal.record.CheckpointRecord;
+import org.apache.ignite.internal.pagemem.wal.record.MetastoreDataRecord;
+import org.apache.ignite.internal.pagemem.wal.record.PageSnapshot;
+import org.apache.ignite.internal.pagemem.wal.record.WALRecord;
+import org.apache.ignite.internal.pagemem.wal.record.delta.PartitionMetaStateRecord;
+import org.apache.ignite.internal.processors.cache.persistence.wal.FileWALPointer;
+import org.apache.ignite.lang.IgniteBiTuple;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.mockito.Mockito;
+
+import static java.util.stream.Collectors.toList;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordPurpose.PHYSICAL;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.EXCHANGE;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.HEADER_RECORD;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.METASTORE_DATA_RECORD;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.PAGE_RECORD;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.PART_META_UPDATE_STATE;
+import static org.apache.ignite.internal.processors.cache.distributed.dht.topology.GridDhtPartitionState.OWNING;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.when;
+
+/**
+ *
+ */
+@RunWith(Parameterized.class)
+public class FilteredWalIteratorTest {
+    /** Count of different records sequence per filter. */
+    private static final int ITERATORS_COUNT_PER_FILTER = 20;
+    /** Count of records on one iterator. */
+    private static final int RECORDS_COUNT_IN_ITERATOR = 30;
+    /** **/
+    private static Random random = new Random();
+    /** **/
+    private static FileWALPointer ZERO_POINTER = new FileWALPointer(0, 0, 0);
+    /** **/
+    private static IgniteBiTuple<WALPointer, WALRecord> TEST_RECORD = new IgniteBiTuple<>(
+        ZERO_POINTER, new MetastoreDataRecord("key", new byte[0])
+    );
+
+    /** Customized iterator for test. */
+    private WALIterator mockedIter;
+    /** Iterator filter for test. */
+    private Predicate<IgniteBiTuple<WALPointer, WALRecord>> filter;
+    /** Expected result for iterator and filter. */
+    private List<IgniteBiTuple<WALPointer, WALRecord>> expRes;
+
+    /**
+     * @param nameOfCase Case name. It required only for printing test name.
+     * @param mockedIter Basic WAL iterator.
+     * @param filter Filter by which record should be filtered.
+     * @param expRes Expected record result.
+     */
+    public FilteredWalIteratorTest(
+        String nameOfCase,
+        WALIterator mockedIter,
+        Predicate<IgniteBiTuple<WALPointer, WALRecord>> filter,
+        List<IgniteBiTuple<WALPointer, WALRecord>> expRes) {
+        this.mockedIter = mockedIter;
+        this.filter = filter;
+        this.expRes = expRes;
+    }
+
+    /**
+     * @throws IgniteCheckedException If failed.
+     */
+    @Test
+    public void shouldReturnCorrectlyFilteredRecords() throws IgniteCheckedException {
+        FilteredWalIterator filteredIter = new FilteredWalIterator(mockedIter, filter);
+
+        List<IgniteBiTuple<WALPointer, WALRecord>> ans = new ArrayList<>();
+        try (WALIterator it = filteredIter) {
+            while (it.hasNext())
+                ans.add(it.next());
+        }
+
+        assertNotNull(ans);
+        assertEquals(expRes, ans);
+    }
+
+    /**
+     * @return Datas for test.
+     */
+    @Parameterized.Parameters(name = "{0} case â„–{index}")
+    public static Iterable<Object[]> providedTestData() {
+        ArrayList<Object[]> res = new ArrayList<>();
+
+        res.addAll(prepareTestCaseData("PhysicalFilter", r -> r.get2().type().purpose() == PHYSICAL));
+        res.addAll(prepareTestCaseData("CheckpointFilter", r -> r.get2() instanceof CheckpointRecord));
+
+        return res;
+    }
+
+    /**
+     * Prepare bunch of data given filter.
+     *
+     * @param testCaseName Human readable name of filter.
+     * @param filter Filter for test.
+     * @return Prepared data.
+     */
+    private static List<Object[]> prepareTestCaseData(
+        String testCaseName,
+        Predicate<IgniteBiTuple<WALPointer, WALRecord>> filter
+    ) {
+        ArrayList<Object[]> res = new ArrayList<>(ITERATORS_COUNT_PER_FILTER);
+
+        Boolean[] hasNextReturn = new Boolean[RECORDS_COUNT_IN_ITERATOR + 1];
+        Arrays.fill(hasNextReturn, true);
+        hasNextReturn[RECORDS_COUNT_IN_ITERATOR] = false;
+
+        for (int i = 0; i < ITERATORS_COUNT_PER_FILTER; i++) {
+            List<IgniteBiTuple<WALPointer, WALRecord>> tuples = randomRecords();
+
+            WALIterator mockedIter = Mockito.mock(WALIterator.class);
+            when(mockedIter.hasNext()).thenReturn(true, hasNextReturn);
+            when(mockedIter.next()).thenReturn(TEST_RECORD, tuples.toArray(new IgniteBiTuple[] {}));
+
+            res.add(new Object[] {testCaseName, mockedIter, filter, tuples.stream().filter(filter).collect(toList())});
+        }
+
+        return res;
+    }
+
+    /**
+     * @return Random records list for iteration.
+     */
+    private static List<IgniteBiTuple<WALPointer, WALRecord>> randomRecords() {
+        ArrayList<IgniteBiTuple<WALPointer, WALRecord>> res = new ArrayList<>(RECORDS_COUNT_IN_ITERATOR);
+
+        for (int i = 0; i < RECORDS_COUNT_IN_ITERATOR; i++)
+            res.add(randomRecord());
+
+        return res;
+    }
+
+    /**
+     * @return Random test record.
+     */
+    private static IgniteBiTuple<WALPointer, WALRecord> randomRecord() {
+        int recordId = random.nextInt(9);
+
+        switch (recordId) {
+            case 0:
+                return new IgniteBiTuple<>(ZERO_POINTER, new MetastoreDataRecord("key", new byte[0]));
+            case 1:
+                return new IgniteBiTuple<>(ZERO_POINTER, new CheckpointRecord(new FileWALPointer(5738, 0, 0)));
+            case 2:
+                return new IgniteBiTuple<>(ZERO_POINTER, new PageSnapshot(new FullPageId(1, 1), new byte[0], 10));
+            case 3:
+                return new IgniteBiTuple<>(ZERO_POINTER, new PartitionMetaStateRecord(1, 1, OWNING, 1));
+            case 4:
+                return new IgniteBiTuple<>(ZERO_POINTER, new CustomizeTypeRecord(METASTORE_DATA_RECORD));
+            case 5:
+                return new IgniteBiTuple<>(ZERO_POINTER, new CustomizeTypeRecord(PAGE_RECORD));
+            case 6:
+                return new IgniteBiTuple<>(ZERO_POINTER, new CustomizeTypeRecord(PART_META_UPDATE_STATE));
+            case 7:
+                return new IgniteBiTuple<>(ZERO_POINTER, new CustomizeTypeRecord(HEADER_RECORD));
+            case 8:
+                return new IgniteBiTuple<>(ZERO_POINTER, new CustomizeTypeRecord(EXCHANGE));
+        }
+
+        return null;
+    }
+
+    /**
+     * Test class for represent record with different type.
+     */
+    public static class CustomizeTypeRecord extends WALRecord {
+        /** **/
+        private final RecordType type;
+
+        /**
+         * @param type Custom type for this record.
+         */
+        public CustomizeTypeRecord(RecordType type) {
+            this.type = type;
+        }
+
+        /** {@inheritDoc} */
+        @Override public RecordType type() {
+            return type;
+        }
+    }
+}
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/wal/scanner/WalScannerTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/wal/scanner/WalScannerTest.java
new file mode 100644
index 0000000..84442c1
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/wal/scanner/WalScannerTest.java
@@ -0,0 +1,337 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.persistence.wal.scanner;
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.internal.pagemem.FullPageId;
+import org.apache.ignite.internal.pagemem.wal.WALIterator;
+import org.apache.ignite.internal.pagemem.wal.WALPointer;
+import org.apache.ignite.internal.pagemem.wal.record.CheckpointRecord;
+import org.apache.ignite.internal.pagemem.wal.record.MetastoreDataRecord;
+import org.apache.ignite.internal.pagemem.wal.record.PageSnapshot;
+import org.apache.ignite.internal.pagemem.wal.record.WALRecord;
+import org.apache.ignite.internal.pagemem.wal.record.delta.FixCountRecord;
+import org.apache.ignite.internal.pagemem.wal.record.delta.PartitionMetaStateRecord;
+import org.apache.ignite.internal.processors.cache.persistence.wal.FileWALPointer;
+import org.apache.ignite.internal.processors.cache.persistence.wal.reader.IgniteWalIteratorFactory;
+import org.apache.ignite.internal.processors.cache.persistence.wal.reader.IgniteWalIteratorFactory.IteratorParametersBuilder;
+import org.apache.ignite.internal.util.typedef.T2;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.lang.IgniteBiTuple;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import static junit.framework.TestCase.assertTrue;
+import static org.apache.ignite.internal.processors.cache.distributed.dht.topology.GridDhtPartitionState.OWNING;
+import static org.apache.ignite.internal.processors.cache.persistence.wal.reader.IgniteWalIteratorFactory.IteratorParametersBuilder.withIteratorParameters;
+import static org.apache.ignite.internal.processors.cache.persistence.wal.scanner.ScannerHandlers.printToFile;
+import static org.apache.ignite.internal.processors.cache.persistence.wal.scanner.ScannerHandlers.printToLog;
+import static org.apache.ignite.internal.processors.cache.persistence.wal.scanner.WalScanner.buildWalScanner;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+/**
+ *
+ */
+public class WalScannerTest {
+    /** **/
+    private static final String TEST_DUMP_FILE = "output.txt";
+    /** **/
+    private static FileWALPointer ZERO_POINTER = new FileWALPointer(0, 0, 0);
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void shouldFindCorrectRecords() throws Exception {
+        // given: Iterator with random value and value which should be find by scanner.
+        long expPageId = 984;
+        int grpId = 123;
+
+        PageSnapshot expPageSnapshot = new PageSnapshot(new FullPageId(expPageId, grpId), new byte[0], 10);
+        CheckpointRecord expCheckpoint = new CheckpointRecord(new FileWALPointer(5738, 0, 0));
+        FixCountRecord expDeltaPage = new FixCountRecord(grpId, expPageId, 4);
+
+        WALIterator mockedIter = mockWalIterator(
+            new IgniteBiTuple<>(ZERO_POINTER, expPageSnapshot),
+            new IgniteBiTuple<>(ZERO_POINTER, new PageSnapshot(new FullPageId(455, grpId), new byte[0], 10)),
+            new IgniteBiTuple<>(ZERO_POINTER, expCheckpoint),
+            new IgniteBiTuple<>(ZERO_POINTER, new MetastoreDataRecord("key", new byte[0])),
+            new IgniteBiTuple<>(ZERO_POINTER, new PartitionMetaStateRecord(grpId, 1, OWNING, 1)),
+            new IgniteBiTuple<>(ZERO_POINTER, expDeltaPage),
+            new IgniteBiTuple<>(ZERO_POINTER, new FixCountRecord(grpId, 98348, 4))
+        );
+
+        IgniteWalIteratorFactory mockedFactory = mock(IgniteWalIteratorFactory.class);
+        when(mockedFactory.iterator(any(IteratorParametersBuilder.class))).thenReturn(mockedIter);
+
+        // Test scanner handler for holding found value instead of printing its.
+        List<WALRecord> holder = new ArrayList<>();
+        ScannerHandler recordCaptor = (rec) -> holder.add(rec.get2());
+
+        Set<T2<Integer,Long>> groupAndPageIds = new HashSet<>();
+
+        groupAndPageIds.add(new T2<>(grpId, expPageId));
+
+        // when: Scanning WAL for searching expected page.
+        buildWalScanner(withIteratorParameters(), mockedFactory)
+            .findAllRecordsFor(groupAndPageIds)
+            .forEach(recordCaptor);
+
+        // then: Should be find only expected value.
+        assertEquals(holder.size(), 3);
+
+        assertEquals(expPageSnapshot, holder.get(0));
+        assertEquals(expCheckpoint, holder.get(1));
+        assertEquals(expDeltaPage, holder.get(2));
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void shouldFindCorrectRecordsForMoreThanOnePages() throws Exception {
+        // given: Iterator with random value and value which should be find by scanner with several ids.
+        long expPageId1 = 984;
+        long expPageId2 = 9584;
+        long expPageId3 = 98344;
+
+        int grpId = 123;
+
+        PageSnapshot expPageSnapshot = new PageSnapshot(new FullPageId(expPageId1, grpId), new byte[0], 10);
+        CheckpointRecord expCheckpoint = new CheckpointRecord(new FileWALPointer(5738, 0, 0));
+        FixCountRecord expDeltaPage1 = new FixCountRecord(grpId, expPageId2, 4);
+        FixCountRecord expDeltaPage2 = new FixCountRecord(grpId, expPageId3, 4);
+
+        WALIterator mockedIter = mockWalIterator(
+            new IgniteBiTuple<>(ZERO_POINTER, expPageSnapshot),
+            new IgniteBiTuple<>(ZERO_POINTER, new PageSnapshot(new FullPageId(455, grpId), new byte[0], 10)),
+            new IgniteBiTuple<>(ZERO_POINTER, expCheckpoint),
+            new IgniteBiTuple<>(ZERO_POINTER, new MetastoreDataRecord("key", new byte[0])),
+            new IgniteBiTuple<>(ZERO_POINTER, new PartitionMetaStateRecord(grpId, 1, OWNING, 1)),
+            new IgniteBiTuple<>(ZERO_POINTER, expDeltaPage1),
+            new IgniteBiTuple<>(ZERO_POINTER, new FixCountRecord(grpId, 98348, 4)),
+            new IgniteBiTuple<>(ZERO_POINTER, new PartitionMetaStateRecord(grpId, 1, OWNING, 1)),
+            new IgniteBiTuple<>(ZERO_POINTER, expDeltaPage2)
+        );
+
+        IgniteWalIteratorFactory mockedFactory = mock(IgniteWalIteratorFactory.class);
+        when(mockedFactory.iterator(any(IteratorParametersBuilder.class))).thenReturn(mockedIter);
+
+        List<WALRecord> holder = new ArrayList<>();
+        ScannerHandler recordCaptor = (rec) -> holder.add(rec.get2());
+
+        Set<T2<Integer,Long>> groupAndPageIds = new HashSet<>();
+
+        groupAndPageIds.add(new T2<>(grpId, expPageId1));
+        groupAndPageIds.add(new T2<>(grpId, expPageId2));
+        groupAndPageIds.add(new T2<>(grpId, expPageId3));
+
+        // when: Scanning WAL for searching expected page.
+        buildWalScanner(withIteratorParameters(), mockedFactory)
+            .findAllRecordsFor(groupAndPageIds)
+            .forEach(recordCaptor);
+
+        // then: Should be find only expected value.
+        assertEquals(4, holder.size());
+
+        assertEquals(expPageSnapshot, holder.get(0));
+        assertEquals(expCheckpoint, holder.get(1));
+        assertEquals(expDeltaPage1, holder.get(2));
+        assertEquals(expDeltaPage2, holder.get(3));
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void shouldDumpToLogFoundRecord() throws Exception {
+        // given: Test logger for interception of logging.
+        long expPageId = 984;
+        int grpId = 123;
+
+        IgniteLogger log = mock(IgniteLogger.class);
+
+        ArgumentCaptor<String> valCapture = ArgumentCaptor.forClass(String.class);
+        doNothing().when(log).info(valCapture.capture());
+
+        WALIterator mockedIter = mockWalIterator(
+            new IgniteBiTuple<>(ZERO_POINTER, new PageSnapshot(new FullPageId(expPageId, grpId), new byte[0], 10)),
+            new IgniteBiTuple<>(ZERO_POINTER, new CheckpointRecord(new FileWALPointer(5738, 0, 0))),
+            new IgniteBiTuple<>(ZERO_POINTER, new FixCountRecord(grpId, expPageId, 4))
+        );
+
+        IgniteWalIteratorFactory factory = mock(IgniteWalIteratorFactory.class);
+        when(factory.iterator(any(IteratorParametersBuilder.class))).thenReturn(mockedIter);
+
+        Set<T2<Integer,Long>> groupAndPageIds = new HashSet<>();
+
+        groupAndPageIds.add(new T2<>(grpId, expPageId));
+
+        // when: Scanning WAL for searching expected page.
+        buildWalScanner(withIteratorParameters(), factory)
+            .findAllRecordsFor(groupAndPageIds)
+            .forEach(printToLog(log));
+
+        // then: Should be find only expected value from log.
+        List<String> actualRecords = valCapture.getAllValues();
+
+        assertEquals(actualRecords.size(), 1);
+
+        assertTrue(actualRecords.get(0), actualRecords.get(0).contains("PageSnapshot ["));
+        assertTrue(actualRecords.get(0), actualRecords.get(0).contains("CheckpointRecord ["));
+        assertTrue(actualRecords.get(0), actualRecords.get(0).contains("FixCountRecord ["));
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void shouldDumpToFileFoundRecord() throws Exception {
+        // given: File for dumping records.
+        File targetFile = Paths.get(U.defaultWorkDirectory(), TEST_DUMP_FILE).toFile();
+
+        long expectedPageId = 984;
+        int grpId = 123;
+
+        WALIterator mockedIter = mockWalIterator(
+            new IgniteBiTuple<>(ZERO_POINTER, new PageSnapshot(new FullPageId(expectedPageId, grpId), new byte[0], 10)),
+            new IgniteBiTuple<>(ZERO_POINTER, new CheckpointRecord(new FileWALPointer(5738, 0, 0))),
+            new IgniteBiTuple<>(ZERO_POINTER, new FixCountRecord(grpId, expectedPageId, 4))
+        );
+
+        IgniteWalIteratorFactory factory = mock(IgniteWalIteratorFactory.class);
+        when(factory.iterator(any(IteratorParametersBuilder.class))).thenReturn(mockedIter);
+
+        Set<T2<Integer,Long>> groupAndPageIds = new HashSet<>();
+
+        groupAndPageIds.add(new T2<>(grpId, expectedPageId));
+
+        List<String> actualRecords;
+
+        try {
+            // when: Scanning WAL for searching expected page.
+            buildWalScanner(withIteratorParameters(), factory)
+                .findAllRecordsFor(groupAndPageIds)
+                .forEach(printToFile(targetFile));
+
+            actualRecords = Files.readAllLines(targetFile.toPath());
+        }
+        finally {
+            targetFile.delete();
+        }
+
+        // then: Should be find only expected value from file.
+        assertEquals(actualRecords.size(), 3);
+
+        assertTrue(actualRecords.get(0), actualRecords.get(0).contains("PageSnapshot ["));
+        assertTrue(actualRecords.get(1), actualRecords.get(1).contains("CheckpointRecord ["));
+        assertTrue(actualRecords.get(2), actualRecords.get(2).contains("FixCountRecord ["));
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void shouldDumpToFileAndLogFoundRecord() throws Exception {
+        // given: File for dumping records and test logger for interception of records.
+        File targetFile = Paths.get(U.defaultWorkDirectory(), TEST_DUMP_FILE).toFile();
+
+        long expPageId = 984;
+        int grpId = 123;
+
+        IgniteLogger log = mock(IgniteLogger.class);
+
+        ArgumentCaptor<String> valCapture = ArgumentCaptor.forClass(String.class);
+        doNothing().when(log).info(valCapture.capture());
+
+        WALIterator mockedIter = mockWalIterator(
+            new IgniteBiTuple<>(ZERO_POINTER, new PageSnapshot(new FullPageId(expPageId, grpId), new byte[0], 10)),
+            new IgniteBiTuple<>(ZERO_POINTER, new CheckpointRecord(new FileWALPointer(5738, 0, 0))),
+            new IgniteBiTuple<>(ZERO_POINTER, new FixCountRecord(grpId, expPageId, 4))
+        );
+
+        IgniteWalIteratorFactory factory = mock(IgniteWalIteratorFactory.class);
+        when(factory.iterator(any(IteratorParametersBuilder.class))).thenReturn(mockedIter);
+
+        Set<T2<Integer,Long>> groupAndPageIds = new HashSet<>();
+
+        groupAndPageIds.add(new T2<>(grpId, expPageId));
+
+        List<String> actualFileRecords = null;
+
+        try {
+            // when: Scanning WAL for searching expected page.
+            buildWalScanner(withIteratorParameters(), factory)
+                .findAllRecordsFor(groupAndPageIds)
+                .forEach(printToLog(log).andThen(printToFile(targetFile)));
+
+            actualFileRecords = Files.readAllLines(targetFile.toPath());
+        }
+        finally {
+            targetFile.delete();
+        }
+
+        // then: Should be find only expected value from file.
+        assertEquals(actualFileRecords.size(), 3);
+
+        assertTrue(actualFileRecords.get(0), actualFileRecords.get(0).contains("PageSnapshot ["));
+        assertTrue(actualFileRecords.get(1), actualFileRecords.get(1).contains("CheckpointRecord ["));
+        assertTrue(actualFileRecords.get(2), actualFileRecords.get(2).contains("FixCountRecord ["));
+
+        // then: Should be find only expected value from log.
+        List<String> actualLogRecords = valCapture.getAllValues();
+
+        assertEquals(actualLogRecords.size(), 1);
+
+        assertTrue(actualLogRecords.get(0), actualLogRecords.get(0).contains("PageSnapshot ["));
+        assertTrue(actualLogRecords.get(0), actualLogRecords.get(0).contains("CheckpointRecord ["));
+        assertTrue(actualLogRecords.get(0), actualLogRecords.get(0).contains("FixCountRecord ["));
+    }
+
+    /**
+     * @param first Not null first value for return.
+     * @param tail Other values.
+     * @return Mocked WAL iterator.
+     */
+    private WALIterator mockWalIterator(
+        IgniteBiTuple<WALPointer, WALRecord> first,
+        IgniteBiTuple<WALPointer, WALRecord>... tail
+    ) {
+        Boolean[] hasNextReturn = new Boolean[tail.length + 1];
+        Arrays.fill(hasNextReturn, true);
+        hasNextReturn[tail.length] = false;
+
+        WALIterator mockedIter = mock(WALIterator.class);
+        when(mockedIter.hasNext()).thenReturn(true, hasNextReturn);
+
+        when(mockedIter.next()).thenReturn(first, tail);
+
+        return mockedIter;
+    }
+}
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/diagnostic/DiagnosticProcessorTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/diagnostic/DiagnosticProcessorTest.java
new file mode 100644
index 0000000..87ac685
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/diagnostic/DiagnosticProcessorTest.java
@@ -0,0 +1,269 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.diagnostic;
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
+import java.util.List;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.IgniteDataStreamer;
+import org.apache.ignite.configuration.DataRegionConfiguration;
+import org.apache.ignite.configuration.DataStorageConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.pagemem.wal.WALIterator;
+import org.apache.ignite.internal.pagemem.wal.record.PageSnapshot;
+import org.apache.ignite.internal.pagemem.wal.record.WALRecord;
+import org.apache.ignite.internal.processors.cache.persistence.file.RandomAccessFileIO;
+import org.apache.ignite.internal.processors.cache.persistence.wal.io.SegmentIO;
+import org.apache.ignite.internal.processors.cache.persistence.wal.io.SimpleSegmentFileInputFactory;
+import org.apache.ignite.internal.processors.cache.persistence.wal.reader.IgniteWalIteratorFactory;
+import org.apache.ignite.internal.processors.cache.persistence.wal.reader.IgniteWalIteratorFactory.IteratorParametersBuilder;
+import org.apache.ignite.internal.processors.cache.persistence.wal.serializer.RecordSerializerFactory;
+import org.apache.ignite.internal.processors.cache.persistence.wal.serializer.RecordV1Serializer;
+import org.apache.ignite.internal.processors.cache.persistence.wal.serializer.SegmentHeader;
+import org.apache.ignite.internal.util.typedef.T2;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.junit.Test;
+
+import static org.apache.ignite.internal.processors.diagnostic.DiagnosticProcessor.DEFAULT_TARGET_FOLDER;
+import static org.apache.ignite.internal.processors.diagnostic.DiagnosticProcessor.DiagnosticAction.PRINT_TO_FILE;
+import static org.apache.ignite.internal.processors.diagnostic.DiagnosticProcessor.DiagnosticAction.PRINT_TO_LOG;
+import static org.apache.ignite.internal.processors.diagnostic.DiagnosticProcessor.DiagnosticAction.PRINT_TO_RAW_FILE;
+import static org.apache.ignite.internal.processors.diagnostic.DiagnosticProcessor.FILE_FORMAT;
+import static org.apache.ignite.internal.processors.diagnostic.DiagnosticProcessor.RAW_FILE_FORMAT;
+
+/**
+ *
+ */
+public class DiagnosticProcessorTest extends GridCommonAbstractTest {
+    /** Cache name. */
+    private static final String CACHE_NAME = "cache0";
+    /** Test directory for dump. */
+    private static final String TEST_DUMP_PAGE_FILE = "testDumpPage";
+
+    /** One time configured diagnosticProcessor. */
+    private static DiagnosticProcessor diagnosticProcessor;
+    /** One time configured page id for searching. */
+    private static T2<Integer, Long> expectedPageId;
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(gridName);
+
+        DataStorageConfiguration dsCfg = new DataStorageConfiguration()
+            .setDefaultDataRegionConfiguration(
+                new DataRegionConfiguration()
+                    .setMaxSize(1024L * 1024 * 1024)
+                    .setPersistenceEnabled(true));
+
+        cfg.setDataStorageConfiguration(dsCfg);
+
+        return cfg;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        super.beforeTestsStarted();
+
+        stopAllGrids();
+
+        cleanPersistenceDir();
+
+        try {
+            IgniteEx ignite = startGrid("node0");
+
+            ignite.cluster().active(true);
+
+            ignite.createCache(CACHE_NAME);
+            try (IgniteDataStreamer<Integer, Integer> st = ignite.dataStreamer(CACHE_NAME)) {
+                st.allowOverwrite(true);
+
+                for (int i = 0; i < 10_000; i++)
+                    st.addData(i, i);
+            }
+
+            diagnosticProcessor = ignite.context().diagnostic();
+            expectedPageId = findAnyPageId();
+        }
+        finally {
+            stopAllGrids();
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        super.afterTest();
+
+        U.delete(U.resolveWorkDirectory(U.defaultWorkDirectory(), DEFAULT_TARGET_FOLDER, false));
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTestsStopped() throws Exception {
+        super.afterTestsStopped();
+
+        diagnosticProcessor = null;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void dumpPageHistoryToDefaultDir() throws Exception {
+        diagnosticProcessor.dumpPageHistory(new PageHistoryDiagnoster.DiagnosticPageBuilder()
+            .pageIds(expectedPageId)
+            .addAction(PRINT_TO_LOG)
+            .addAction(PRINT_TO_FILE)
+        );
+
+        Path path = Paths.get(U.defaultWorkDirectory(), DEFAULT_TARGET_FOLDER);
+        File dumpFile = path.toFile().listFiles((dir, name) -> name.endsWith(FILE_FORMAT))[0];
+
+        List<String> records = Files.readAllLines(dumpFile.toPath());
+
+        assertTrue(!records.isEmpty());
+
+        assertTrue(records.stream().anyMatch(line -> line.contains("CheckpointRecord")));
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void dumpRawPageHistoryToDefaultDir() throws Exception {
+        diagnosticProcessor.dumpPageHistory(new PageHistoryDiagnoster.DiagnosticPageBuilder()
+            .pageIds(expectedPageId)
+            .addAction(PRINT_TO_RAW_FILE)
+        );
+
+        Path path = Paths.get(U.defaultWorkDirectory(), DEFAULT_TARGET_FOLDER);
+        File dumpFile = path.toFile().listFiles((dir, name) -> name.endsWith(RAW_FILE_FORMAT))[0];
+
+        try (SegmentIO io = new SegmentIO(0L, new RandomAccessFileIO(dumpFile, StandardOpenOption.READ))) {
+            SegmentHeader hdr = RecordV1Serializer.readSegmentHeader(io, new SimpleSegmentFileInputFactory());
+
+            assertFalse(hdr.isCompacted());
+
+            assertEquals(RecordSerializerFactory.LATEST_SERIALIZER_VERSION, hdr.getSerializerVersion());
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void dumpPageHistoryToCustomAbsoluteDir() throws Exception {
+        Path path = Paths.get(U.defaultWorkDirectory(), TEST_DUMP_PAGE_FILE);
+        try {
+            diagnosticProcessor.dumpPageHistory(new PageHistoryDiagnoster.DiagnosticPageBuilder()
+                .pageIds(expectedPageId)
+                .folderForDump(path.toFile())
+                .addAction(PRINT_TO_FILE)
+            );
+
+            File dumpFile = path.toFile().listFiles((dir, name) -> name.endsWith(FILE_FORMAT))[0];
+
+            List<String> records = Files.readAllLines(dumpFile.toPath());
+
+            assertTrue(!records.isEmpty());
+
+            assertTrue(records.stream().anyMatch(line -> line.contains("CheckpointRecord")));
+        }
+        finally {
+            U.delete(U.resolveWorkDirectory(U.defaultWorkDirectory(), TEST_DUMP_PAGE_FILE, false));
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void dumpPageHistoryToCustomRelativeDir() throws Exception {
+        Path path = Paths.get(U.defaultWorkDirectory(), DEFAULT_TARGET_FOLDER, TEST_DUMP_PAGE_FILE);
+
+        diagnosticProcessor.dumpPageHistory(new PageHistoryDiagnoster.DiagnosticPageBuilder()
+            .pageIds(expectedPageId)
+            .folderForDump(new File(TEST_DUMP_PAGE_FILE))
+            .addAction(PRINT_TO_FILE)
+        );
+
+        File dumpFile = path.toFile().listFiles((dir, name) -> name.endsWith(FILE_FORMAT))[0];
+
+        List<String> records = Files.readAllLines(dumpFile.toPath());
+
+        assertTrue(!records.isEmpty());
+
+        assertTrue(records.stream().anyMatch(line -> line.contains("CheckpointRecord")));
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void dumpOnlyCheckpointRecordBecausePageIdNotSet() throws Exception {
+        diagnosticProcessor.dumpPageHistory(new PageHistoryDiagnoster.DiagnosticPageBuilder()
+            .addAction(PRINT_TO_LOG)
+            .addAction(PRINT_TO_FILE)
+        );
+
+        Path path = Paths.get(U.defaultWorkDirectory(), DEFAULT_TARGET_FOLDER);
+
+        File dumpFile = path.toFile().listFiles((dir, name) -> name.endsWith(FILE_FORMAT))[0];
+
+        List<String> records = Files.readAllLines(dumpFile.toPath());
+
+        assertTrue(records.stream().allMatch(line -> line.contains("CheckpointRecord")));
+    }
+
+    /**
+     * @throws IgniteCheckedException If failed.
+     */
+    @Test(expected = NullPointerException.class)
+    public void throwExceptionBecauseNotAnyActionsWasSet() throws IgniteCheckedException {
+        diagnosticProcessor.dumpPageHistory(new PageHistoryDiagnoster.DiagnosticPageBuilder()
+            .pageIds(expectedPageId)
+        );
+    }
+
+    /**
+     * Find first any page id for test.
+     *
+     * @return Page id in WAL.
+     * @throws org.apache.ignite.IgniteCheckedException If failed.
+     */
+    private T2<Integer, Long> findAnyPageId() throws org.apache.ignite.IgniteCheckedException {
+        IgniteWalIteratorFactory factory = new IgniteWalIteratorFactory();
+
+        try (WALIterator it = factory.iterator(new IteratorParametersBuilder().filesOrDirs(U.defaultWorkDirectory()))) {
+            while (it.hasNext()) {
+                WALRecord record = it.next().get2();
+
+                if (record instanceof PageSnapshot){
+                    PageSnapshot rec = (PageSnapshot)record;
+
+                    return new T2<>(rec.groupId(), rec.fullPageId().pageId());
+                }
+            }
+        }
+
+        throw new IgniteCheckedException();
+    }
+}
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePdsTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePdsTestSuite.java
index 57472e0..f9c1686 100644
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePdsTestSuite.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePdsTestSuite.java
@@ -56,6 +56,7 @@ import org.apache.ignite.internal.processors.database.IgniteDbMultiNodePutGetTes
 import org.apache.ignite.internal.processors.database.IgniteDbPutGetWithCacheStoreTest;
 import org.apache.ignite.internal.processors.database.IgniteDbSingleNodePutGetTest;
 import org.apache.ignite.internal.processors.database.IgniteDbSingleNodeTinyPutGetTest;
+import org.apache.ignite.internal.processors.diagnostic.DiagnosticProcessorTest;
 import org.apache.ignite.testframework.GridTestUtils;
 import org.junit.runner.RunWith;
 import org.junit.runners.AllTests;
@@ -179,5 +180,8 @@ public class IgnitePdsTestSuite {
 
         //MetaStorage
         GridTestUtils.addTestIfNeeded(suite, IgniteMetaStorageBasicTest.class, ignoredTests);
+
+        //Diagnostic
+        GridTestUtils.addTestIfNeeded(suite, DiagnosticProcessorTest.class, ignoredTests);
     }
 }
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePdsTestSuite2.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePdsTestSuite2.java
index bd6c3fc..1cc6393 100644
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePdsTestSuite2.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePdsTestSuite2.java
@@ -73,7 +73,9 @@ import org.apache.ignite.internal.processors.cache.persistence.db.wal.crc.Ignite
 import org.apache.ignite.internal.processors.cache.persistence.db.wal.crc.IgniteStandaloneWalIteratorInvalidCrcTest;
 import org.apache.ignite.internal.processors.cache.persistence.db.wal.crc.IgniteWithoutArchiverWalIteratorInvalidCrcTest;
 import org.apache.ignite.internal.processors.cache.persistence.db.wal.reader.IgniteWalReaderTest;
+import org.apache.ignite.internal.processors.cache.persistence.wal.reader.FilteredWalIteratorTest;
 import org.apache.ignite.internal.processors.cache.persistence.wal.reader.StandaloneWalRecordsIteratorTest;
+import org.apache.ignite.internal.processors.cache.persistence.wal.scanner.WalScannerTest;
 import org.apache.ignite.testframework.GridTestUtils;
 import org.junit.runner.RunWith;
 import org.junit.runners.AllTests;
@@ -217,6 +219,10 @@ public class IgnitePdsTestSuite2 extends TestSuite {
 
         GridTestUtils.addTestIfNeeded(suite, StandaloneWalRecordsIteratorTest.class, ignoredTests);
 
+        GridTestUtils.addTestIfNeeded(suite, FilteredWalIteratorTest.class, ignoredTests);
+
+        GridTestUtils.addTestIfNeeded(suite, WalScannerTest.class, ignoredTests);
+
         //GridTestUtils.addTestIfNeeded(suite, IgniteWalRecoverySeveralRestartsTest.class, ignoredTests);
 
         GridTestUtils.addTestIfNeeded(suite, IgniteRebalanceScheduleResendPartitionsTest.class, ignoredTests);
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePdsTestSuite4.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePdsTestSuite4.java
index 248f8ca..c199c3c 100644
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePdsTestSuite4.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePdsTestSuite4.java
@@ -22,6 +22,7 @@ import org.apache.ignite.cache.ResetLostPartitionTest;
 import org.apache.ignite.internal.processors.cache.IgniteClusterActivateDeactivateTestWithPersistenceAndMemoryReuse;
 import org.apache.ignite.internal.processors.cache.distributed.CachePageWriteLockUnlockTest;
 import org.apache.ignite.internal.processors.cache.distributed.rebalancing.IgniteRebalanceOnCachesStoppingOrDestroyingTest;
+import org.apache.ignite.internal.processors.cache.persistence.CorruptedTreeFailureHandlingTest;
 import org.apache.ignite.internal.processors.cache.persistence.IgnitePdsContinuousRestartTestWithSharedGroupAndIndexes;
 import org.apache.ignite.internal.processors.cache.persistence.IgnitePdsRecoveryAfterFileCorruptionTest;
 import org.apache.ignite.internal.processors.cache.persistence.IgnitePdsTaskCancelingTest;
@@ -65,6 +66,7 @@ public class IgnitePdsTestSuite4 {
         GridTestUtils.addTestIfNeeded(suite, CachePageWriteLockUnlockTest.class, ignoredTests);
         GridTestUtils.addTestIfNeeded(suite, IgnitePdsCacheWalDisabledOnRebalancingTest.class, ignoredTests);
         GridTestUtils.addTestIfNeeded(suite, IgnitePdsStartWIthEmptyArchive.class, ignoredTests);
+        GridTestUtils.addTestIfNeeded(suite, CorruptedTreeFailureHandlingTest.class, ignoredTests);
 
         return suite;
     }
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/visor/verify/ValidateIndexesClosure.java b/modules/indexing/src/main/java/org/apache/ignite/internal/visor/verify/ValidateIndexesClosure.java
index a015a46..ee8d557 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/visor/verify/ValidateIndexesClosure.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/visor/verify/ValidateIndexesClosure.java
@@ -54,6 +54,7 @@ import org.apache.ignite.internal.processors.cache.persistence.DbCheckpointListe
 import org.apache.ignite.internal.processors.cache.persistence.GridCacheDatabaseSharedManager;
 import org.apache.ignite.internal.processors.cache.persistence.IgniteCacheDatabaseSharedManager;
 import org.apache.ignite.internal.processors.cache.persistence.file.FilePageStoreManager;
+import org.apache.ignite.internal.processors.cache.persistence.tree.CorruptedTreeException;
 import org.apache.ignite.internal.processors.cache.verify.GridNotIdleException;
 import org.apache.ignite.internal.processors.cache.verify.IdleVerifyUtility;
 import org.apache.ignite.internal.processors.cache.verify.PartitionKey;
@@ -68,6 +69,7 @@ import org.apache.ignite.internal.processors.query.h2.opt.GridH2Table;
 import org.apache.ignite.internal.util.lang.GridIterator;
 import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.T2;
+import org.apache.ignite.internal.util.typedef.X;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.lang.IgniteCallable;
 import org.apache.ignite.resources.IgniteInstanceResource;
@@ -75,6 +77,7 @@ import org.apache.ignite.resources.LoggerResource;
 import org.h2.engine.Session;
 import org.h2.index.Cursor;
 import org.h2.index.Index;
+import org.h2.message.DbException;
 
 import static org.apache.ignite.internal.pagemem.PageIdAllocator.FLAG_IDX;
 import static org.apache.ignite.internal.pagemem.PageIdAllocator.INDEX_PARTITION;
@@ -673,10 +676,15 @@ public class ValidateIndexesClosure implements IgniteCallable<VisorValidateIndex
                     if (!cursor.next())
                         break;
                 }
-                catch (IllegalStateException e) {
-                    throw new IgniteCheckedException("Key is present in SQL index, but is missing in corresponding " +
-                        "data page. Previous successfully read key: " +
-                        CacheObjectUtils.unwrapBinaryIfNeeded(ctx.cacheObjectContext(), previousKey, true, true), e);
+                catch (DbException e) {
+                    if (X.hasCause(e, CorruptedTreeException.class))
+                        throw new IgniteCheckedException("Key is present in SQL index, but is missing in corresponding " +
+                            "data page. Previous successfully read key: " +
+                            CacheObjectUtils.unwrapBinaryIfNeeded(ctx.cacheObjectContext(), previousKey, true, true),
+                            X.cause(e, CorruptedTreeException.class)
+                        );
+
+                    throw e;
                 }
 
                 GridH2Row h2Row = (GridH2Row)cursor.get();


[ignite] 15/31: IGNITE-1090 Fixed GridCachePartitionedOptimisticTxNodeRestartTest - Fixes #6140.

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch gg-19225
in repository https://gitbox.apache.org/repos/asf/ignite.git

commit bf3a7023684fca3d3acbcfd8a3770264129a495c
Author: Alexey Goncharuk <al...@gmail.com>
AuthorDate: Fri Mar 22 13:34:58 2019 +0300

    IGNITE-1090 Fixed GridCachePartitionedOptimisticTxNodeRestartTest - Fixes #6140.
    
    Signed-off-by: Alexey Goncharuk <al...@gmail.com>
    
    (cherry picked from commit 5307b0a)
---
 .../ignite/internal/processors/cache/GridCacheMvcc.java      |  5 +++--
 .../cache/distributed/GridDistributedCacheEntry.java         |  2 +-
 .../processors/cache/transactions/IgniteTxHandler.java       |  6 ++++--
 .../processors/cache/transactions/IgniteTxManager.java       |  5 +----
 .../internal/processors/cache/GridCacheTestEntryEx.java      |  2 +-
 .../GridCachePartitionedOptimisticTxNodeRestartTest.java     | 12 +++---------
 .../distributed/near/NearCacheMultithreadedUpdateTest.java   |  2 +-
 .../ignite/testsuites/IgniteCacheRestartTestSuite.java       |  8 +++++---
 8 files changed, 19 insertions(+), 23 deletions(-)

diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvcc.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvcc.java
index d822eae..5464bf4 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvcc.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvcc.java
@@ -974,8 +974,9 @@ public final class GridCacheMvcc {
      * as system invalidate and marks these candidates as owned and used.
      *
      * @param ver Version to salvage.
+     * @param near {@code True} If salvage near cache candidate.
      */
-    public void salvageRemote(GridCacheVersion ver) {
+    public void salvageRemote(GridCacheVersion ver, boolean near) {
         assert ver != null;
 
         GridCacheMvccCandidate cand = candidate(rmts, ver);
@@ -994,7 +995,7 @@ public final class GridCacheMvcc {
                 // Only Near and DHT remote candidates should be released.
                 assert !rmt.nearLocal();
 
-                IgniteInternalTx tx = cctx.tm().tx(rmt.version());
+                IgniteInternalTx tx = near ? cctx.tm().nearTx(rmt.version()) : cctx.tm().tx(rmt.version());
 
                 if (tx != null) {
                     tx.systemInvalidate(true);
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedCacheEntry.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedCacheEntry.java
index eeaea97..d948f47 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedCacheEntry.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedCacheEntry.java
@@ -613,7 +613,7 @@ public class GridDistributedCacheEntry extends GridCacheMapEntry {
                 }
 
                 if (sysInvalidate && baseVer != null)
-                    mvcc.salvageRemote(baseVer);
+                    mvcc.salvageRemote(baseVer, isNear());
 
                 owner = mvcc.doneRemote(lockVer,
                     maskNull(pendingVers),
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxHandler.java
index 8f5f642..106b910 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxHandler.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxHandler.java
@@ -1431,8 +1431,10 @@ public class IgniteTxHandler {
         try {
             if (req.commit() || req.isSystemInvalidate()) {
                 tx.commitVersion(req.commitVersion());
-                tx.invalidate(req.isInvalidate());
-                tx.systemInvalidate(req.isSystemInvalidate());
+                if (req.isInvalidate())
+                    tx.invalidate(true);
+                if (req.isSystemInvalidate())
+                    tx.systemInvalidate(true);
                 tx.mvccSnapshot(req.mvccSnapshot());
 
                 // Complete remote candidates.
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxManager.java
index 817ff27..4230125 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxManager.java
@@ -1658,10 +1658,7 @@ public class IgniteTxManager extends GridCacheSharedManagerAdapter {
     public boolean onOwnerChanged(GridCacheEntryEx entry, GridCacheMvccCandidate owner) {
         // We only care about acquired locks.
         if (owner != null) {
-            IgniteTxAdapter tx = tx(owner.version());
-
-            if (tx == null)
-                tx = nearTx(owner.version());
+            IgniteTxAdapter tx = entry.isNear() ? nearTx(owner.version()) : tx(owner.version());
 
             if (tx != null) {
                 if (!tx.local()) {
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheTestEntryEx.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheTestEntryEx.java
index 60f15b2..551978d 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheTestEntryEx.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheTestEntryEx.java
@@ -213,7 +213,7 @@ public class GridCacheTestEntryEx extends GridMetadataAwareAdapter implements Gr
      * @param baseVer Base version.
      */
     void salvageRemote(GridCacheVersion baseVer) {
-        mvcc.salvageRemote(baseVer);
+        mvcc.salvageRemote(baseVer, false);
     }
 
     /**
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/GridCachePartitionedOptimisticTxNodeRestartTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/GridCachePartitionedOptimisticTxNodeRestartTest.java
index c72408e..11c303d 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/GridCachePartitionedOptimisticTxNodeRestartTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/GridCachePartitionedOptimisticTxNodeRestartTest.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
@@ -36,12 +36,6 @@ import static org.apache.ignite.transactions.TransactionConcurrency.OPTIMISTIC;
 @RunWith(JUnit4.class)
 public class GridCachePartitionedOptimisticTxNodeRestartTest extends GridCacheAbstractNodeRestartSelfTest {
     /** {@inheritDoc} */
-    @Override protected void beforeTest() throws Exception {
-        if (nearEnabled())
-            fail("https://issues.apache.org/jira/browse/IGNITE-1090");
-    }
-
-    /** {@inheritDoc} */
     @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
         IgniteConfiguration c = super.getConfiguration(igniteInstanceName);
 
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/NearCacheMultithreadedUpdateTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/NearCacheMultithreadedUpdateTest.java
index 6bfbc33..d66e827 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/NearCacheMultithreadedUpdateTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/NearCacheMultithreadedUpdateTest.java
@@ -45,7 +45,7 @@ public class NearCacheMultithreadedUpdateTest extends GridCommonAbstractTest {
     private boolean client;
 
     /** */
-    private final int SRV_CNT = 3;
+    private static final int SRV_CNT = 3;
 
     /** {@inheritDoc} */
     @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheRestartTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheRestartTestSuite.java
index ebc8c57..49154f2 100644
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheRestartTestSuite.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheRestartTestSuite.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
@@ -23,6 +23,7 @@ import org.apache.ignite.internal.processors.cache.distributed.IgniteCacheNearRe
 import org.apache.ignite.internal.processors.cache.distributed.dht.GridCachePartitionedNearDisabledOptimisticTxNodeRestartTest;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridCachePartitionedNodeRestartTest;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridCachePartitionedOptimisticTxNodeRestartTest;
+import org.apache.ignite.internal.processors.cache.distributed.near.NearCacheMultithreadedUpdateTest;
 import org.apache.ignite.internal.processors.cache.distributed.replicated.GridCacheReplicatedNodeRestartSelfTest;
 import org.junit.runner.RunWith;
 import org.junit.runners.AllTests;
@@ -43,6 +44,7 @@ public class IgniteCacheRestartTestSuite {
         suite.addTest(new JUnit4TestAdapter(GridCacheReplicatedNodeRestartSelfTest.class));
         suite.addTest(new JUnit4TestAdapter(GridCachePartitionedNearDisabledOptimisticTxNodeRestartTest.class));
         suite.addTest(new JUnit4TestAdapter(IgniteCacheNearRestartRollbackSelfTest.class));
+        suite.addTest(new JUnit4TestAdapter(NearCacheMultithreadedUpdateTest.class));
 
         suite.addTest(new JUnit4TestAdapter(IgniteCacheCreateRestartSelfTest.class));
 


[ignite] 14/31: GG-19160 GridDeploymentSelfTest#testRedeploy fails

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch gg-19225
in repository https://gitbox.apache.org/repos/asf/ignite.git

commit 2a32a34e4144e25d5a7a6a2f7e89267cbd82c083
Author: Eduard Shangareev <es...@gridgain.com>
AuthorDate: Fri May 31 03:32:55 2019 +0300

    GG-19160 GridDeploymentSelfTest#testRedeploy fails
---
 .../test/java/org/apache/ignite/internal/GridDeploymentSelfTest.java   | 2 +-
 .../internal/processors/service/ServiceDeploymentOnActivationTest.java | 3 ++-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/modules/core/src/test/java/org/apache/ignite/internal/GridDeploymentSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/GridDeploymentSelfTest.java
index f7b97c2..25a5bdb 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/GridDeploymentSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/GridDeploymentSelfTest.java
@@ -481,7 +481,7 @@ public class GridDeploymentSelfTest extends GridCommonAbstractTest {
 
         /** {@inheritDoc} */
         @Override public boolean register(ClassLoader ldr, Class rsrc) throws IgniteSpiException {
-            if (super.register(ldr, rsrc)) {
+            if (super.register(ldr, rsrc) && ComputeTaskAdapter.class.isAssignableFrom(rsrc)) {
                 deployCnt++;
 
                 return true;
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/service/ServiceDeploymentOnActivationTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/service/ServiceDeploymentOnActivationTest.java
index c674875..cce660d 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/service/ServiceDeploymentOnActivationTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/service/ServiceDeploymentOnActivationTest.java
@@ -28,6 +28,7 @@ import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.lang.IgnitePredicate;
 import org.apache.ignite.services.ServiceConfiguration;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -165,8 +166,8 @@ public class ServiceDeploymentOnActivationTest extends GridCommonAbstractTest {
      * @throws Exception If failed.
      */
     @Test
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-8279")
     public void testClientsStaticConfigWithoutPersistence() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-8279");
 
         persistence = false;
 


[ignite] 31/31: GG-19225: MVCC: Fix incorrect exception thrown.

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch gg-19225
in repository https://gitbox.apache.org/repos/asf/ignite.git

commit ba764c6c3edf14e499259090773f43f4a3ba52f6
Author: Andrey V. Mashenkov <an...@gmail.com>
AuthorDate: Wed Jun 5 14:07:49 2019 +0300

    GG-19225: MVCC: Fix incorrect exception thrown.
---
 .../cache/distributed/dht/NotMappedPartitionInTxTest.java     |  3 ---
 .../processors/query/h2/twostep/GridReduceQueryExecutor.java  | 11 ++++++-----
 2 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/NotMappedPartitionInTxTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/NotMappedPartitionInTxTest.java
index 75b6dd4..06d58ce 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/NotMappedPartitionInTxTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/NotMappedPartitionInTxTest.java
@@ -38,7 +38,6 @@ import org.apache.ignite.transactions.Transaction;
 import org.apache.ignite.transactions.TransactionConcurrency;
 import org.apache.ignite.transactions.TransactionIsolation;
 import org.jetbrains.annotations.Nullable;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -115,7 +114,6 @@ public class NotMappedPartitionInTxTest extends GridCommonAbstractTest {
     /**
      *
      */
-    @Ignore("https://issues.apache.org/jira/browse/IGNITE-10377")
     @Test
     public void testOneServerMvcc() throws Exception {
         try {
@@ -160,7 +158,6 @@ public class NotMappedPartitionInTxTest extends GridCommonAbstractTest {
     /**
      *
      */
-    @Ignore("https://issues.apache.org/jira/browse/IGNITE-10377")
     @Test
     public void testFourServersMvcc() throws Exception {
         try {
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridReduceQueryExecutor.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridReduceQueryExecutor.java
index 5c2c287..2a25263 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridReduceQueryExecutor.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridReduceQueryExecutor.java
@@ -47,6 +47,7 @@ import org.apache.ignite.IgniteClientDisconnectedException;
 import org.apache.ignite.IgniteException;
 import org.apache.ignite.IgniteLogger;
 import org.apache.ignite.IgniteSystemProperties;
+import org.apache.ignite.cache.CacheServerNotFoundException;
 import org.apache.ignite.cache.PartitionLossPolicy;
 import org.apache.ignite.cache.query.QueryCancelledException;
 import org.apache.ignite.cluster.ClusterNode;
@@ -513,7 +514,7 @@ public class GridReduceQueryExecutor {
         Set<ClusterNode> nodes = map.keySet();
 
         if (F.isEmpty(map))
-            throw new CacheException("Failed to find data nodes for cache: " + cctx.name());
+            throw new CacheServerNotFoundException("Failed to find data nodes for cache: " + cctx.name());
 
         for (int i = 1; i < cacheIds.size(); i++) {
             GridCacheContext<?,?> extraCctx = cacheContext(cacheIds.get(i));
@@ -531,7 +532,7 @@ public class GridReduceQueryExecutor {
             Set<ClusterNode> extraNodes = stableDataNodesMap(topVer, extraCctx, parts).keySet();
 
             if (F.isEmpty(extraNodes))
-                throw new CacheException("Failed to find data nodes for cache: " + extraCacheName);
+                throw new CacheServerNotFoundException("Failed to find data nodes for cache: " + extraCacheName);
 
             boolean disjoint;
 
@@ -1404,7 +1405,7 @@ public class GridReduceQueryExecutor {
         Set<ClusterNode> dataNodes = new HashSet<>(dataNodes(cctx.groupId(), NONE));
 
         if (dataNodes.isEmpty())
-            throw new CacheException("Failed to find data nodes for cache: " + cacheName);
+            throw new CacheServerNotFoundException("Failed to find data nodes for cache: " + cacheName);
 
         // Find all the nodes owning all the partitions for replicated cache.
         for (int p = 0, parts = cctx.affinity().partitions(); p < parts; p++) {
@@ -1484,7 +1485,7 @@ public class GridReduceQueryExecutor {
                     return null; // Retry.
                 }
 
-                throw new CacheException("Failed to find data nodes [cache=" + cctx.name() + ", part=" + p + "]");
+                throw new CacheServerNotFoundException("Failed to find data nodes [cache=" + cctx.name() + ", part=" + p + "]");
             }
 
             partLocs[p] = new HashSet<>(owners);
@@ -1520,7 +1521,7 @@ public class GridReduceQueryExecutor {
                             return null; // Retry.
                         }
 
-                        throw new CacheException("Failed to find data nodes [cache=" + extraCctx.name() +
+                        throw new CacheServerNotFoundException("Failed to find data nodes [cache=" + extraCctx.name() +
                             ", part=" + p + "]");
                     }
 


[ignite] 30/31: GG-19169: Fix wrong mvcc tx detection. This closes #78.

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch gg-19225
in repository https://gitbox.apache.org/repos/asf/ignite.git

commit b1a49bef46bba191288b2bb6fbabe7a9f94b0204
Author: Andrey V. Mashenkov <an...@gmail.com>
AuthorDate: Wed Jun 5 13:41:56 2019 +0300

    GG-19169: Fix wrong mvcc tx detection. This closes #78.
---
 .../processors/query/h2/IgniteH2Indexing.java      | 56 ++++++++++------------
 1 file changed, 25 insertions(+), 31 deletions(-)

diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
index b90093c..233b551 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
@@ -852,10 +852,6 @@ public class IgniteH2Indexing implements GridQueryIndexing {
 
             boolean forUpdate = GridSqlQueryParser.isForUpdateQuery(p);
 
-            if (forUpdate && !mvccEnabled)
-                throw new IgniteSQLException("SELECT FOR UPDATE query requires transactional " +
-                    "cache with MVCC enabled.", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
-
             if (this.ctx.security().enabled()) {
                 GridSqlQueryParser parser = new GridSqlQueryParser(false);
 
@@ -868,44 +864,42 @@ public class IgniteH2Indexing implements GridQueryIndexing {
 
             int opTimeout = qryTimeout;
 
-            if (mvccEnabled) {
-                if (mvccTracker == null)
-                    mvccTracker = mvccTracker(stmt, startTx);
+            if (mvccTracker == null)
+                mvccTracker = mvccTracker(stmt, startTx);
 
-                if (mvccTracker != null) {
-                    ctx.mvccSnapshot(mvccTracker.snapshot());
+            if (mvccEnabled = (mvccTracker != null)) {
+                ctx.mvccSnapshot(mvccTracker.snapshot());
 
-                    tx = checkActive(tx(this.ctx));
+                tx = checkActive(tx(this.ctx));
 
-                    opTimeout = operationTimeout(opTimeout, tx);
-                }
+                opTimeout = operationTimeout(opTimeout, tx);
+            }
 
-                if (forUpdate) {
-                    if (mvccTracker == null)
-                        throw new IgniteSQLException("SELECT FOR UPDATE query requires transactional " +
-                            "cache with MVCC enabled.", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
+            if (forUpdate) {
+                if (!mvccEnabled)
+                    throw new IgniteSQLException("SELECT FOR UPDATE query requires transactional " +
+                        "cache with MVCC enabled.", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
 
-                    GridSqlStatement stmt0 = new GridSqlQueryParser(false).parse(p);
+                GridSqlStatement stmt0 = new GridSqlQueryParser(false).parse(p);
 
-                    qry = GridSqlQueryParser.rewriteQueryForUpdateIfNeeded(stmt0, forUpdate = tx != null);
+                qry = GridSqlQueryParser.rewriteQueryForUpdateIfNeeded(stmt0, forUpdate = tx != null);
 
-                    stmt = preparedStatementWithParams(conn, qry, params, true);
+                stmt = preparedStatementWithParams(conn, qry, params, true);
 
-                    if (forUpdate) {
-                        GridCacheContext cctx = mvccTracker.context();
+                if (forUpdate) {
+                    GridCacheContext cctx = mvccTracker.context();
 
-                        try {
-                            if (tx.topologyVersionSnapshot() == null)
-                                new TxTopologyVersionFuture(tx, cctx).get();
-                        }
-                        catch (Exception e) {
-                            throw new IgniteSQLException("Failed to lock topology for SELECT FOR UPDATE query.", e);
-                        }
+                    try {
+                        if (tx.topologyVersionSnapshot() == null)
+                            new TxTopologyVersionFuture(tx, cctx).get();
+                    }
+                    catch (Exception e) {
+                        throw new IgniteSQLException("Failed to lock topology for SELECT FOR UPDATE query.", e);
+                    }
 
-                        sfuFut = new GridNearTxSelectForUpdateFuture(cctx, tx, opTimeout);
+                    sfuFut = new GridNearTxSelectForUpdateFuture(cctx, tx, opTimeout);
 
-                        sfuFut.initLocal();
-                    }
+                    sfuFut.initLocal();
                 }
             }
 


[ignite] 17/31: IGNITE-11702 Awaiting PME in test. - Fixes #6425.

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch gg-19225
in repository https://gitbox.apache.org/repos/asf/ignite.git

commit b75a023ff106d38731c4382f4214c90424e28be0
Author: ibessonov <be...@gmail.com>
AuthorDate: Wed Apr 10 13:29:56 2019 +0300

    IGNITE-11702 Awaiting PME in test. - Fixes #6425.
    
    Signed-off-by: Dmitriy Govorukhin <dm...@gmail.com>
    (cherry picked from commit 438c9e1865d8ecfe0744621390452369f4676302)
---
 .../cache/distributed/near/GridCacheNearOnlyTopologySelfTest.java     | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/GridCacheNearOnlyTopologySelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/GridCacheNearOnlyTopologySelfTest.java
index acc9b66..3689341 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/GridCacheNearOnlyTopologySelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/GridCacheNearOnlyTopologySelfTest.java
@@ -177,9 +177,11 @@ public class GridCacheNearOnlyTopologySelfTest extends GridCommonAbstractTest {
                 Ignite ignite = startGrid(i);
 
                 if (cilent)
-                    ignite.createNearCache(DEFAULT_CACHE_NAME, new NearCacheConfiguration());
+                    ignite.createNearCache(DEFAULT_CACHE_NAME, new NearCacheConfiguration<>());
             }
 
+            awaitPartitionMapExchange();
+
             for (int i = 0; i < 10; i++)
                 grid(1).cache(DEFAULT_CACHE_NAME).put(i, i);
 


[ignite] 23/31: GG-18917 [IGNITE-11821] Deprecate rebalance properties at CacheConfiguration and move them to IgniteConfiguration level (#6534)

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch gg-19225
in repository https://gitbox.apache.org/repos/asf/ignite.git

commit 81b8d8519dcdeb23b3e9c6c2f552cb4a4aafd892
Author: Maxim Muzafarov <ma...@gmail.com>
AuthorDate: Mon Jun 3 16:59:22 2019 +0300

    GG-18917 [IGNITE-11821] Deprecate rebalance properties at CacheConfiguration and move them to IgniteConfiguration level (#6534)
    
    (cherry picked from commit 64c6686da2d9c7fd730147089dc50ac8bc4b78c9)
---
 .../org/apache/ignite/IgniteSystemProperties.java  |  11 +-
 .../ignite/client/ClientCacheConfiguration.java    |   9 +-
 .../ignite/configuration/CacheConfiguration.java   |  63 +++++++--
 .../ignite/configuration/IgniteConfiguration.java  | 155 +++++++++++++++++++++
 .../org/apache/ignite/internal/IgniteKernal.java   |  16 +++
 .../processors/cache/GridCacheAttributes.java      |   9 ++
 .../processors/cache/GridCachePreloader.java       |  45 ++++++
 .../cache/GridCachePreloaderAdapter.java           |  29 ++++
 .../processors/cache/GridCacheProcessor.java       |   6 +-
 .../dht/preloader/GridDhtPartitionDemander.java    |  10 +-
 .../dht/preloader/GridDhtPartitionSupplier.java    |  24 ++--
 .../GridCacheAbstractNodeRestartSelfTest.java      |   2 +-
 .../GridCachePreloadRestartAbstractSelfTest.java   |   2 +-
 .../dht/GridCacheDhtPreloadBigDataSelfTest.java    |   2 +-
 .../dht/GridCacheDhtPreloadSelfTest.java           |   2 +-
 .../dht/GridCacheDhtPreloadStartStopSelfTest.java  |   2 +-
 .../dht/GridCacheDhtPreloadUnloadSelfTest.java     |   2 +-
 .../configvariations/ConfigVariations.java         |   2 +-
 .../ApiParity/IgniteConfigurationParityTest.cs     |   4 +
 19 files changed, 352 insertions(+), 43 deletions(-)

diff --git a/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java b/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java
index 904efe7..4e7b312 100644
--- a/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java
+++ b/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
@@ -28,6 +28,7 @@ import org.apache.ignite.cluster.ClusterGroup;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.CheckpointWriteOrder;
 import org.apache.ignite.configuration.DataStorageConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.internal.client.GridClient;
 import org.apache.ignite.internal.marshaller.optimized.OptimizedMarshaller;
 import org.apache.ignite.internal.processors.rest.GridRestCommand;
@@ -1021,9 +1022,11 @@ public final class IgniteSystemProperties {
     public static final String IGNITE_WAIT_SCHEMA_UPDATE = "IGNITE_WAIT_SCHEMA_UPDATE";
 
     /**
-     * System property to override {@link CacheConfiguration#rebalanceThrottle} configuration property for all caches.
+     * System property to override {@link CacheConfiguration#getRebalanceThrottle} configuration property for all caches.
      * {@code 0} by default, which means that override is disabled.
+     * @deprecated Use {@link IgniteConfiguration#getRebalanceThrottle()} instead.
      */
+    @Deprecated
     public static final String IGNITE_REBALANCE_THROTTLE_OVERRIDE = "IGNITE_REBALANCE_THROTTLE_OVERRIDE";
 
     /**
diff --git a/modules/core/src/main/java/org/apache/ignite/client/ClientCacheConfiguration.java b/modules/core/src/main/java/org/apache/ignite/client/ClientCacheConfiguration.java
index 2777c9c..cf40ead 100644
--- a/modules/core/src/main/java/org/apache/ignite/client/ClientCacheConfiguration.java
+++ b/modules/core/src/main/java/org/apache/ignite/client/ClientCacheConfiguration.java
@@ -25,6 +25,7 @@ import org.apache.ignite.cache.CacheWriteSynchronizationMode;
 import org.apache.ignite.cache.PartitionLossPolicy;
 import org.apache.ignite.cache.QueryEntity;
 import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.internal.util.typedef.internal.S;
 
 /** Cache configuration. */
@@ -60,10 +61,10 @@ public final class ClientCacheConfiguration implements Serializable {
     private boolean readFromBackup = CacheConfiguration.DFLT_READ_FROM_BACKUP;
 
     /** @serial Rebalance batch size. */
-    private int rebalanceBatchSize = CacheConfiguration.DFLT_REBALANCE_BATCH_SIZE;
+    private int rebalanceBatchSize = IgniteConfiguration.DFLT_REBALANCE_BATCH_SIZE;
 
     /** @serial Rebalance batches prefetch count. */
-    private long rebalanceBatchesPrefetchCnt = CacheConfiguration.DFLT_REBALANCE_BATCHES_PREFETCH_COUNT;
+    private long rebalanceBatchesPrefetchCnt = IgniteConfiguration.DFLT_REBALANCE_BATCHES_PREFETCH_COUNT;
 
     /** @serial Rebalance delay. */
     private long rebalanceDelay = 0;
@@ -75,10 +76,10 @@ public final class ClientCacheConfiguration implements Serializable {
     private int rebalanceOrder = 0;
 
     /** @serial Rebalance throttle. */
-    private long rebalanceThrottle = CacheConfiguration.DFLT_REBALANCE_THROTTLE;
+    private long rebalanceThrottle = IgniteConfiguration.DFLT_REBALANCE_THROTTLE;
 
     /** @serial @serial Rebalance timeout. */
-    private long rebalanceTimeout = CacheConfiguration.DFLT_REBALANCE_TIMEOUT;
+    private long rebalanceTimeout = IgniteConfiguration.DFLT_REBALANCE_TIMEOUT;
 
     /** @serial Write synchronization mode. */
     private CacheWriteSynchronizationMode writeSynchronizationMode = CacheWriteSynchronizationMode.PRIMARY_SYNC;
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 66d951b..c7208f2 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
@@ -80,18 +80,33 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> {
     /** Maximum number of partitions. */
     public static final int MAX_PARTITIONS_COUNT = 65000;
 
-    /** Default size of rebalance thread pool. */
+    /**
+     * Default size of rebalance thread pool.
+     * @deprecated Use {@link IgniteConfiguration#DFLT_REBALANCE_THREAD_POOL_SIZE} instead.
+     */
     @Deprecated
-    public static final int DFLT_REBALANCE_THREAD_POOL_SIZE = 2;
+    public static final int DFLT_REBALANCE_THREAD_POOL_SIZE = IgniteConfiguration.DFLT_REBALANCE_THREAD_POOL_SIZE;
 
-    /** Default rebalance timeout (ms).*/
-    public static final long DFLT_REBALANCE_TIMEOUT = 10000;
+    /**
+     * Default rebalance timeout (ms).
+     * @deprecated Use {@link IgniteConfiguration#DFLT_REBALANCE_TIMEOUT} instead.
+     */
+    @Deprecated
+    public static final long DFLT_REBALANCE_TIMEOUT = IgniteConfiguration.DFLT_REBALANCE_TIMEOUT;
 
-    /** Default rebalance batches prefetch count. */
-    public static final long DFLT_REBALANCE_BATCHES_PREFETCH_COUNT = 2;
+    /**
+     * Default rebalance batches prefetch count.
+     * @deprecated Use {@link IgniteConfiguration#DFLT_REBALANCE_BATCHES_PREFETCH_COUNT} instead.
+     */
+    @Deprecated
+    public static final long DFLT_REBALANCE_BATCHES_PREFETCH_COUNT = IgniteConfiguration.DFLT_REBALANCE_BATCHES_PREFETCH_COUNT;
 
-    /** Time in milliseconds to wait between rebalance messages to avoid overloading CPU. */
-    public static final long DFLT_REBALANCE_THROTTLE = 0;
+    /**
+     * Time in milliseconds to wait between rebalance messages to avoid overloading CPU.
+     * @deprecated Use {@link IgniteConfiguration#DFLT_REBALANCE_THROTTLE} instead.
+     */
+    @Deprecated
+    public static final long DFLT_REBALANCE_THROTTLE = IgniteConfiguration.DFLT_REBALANCE_THROTTLE;
 
     /** Default number of backups. */
     public static final int DFLT_BACKUPS = 0;
@@ -120,8 +135,12 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> {
     /** Default rebalance mode for distributed cache. */
     public static final CacheRebalanceMode DFLT_REBALANCE_MODE = CacheRebalanceMode.ASYNC;
 
-    /** Default rebalance batch size in bytes. */
-    public static final int DFLT_REBALANCE_BATCH_SIZE = 512 * 1024; // 512K
+    /**
+     * Default rebalance batch size in bytes.
+     * @deprecated Use {@link IgniteConfiguration#DFLT_REBALANCE_BATCH_SIZE} instead.
+     */
+    @Deprecated
+    public static final int DFLT_REBALANCE_BATCH_SIZE = IgniteConfiguration.DFLT_REBALANCE_BATCH_SIZE;
 
     /** Default value for eager ttl flag. */
     public static final boolean DFLT_EAGER_TTL = true;
@@ -205,6 +224,7 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> {
     private int rebalancePoolSize = DFLT_REBALANCE_THREAD_POOL_SIZE;
 
     /** Rebalance timeout. */
+    @Deprecated
     private long rebalanceTimeout = DFLT_REBALANCE_TIMEOUT;
 
     /** Cache eviction policy. */
@@ -278,9 +298,11 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> {
     private int rebalanceOrder;
 
     /** Rebalance batch size. */
+    @Deprecated
     private int rebalanceBatchSize = DFLT_REBALANCE_BATCH_SIZE;
 
     /** Rebalance batches prefetch count. */
+    @Deprecated
     private long rebalanceBatchesPrefetchCnt = DFLT_REBALANCE_BATCHES_PREFETCH_COUNT;
 
     /** Maximum number of concurrent asynchronous operations. */
@@ -316,7 +338,8 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> {
     /** */
     private long rebalanceDelay;
 
-    /** */
+    /** Time in milliseconds to wait between rebalance messages to avoid overloading CPU. */
+    @Deprecated
     private long rebalanceThrottle = DFLT_REBALANCE_THROTTLE;
 
     /** */
@@ -1200,7 +1223,9 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> {
      * {@link #DFLT_REBALANCE_BATCH_SIZE}.
      *
      * @return Size in bytes of a single rebalance message.
+     * @deprecated Use {@link IgniteConfiguration#getRebalanceBatchSize()} instead.
      */
+    @Deprecated
     public int getRebalanceBatchSize() {
         return rebalanceBatchSize;
     }
@@ -1210,7 +1235,9 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> {
      *
      * @param rebalanceBatchSize Rebalance batch size.
      * @return {@code this} for chaining.
+     * @deprecated Use {@link IgniteConfiguration#setRebalanceBatchSize(int)} instead.
      */
+    @Deprecated
     public CacheConfiguration<K, V> setRebalanceBatchSize(int rebalanceBatchSize) {
         this.rebalanceBatchSize = rebalanceBatchSize;
 
@@ -1225,7 +1252,9 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> {
      * Minimum is 1.
      *
      * @return batches count
+     * @deprecated Use {@link IgniteConfiguration#getRebalanceBatchesPrefetchCount()} instead.
      */
+    @Deprecated
     public long getRebalanceBatchesPrefetchCount() {
         return rebalanceBatchesPrefetchCnt;
     }
@@ -1239,7 +1268,9 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> {
      *
      * @param rebalanceBatchesCnt batches count.
      * @return {@code this} for chaining.
+     * @deprecated Use {@link IgniteConfiguration#setRebalanceBatchesPrefetchCount(long)} instead.
      */
+    @Deprecated
     public CacheConfiguration<K, V> setRebalanceBatchesPrefetchCount(long rebalanceBatchesCnt) {
         this.rebalanceBatchesPrefetchCnt = rebalanceBatchesCnt;
 
@@ -1488,7 +1519,9 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> {
      * Default value is {@link #DFLT_REBALANCE_TIMEOUT}.
      *
      * @return Rebalance timeout (ms).
+     * @deprecated Use {@link IgniteConfiguration#getRebalanceTimeout()} instead.
      */
+    @Deprecated
     public long getRebalanceTimeout() {
         return rebalanceTimeout;
     }
@@ -1498,7 +1531,9 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> {
      *
      * @param rebalanceTimeout Rebalance timeout (ms).
      * @return {@code this} for chaining.
+     * @deprecated Use {@link IgniteConfiguration#setRebalanceTimeout(long)} instead.
      */
+    @Deprecated
     public CacheConfiguration<K, V> setRebalanceTimeout(long rebalanceTimeout) {
         this.rebalanceTimeout = rebalanceTimeout;
 
@@ -1555,8 +1590,10 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> {
      * the default is defined by {@link #DFLT_REBALANCE_THROTTLE} constant.
      *
      * @return Time in milliseconds to wait between rebalance messages to avoid overloading of CPU,
-     *      {@code 0} to disable throttling.
+     * {@code 0} to disable throttling.
+     * @deprecated Use {@link IgniteConfiguration#getRebalanceThrottle()} instead.
      */
+    @Deprecated
     public long getRebalanceThrottle() {
         return rebalanceThrottle;
     }
@@ -1572,7 +1609,9 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> {
      * @param rebalanceThrottle Time in milliseconds to wait between rebalance messages to avoid overloading of CPU,
      * {@code 0} to disable throttling.
      * @return {@code this} for chaining.
+     * @deprecated Use {@link IgniteConfiguration#setRebalanceThrottle(long)} instead.
      */
+    @Deprecated
     public CacheConfiguration<K, V> setRebalanceThrottle(long rebalanceThrottle) {
         this.rebalanceThrottle = rebalanceThrottle;
 
diff --git a/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java b/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java
index 4062b92..c35d22f 100644
--- a/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java
+++ b/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java
@@ -155,6 +155,18 @@ public class IgniteConfiguration {
     /** Default limit of threads used for rebalance. */
     public static final int DFLT_REBALANCE_THREAD_POOL_SIZE = 1;
 
+    /** Default rebalance message timeout in milliseconds (value is {@code 10000}). */
+    public static final long DFLT_REBALANCE_TIMEOUT = 10000;
+
+    /** Default rebalance batches prefetch count (value is {@code 2}). */
+    public static final long DFLT_REBALANCE_BATCHES_PREFETCH_COUNT = 2;
+
+    /** Time to wait between rebalance messages in milliseconds to avoid overloading CPU (value is {@code 0}). */
+    public static final long DFLT_REBALANCE_THROTTLE = 0;
+
+    /** Default rebalance batch size in bytes (value is {@code 512Kb}). */
+    public static final int DFLT_REBALANCE_BATCH_SIZE = 512 * 1024; // 512K
+
     /** Default size of system thread pool. */
     public static final int DFLT_SYSTEM_CORE_THREAD_CNT = DFLT_PUBLIC_THREAD_CNT;
 
@@ -386,6 +398,18 @@ public class IgniteConfiguration {
     /** Rebalance thread pool size. */
     private int rebalanceThreadPoolSize = DFLT_REBALANCE_THREAD_POOL_SIZE;
 
+    /** Rrebalance messages timeout in milliseconds. */
+    private long rebalanceTimeout = DFLT_REBALANCE_TIMEOUT;
+
+    /** Rebalance batches prefetch count. */
+    private long rebalanceBatchesPrefetchCnt = DFLT_REBALANCE_BATCHES_PREFETCH_COUNT;
+
+    /** Time to wait between rebalance messages in milliseconds. */
+    private long rebalanceThrottle = DFLT_REBALANCE_THROTTLE;
+
+    /** Rebalance batch size in bytes. */
+    private int rebalanceBatchSize = DFLT_REBALANCE_BATCH_SIZE;
+
     /** Transactions configuration. */
     private TransactionConfiguration txCfg = new TransactionConfiguration();
 
@@ -619,6 +643,10 @@ public class IgniteConfiguration {
         pubPoolSize = cfg.getPublicThreadPoolSize();
         qryPoolSize = cfg.getQueryThreadPoolSize();
         rebalanceThreadPoolSize = cfg.getRebalanceThreadPoolSize();
+        rebalanceTimeout = cfg.getRebalanceTimeout();
+        rebalanceBatchesPrefetchCnt = cfg.getRebalanceBatchesPrefetchCount();
+        rebalanceThrottle = cfg.getRebalanceThrottle();
+        rebalanceBatchSize = cfg.getRebalanceBatchSize();
         segChkFreq = cfg.getSegmentCheckFrequency();
         segPlc = cfg.getSegmentationPolicy();
         segResolveAttempts = cfg.getSegmentationResolveAttempts();
@@ -1590,6 +1618,133 @@ public class IgniteConfiguration {
     }
 
     /**
+     * Rebalance timeout for supply and demand messages in milliseconds. The {@code rebalanceTimeout} parameter
+     * specifies how long a message will stay in a receiving queue, waiting for other ordered messages that are
+     * ordered ahead of it to arrive will be processed. If timeout expires, then all messages that have not arrived
+     * before this message will be skipped. If an expired supply (demand) message actually does arrive, it will be
+     * ignored.
+     * <p>
+     * Default value is defined by {@link IgniteConfiguration#DFLT_REBALANCE_TIMEOUT}, if {@code 0} than the
+     * {@link IgniteConfiguration#getNetworkTimeout()} will be used instead.
+     *
+     * @return Rebalance message timeout in milliseconds.
+     */
+    public long getRebalanceTimeout() {
+        return rebalanceTimeout;
+    }
+
+    /**
+     * Rebalance timeout for supply and demand messages in milliseconds. The {@code rebalanceTimeout} parameter
+     * specifies how long a message will stay in a receiving queue, waiting for other ordered messages that are
+     * ordered ahead of it to arrive will be processed. If timeout expires, then all messages that have not arrived
+     * before this message will be skipped. If an expired supply (demand) message actually does arrive, it will be
+     * ignored.
+     * <p>
+     * Default value is defined by {@link IgniteConfiguration#DFLT_REBALANCE_TIMEOUT}, if {@code 0} than the
+     * {@link IgniteConfiguration#getNetworkTimeout()} will be used instead.
+     *
+     * @param rebalanceTimeout Rebalance message timeout in milliseconds.
+     * @return {@code this} for chaining.
+     */
+    public IgniteConfiguration setRebalanceTimeout(long rebalanceTimeout) {
+        this.rebalanceTimeout = rebalanceTimeout;
+
+        return this;
+    }
+
+    /**
+     * The number of batches generated by supply node at rebalancing procedure start. To gain better rebalancing
+     * performance supplier node can provide more than one batch at rebalancing start and provide one new to each
+     * next demand request.
+     * <p>
+     * Default value is defined by {@link IgniteConfiguration#DFLT_REBALANCE_BATCHES_PREFETCH_COUNT}, minimum value is {@code 1}.
+     *
+     * @return The number of batches prefetch count.
+     */
+    public long getRebalanceBatchesPrefetchCount() {
+        return rebalanceBatchesPrefetchCnt;
+    }
+
+    /**
+     * The number of batches generated by supply node at rebalancing procedure start. To gain better rebalancing
+     * performance supplier node can provide more than one batch at rebalancing start and provide one new to each
+     * next demand request.
+     * <p>
+     * Default value is defined by {@link IgniteConfiguration#DFLT_REBALANCE_BATCHES_PREFETCH_COUNT}, minimum value is {@code 1}.
+     *
+     * @param rebalanceBatchesCnt The number of batches prefetch count.
+     * @return {@code this} for chaining.
+     */
+    public IgniteConfiguration setRebalanceBatchesPrefetchCount(long rebalanceBatchesCnt) {
+        this.rebalanceBatchesPrefetchCnt = rebalanceBatchesCnt;
+
+        return this;
+    }
+
+    /**
+     * Time in milliseconds to wait between rebalance messages to avoid overloading of CPU or network.
+     * When rebalancing large data sets, the CPU or network can get over-consumed with rebalancing messages,
+     * which consecutively may slow down the application performance. This parameter helps tune
+     * the amount of time to wait between rebalance messages to make sure that rebalancing process
+     * does not have any negative performance impact. Note that application will continue to work
+     * properly while rebalancing is still in progress.
+     * <p>
+     * Value of {@code 0} means that throttling is disabled. By default throttling is disabled -
+     * the default is defined by {@link IgniteConfiguration#DFLT_REBALANCE_THROTTLE} constant.
+     *
+     * @return Time in milliseconds to wait between rebalance messages, {@code 0} to disable throttling.
+     */
+    public long getRebalanceThrottle() {
+        return rebalanceThrottle;
+    }
+
+    /**
+     * Time in milliseconds to wait between rebalance messages to avoid overloading of CPU or network. When rebalancing
+     * large data sets, the CPU or network can get over-consumed with rebalancing messages, which consecutively may slow
+     * down the application performance. This parameter helps tune the amount of time to wait between rebalance messages
+     * to make sure that rebalancing process does not have any negative performance impact. Note that application will
+     * continue to work properly while rebalancing is still in progress.
+     * <p>
+     * Value of {@code 0} means that throttling is disabled. By default throttling is disabled -
+     * the default is defined by {@link IgniteConfiguration#DFLT_REBALANCE_THROTTLE} constant.
+     *
+     * @param rebalanceThrottle Time in milliseconds to wait between rebalance messages, {@code 0} to disable throttling.
+     * @return {@code this} for chaining.
+     */
+    public IgniteConfiguration setRebalanceThrottle(long rebalanceThrottle) {
+        this.rebalanceThrottle = rebalanceThrottle;
+
+        return this;
+    }
+
+    /**
+     * The supply message size in bytes to be loaded within a single rebalance batch. The data balancing algorithm
+     * splits all the cache data entries on supply node into multiple batches prior to sending them to the demand node.
+     * <p>
+     * Default value is defined by {@link IgniteConfiguration#DFLT_REBALANCE_BATCH_SIZE}.
+     *
+     * @return Rebalance message size in bytes.
+     */
+    public int getRebalanceBatchSize() {
+        return rebalanceBatchSize;
+    }
+
+    /**
+     * The supply message size in bytes to be loaded within a single rebalance batch. The data balancing algorithm
+     * splits all the cache data entries on supply node into multiple batches prior to sending them to the demand node.
+     * <p>
+     * Default value is defined by {@link IgniteConfiguration#DFLT_REBALANCE_BATCH_SIZE}.
+     *
+     * @param rebalanceBatchSize Rebalance message size in bytes.
+     * @return {@code this} for chaining.
+     */
+    public IgniteConfiguration setRebalanceBatchSize(int rebalanceBatchSize) {
+        this.rebalanceBatchSize = rebalanceBatchSize;
+
+        return this;
+    }
+
+    /**
      * Returns a collection of life-cycle beans. These beans will be automatically
      * notified of grid life-cycle events. Use life-cycle beans whenever you
      * want to perform certain logic before and after grid startup and stopping
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java b/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
index c3dbf07..f324d7f 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
@@ -2597,6 +2597,22 @@ public class IgniteKernal implements IgniteEx, IgniteMXBean, Externalizable {
                 throw new IgniteCheckedException("Rebalance thread pool size minimal allowed value is 1. " +
                     "Change IgniteConfiguration.rebalanceThreadPoolSize property before next start.");
 
+            if (cfg.getRebalanceBatchesPrefetchCount() < 1)
+                throw new IgniteCheckedException("Rebalance batches prefetch count minimal allowed value is 1. " +
+                    "Change IgniteConfiguration.rebalanceBatchesPrefetchCount property before next start.");
+
+            if (cfg.getRebalanceBatchSize() <= 0)
+                throw new IgniteCheckedException("Rebalance batch size must be greater than zero. " +
+                    "Change IgniteConfiguration.rebalanceBatchSize property before next start.");
+
+            if (cfg.getRebalanceThrottle() < 0)
+                throw new IgniteCheckedException("Rebalance throttle can't have negative value. " +
+                    "Change IgniteConfiguration.rebalanceThrottle property before next start.");
+
+            if (cfg.getRebalanceTimeout() < 0)
+                throw new IgniteCheckedException("Rebalance message timeout can't have negative value. " +
+                    "Change IgniteConfiguration.rebalanceTimeout property before next start.");
+
             for (CacheConfiguration ccfg : cfg.getCacheConfiguration()) {
                 if (ccfg.getRebalanceBatchesPrefetchCount() < 1)
                     throw new IgniteCheckedException("Rebalance batches prefetch count minimal allowed value is 1. " +
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAttributes.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAttributes.java
index 371d8e9..a51c7bf 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAttributes.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAttributes.java
@@ -24,6 +24,7 @@ import org.apache.ignite.cache.CacheWriteSynchronizationMode;
 import org.apache.ignite.cache.affinity.AffinityFunction;
 import org.apache.ignite.cache.affinity.rendezvous.RendezvousAffinityFunction;
 import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.configuration.NearCacheConfiguration;
 import org.apache.ignite.configuration.TransactionConfiguration;
 import org.apache.ignite.internal.util.typedef.internal.S;
@@ -250,7 +251,9 @@ public class GridCacheAttributes implements Serializable {
 
     /**
      * @return Preload batch size.
+     * @deprecated Use {@link IgniteConfiguration#getRebalanceBatchSize()} instead.
      */
+    @Deprecated
     public int rebalanceBatchSize() {
         return ccfg.getRebalanceBatchSize();
     }
@@ -264,7 +267,9 @@ public class GridCacheAttributes implements Serializable {
 
     /**
      * @return Rebalance prefetch count.
+     * @deprecated Use {@link IgniteConfiguration#getRebalanceBatchesPrefetchCount()} instead.
      */
+    @Deprecated
     public long rebalanceBatchesPrefetchCount() {
         return ccfg.getRebalanceBatchesPrefetchCount();
     }
@@ -278,14 +283,18 @@ public class GridCacheAttributes implements Serializable {
 
     /**
      * @return Rebalance throttle.
+     * @deprecated Use {@link IgniteConfiguration#getRebalanceThrottle()} instead.
      */
+    @Deprecated
     public long rebalanceThrottle() {
         return ccfg.getRebalanceThrottle();
     }
 
     /**
      * @return Rebalance timeout.
+     * @deprecated Use {@link IgniteConfiguration#getRebalanceTimeout()} instead.
      */
+    @Deprecated
     public long rebalanceTimeout() {
         return ccfg.getRebalanceTimeout();
     }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCachePreloader.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCachePreloader.java
index 58145cf..6a5813a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCachePreloader.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCachePreloader.java
@@ -19,6 +19,8 @@ package org.apache.ignite.internal.processors.cache;
 import java.util.Collection;
 import java.util.UUID;
 import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.internal.IgniteInternalFuture;
 import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
 import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtFuture;
@@ -201,4 +203,47 @@ public interface GridCachePreloader {
      * Resume preloader.
      */
     public void resume();
+
+    /**
+     * Rebalance timeout for supply and demand messages in milliseconds.
+     * <p>
+     * The {@link IgniteConfiguration#getRebalanceTimeout()} will be used by default. If an Ignite's configuration value
+     * is not provided than the {@link CacheConfiguration#getRebalanceTimeout()} will be used instead.
+     *
+     * @return Rebalance message timeout in milliseconds.
+     */
+    public long timeout();
+
+    /**
+     * The number of batches generated by supply node at rebalancing procedure start.
+     * <p>
+     * The {@link IgniteConfiguration#getRebalanceBatchesPrefetchCount()} will be used by default. If an Ignite's
+     * configuration value is not provided than the {@link CacheConfiguration#getRebalanceBatchesPrefetchCount()}
+     * will be used instead.
+     *
+     * @return The number of batches prefetch count.
+     */
+    public long batchesPrefetchCount();
+
+    /**
+     * Time in milliseconds to wait between rebalance messages to avoid overloading of CPU or network.
+     * <p>
+     * The {@link IgniteConfiguration#getRebalanceThrottle()} will be used by default. If an Ignite's
+     * configuration value is not provided than the {@link CacheConfiguration#getRebalanceThrottle()}
+     * will be used instead.
+     *
+     * @return Time in milliseconds to wait between rebalance messages, {@code 0} to disable throttling.
+     */
+    public long throttle();
+
+    /**
+     * The supply message size in bytes to be loaded within a single rebalance batch.
+     * <p>
+     * The {@link IgniteConfiguration#getRebalanceBatchSize()} will be used by default. If an Ignite's
+     * configuration value is not provided than the {@link CacheConfiguration#getRebalanceBatchSize()}
+     * will be used instead.
+     *
+     * @return Rebalance message size in bytes.
+     */
+    public int batchSize();
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCachePreloaderAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCachePreloaderAdapter.java
index d176a3b..039067c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCachePreloaderAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCachePreloaderAdapter.java
@@ -34,6 +34,11 @@ import org.apache.ignite.internal.util.future.GridFinishedFuture;
 import org.apache.ignite.lang.IgnitePredicate;
 import org.jetbrains.annotations.Nullable;
 
+import static org.apache.ignite.configuration.IgniteConfiguration.DFLT_REBALANCE_BATCHES_PREFETCH_COUNT;
+import static org.apache.ignite.configuration.IgniteConfiguration.DFLT_REBALANCE_BATCH_SIZE;
+import static org.apache.ignite.configuration.IgniteConfiguration.DFLT_REBALANCE_THROTTLE;
+import static org.apache.ignite.configuration.IgniteConfiguration.DFLT_REBALANCE_TIMEOUT;
+
 /**
  * Adapter for preloading which always assumes that preloading finished.
  */
@@ -190,4 +195,28 @@ public class GridCachePreloaderAdapter implements GridCachePreloader {
     @Override public void resume() {
         // No-op
     }
+
+    /** {@inheritDoc} */
+    @Override public long timeout() {
+        return grp.shared().gridConfig().getRebalanceTimeout() == DFLT_REBALANCE_TIMEOUT ?
+            grp.config().getRebalanceTimeout() : grp.shared().gridConfig().getRebalanceTimeout();
+    }
+
+    /** {@inheritDoc} */
+    @Override public long batchesPrefetchCount() {
+        return grp.shared().gridConfig().getRebalanceBatchesPrefetchCount() == DFLT_REBALANCE_BATCHES_PREFETCH_COUNT ?
+            grp.config().getRebalanceBatchesPrefetchCount() : grp.shared().gridConfig().getRebalanceBatchesPrefetchCount();
+    }
+
+    /** {@inheritDoc} */
+    @Override public long throttle() {
+        return grp.shared().gridConfig().getRebalanceThrottle() == DFLT_REBALANCE_THROTTLE ?
+            grp.config().getRebalanceThrottle() : grp.shared().gridConfig().getRebalanceThrottle();
+    }
+
+    /** {@inheritDoc} */
+    @Override public int batchSize() {
+        return grp.shared().gridConfig().getRebalanceBatchSize() == DFLT_REBALANCE_BATCH_SIZE ?
+            grp.config().getRebalanceBatchSize() : grp.shared().gridConfig().getRebalanceBatchSize();
+    }
 }
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 cb82a37..167cdcc 100644
--- 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
@@ -527,8 +527,12 @@ public class GridCacheProcessor extends GridProcessorAdapter {
             throw new IgniteCheckedException("Cannot have more than " + CacheConfiguration.MAX_PARTITIONS_COUNT +
                 " partitions [cacheName=" + cc.getName() + ", partitions=" + cc.getAffinity().partitions() + ']');
 
-        if (cc.getRebalanceMode() != CacheRebalanceMode.NONE)
+        if (cc.getRebalanceMode() != CacheRebalanceMode.NONE) {
             assertParameter(cc.getRebalanceBatchSize() > 0, "rebalanceBatchSize > 0");
+            assertParameter(cc.getRebalanceTimeout() >= 0, "rebalanceTimeout >= 0");
+            assertParameter(cc.getRebalanceThrottle() >= 0, "rebalanceThrottle >= 0");
+            assertParameter(cc.getRebalanceBatchesPrefetchCount() > 0, "rebalanceBatchesPrefetchCount > 0");
+        }
 
         if (cc.getCacheMode() == PARTITIONED || cc.getCacheMode() == REPLICATED) {
             if (cc.getAtomicityMode() == ATOMIC && cc.getWriteSynchronizationMode() == FULL_ASYNC)
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtPartitionDemander.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtPartitionDemander.java
index bd7d18f..07d9b64 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtPartitionDemander.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtPartitionDemander.java
@@ -509,7 +509,7 @@ public class GridDhtPartitionDemander {
 
                     demandMsg.topic(rebalanceTopics.get(stripe));
                     demandMsg.rebalanceId(fut.rebalanceId);
-                    demandMsg.timeout(cfg.getRebalanceTimeout());
+                    demandMsg.timeout(grp.preloader().timeout());
 
                     final int topicId = stripe;
 
@@ -837,7 +837,7 @@ public class GridDhtPartitionDemander {
                 supplyMsg.topologyVersion(),
                 grp.groupId());
 
-            d.timeout(grp.config().getRebalanceTimeout());
+            d.timeout(grp.preloader().timeout());
 
             d.topic(rebalanceTopics.get(topicId));
 
@@ -845,7 +845,7 @@ public class GridDhtPartitionDemander {
                 // Send demand message.
                 try {
                     ctx.io().sendOrderedMessage(node, rebalanceTopics.get(topicId),
-                        d.convertIfNeeded(node.version()), grp.ioPolicy(), grp.config().getRebalanceTimeout());
+                        d.convertIfNeeded(node.version()), grp.ioPolicy(), grp.preloader().timeout());
 
                     if (log.isDebugEnabled())
                         log.debug("Send next demand message [" + demandRoutineInfo(topicId, nodeId, supplyMsg) + "]");
@@ -1360,14 +1360,14 @@ public class GridDhtPartitionDemander {
                 this.topologyVersion(),
                 grp.groupId());
 
-            d.timeout(grp.config().getRebalanceTimeout());
+            d.timeout(grp.preloader().timeout());
 
             try {
                 for (int idx = 0; idx < ctx.gridConfig().getRebalanceThreadPoolSize(); idx++) {
                     d.topic(GridCachePartitionExchangeManager.rebalanceTopic(idx));
 
                     ctx.io().sendOrderedMessage(node, GridCachePartitionExchangeManager.rebalanceTopic(idx),
-                        d.convertIfNeeded(node.version()), grp.ioPolicy(), grp.config().getRebalanceTimeout());
+                        d.convertIfNeeded(node.version()), grp.ioPolicy(), grp.preloader().timeout());
                 }
             }
             catch (IgniteCheckedException ignored) {
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtPartitionSupplier.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtPartitionSupplier.java
index e3243ff..b19bddd 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtPartitionSupplier.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtPartitionSupplier.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2019 GridGain Systems, Inc. and Contributors.
- * 
+ *
  * Licensed under the GridGain Community Edition License (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
- * 
+ *
  * 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.
@@ -28,7 +28,7 @@ import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.IgniteLogger;
 import org.apache.ignite.IgniteSystemProperties;
 import org.apache.ignite.cluster.ClusterNode;
-import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.internal.cluster.ClusterTopologyCheckedException;
 import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
 import org.apache.ignite.internal.processors.cache.CacheGroupContext;
@@ -74,7 +74,11 @@ class GridDhtPartitionSupplier {
     /** Supply context map. T3: nodeId, topicId, topVer. */
     private final Map<T3<UUID, Integer, AffinityTopologyVersion>, SupplyContext> scMap = new HashMap<>();
 
-    /** Override for rebalance throttle. */
+    /**
+     * Override for rebalance throttle.
+     * @deprecated Use {@link IgniteConfiguration#getRebalanceThrottle()} instead.
+     */
+    @Deprecated
     private long rebalanceThrottleOverride =
         IgniteSystemProperties.getLong(IgniteSystemProperties.IGNITE_REBALANCE_THROTTLE_OVERRIDE, 0);
 
@@ -171,7 +175,7 @@ class GridDhtPartitionSupplier {
      * For each demand message method lookups (or creates new) supply context and starts to iterate entries across requested partitions.
      * Each entry in iterator is placed to prepared supply message.
      *
-     * If supply message size in bytes becomes greater than {@link CacheConfiguration#getRebalanceBatchSize()}
+     * If supply message size in bytes becomes greater than {@link IgniteConfiguration#getRebalanceBatchSize()}
      * method sends this message to demand node and saves partial state of iterated entries to supply context,
      * then restores the context again after new demand message with the same context id is arrived.
      *
@@ -252,7 +256,7 @@ class GridDhtPartitionSupplier {
 
             assert !(sctx != null && !demandMsg.partitions().isEmpty());
 
-            long maxBatchesCnt = grp.config().getRebalanceBatchesPrefetchCount();
+            long maxBatchesCnt = grp.preloader().batchesPrefetchCount();
 
             if (sctx == null) {
                 if (log.isDebugEnabled())
@@ -312,7 +316,7 @@ class GridDhtPartitionSupplier {
                 remainingParts = sctx.remainingParts;
             }
 
-            final int msgMaxSize = grp.config().getRebalanceBatchSize();
+            final int msgMaxSize = grp.preloader().batchSize();
 
             long batchesCnt = 0;
 
@@ -554,8 +558,8 @@ class GridDhtPartitionSupplier {
             // Throttle preloading.
             if (rebalanceThrottleOverride > 0)
                 U.sleep(rebalanceThrottleOverride);
-            else if (grp.config().getRebalanceThrottle() > 0)
-                U.sleep(grp.config().getRebalanceThrottle());
+            else if (grp.preloader().throttle() > 0)
+                U.sleep(grp.preloader().throttle());
 
             return true;
         }
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/GridCacheAbstractNodeRestartSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/GridCacheAbstractNodeRestartSelfTest.java
index 882686a..340f342 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/GridCacheAbstractNodeRestartSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/GridCacheAbstractNodeRestartSelfTest.java
@@ -52,7 +52,7 @@ import static org.apache.ignite.cache.CacheAtomicityMode.ATOMIC;
 import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL;
 import static org.apache.ignite.cache.CacheRebalanceMode.ASYNC;
 import static org.apache.ignite.cache.CacheRebalanceMode.SYNC;
-import static org.apache.ignite.configuration.CacheConfiguration.DFLT_REBALANCE_BATCH_SIZE;
+import static org.apache.ignite.configuration.IgniteConfiguration.DFLT_REBALANCE_BATCH_SIZE;
 import static org.apache.ignite.transactions.TransactionConcurrency.PESSIMISTIC;
 import static org.apache.ignite.transactions.TransactionIsolation.REPEATABLE_READ;
 
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/GridCachePreloadRestartAbstractSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/GridCachePreloadRestartAbstractSelfTest.java
index 55b038a..cb0db54 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/GridCachePreloadRestartAbstractSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/GridCachePreloadRestartAbstractSelfTest.java
@@ -36,8 +36,8 @@ import static org.apache.ignite.cache.CacheRebalanceMode.ASYNC;
 import static org.apache.ignite.cache.CacheRebalanceMode.NONE;
 import static org.apache.ignite.cache.CacheRebalanceMode.SYNC;
 import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
-import static org.apache.ignite.configuration.CacheConfiguration.DFLT_REBALANCE_BATCH_SIZE;
 import static org.apache.ignite.configuration.DeploymentMode.CONTINUOUS;
+import static org.apache.ignite.configuration.IgniteConfiguration.DFLT_REBALANCE_BATCH_SIZE;
 
 /**
  * Test node restart.
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridCacheDhtPreloadBigDataSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridCacheDhtPreloadBigDataSelfTest.java
index 27b9dec..c0fc586 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridCacheDhtPreloadBigDataSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridCacheDhtPreloadBigDataSelfTest.java
@@ -35,8 +35,8 @@ import static org.apache.ignite.cache.CacheMode.PARTITIONED;
 import static org.apache.ignite.cache.CacheRebalanceMode.ASYNC;
 import static org.apache.ignite.cache.CacheRebalanceMode.SYNC;
 import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
-import static org.apache.ignite.configuration.CacheConfiguration.DFLT_REBALANCE_BATCH_SIZE;
 import static org.apache.ignite.configuration.DeploymentMode.CONTINUOUS;
+import static org.apache.ignite.configuration.IgniteConfiguration.DFLT_REBALANCE_BATCH_SIZE;
 
 /**
  * Test large cache counts.
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridCacheDhtPreloadSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridCacheDhtPreloadSelfTest.java
index 20de601..3c09470 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridCacheDhtPreloadSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridCacheDhtPreloadSelfTest.java
@@ -51,8 +51,8 @@ import static org.apache.ignite.cache.CacheMode.PARTITIONED;
 import static org.apache.ignite.cache.CacheRebalanceMode.ASYNC;
 import static org.apache.ignite.cache.CacheRebalanceMode.SYNC;
 import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
-import static org.apache.ignite.configuration.CacheConfiguration.DFLT_REBALANCE_BATCH_SIZE;
 import static org.apache.ignite.configuration.DeploymentMode.CONTINUOUS;
+import static org.apache.ignite.configuration.IgniteConfiguration.DFLT_REBALANCE_BATCH_SIZE;
 import static org.apache.ignite.events.EventType.EVTS_CACHE_REBALANCE;
 import static org.apache.ignite.internal.processors.cache.distributed.dht.topology.GridDhtPartitionState.MOVING;
 import static org.apache.ignite.internal.processors.cache.distributed.dht.topology.GridDhtPartitionState.OWNING;
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridCacheDhtPreloadStartStopSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridCacheDhtPreloadStartStopSelfTest.java
index 6b84b61..b0d11fb 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridCacheDhtPreloadStartStopSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridCacheDhtPreloadStartStopSelfTest.java
@@ -42,8 +42,8 @@ import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL;
 import static org.apache.ignite.cache.CacheMode.PARTITIONED;
 import static org.apache.ignite.cache.CacheRebalanceMode.ASYNC;
 import static org.apache.ignite.cache.CacheRebalanceMode.SYNC;
-import static org.apache.ignite.configuration.CacheConfiguration.DFLT_REBALANCE_BATCH_SIZE;
 import static org.apache.ignite.configuration.DeploymentMode.CONTINUOUS;
+import static org.apache.ignite.configuration.IgniteConfiguration.DFLT_REBALANCE_BATCH_SIZE;
 import static org.apache.ignite.internal.processors.cache.distributed.dht.topology.GridDhtPartitionState.OWNING;
 
 /**
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridCacheDhtPreloadUnloadSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridCacheDhtPreloadUnloadSelfTest.java
index 2b9c432..adbdc1a 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridCacheDhtPreloadUnloadSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridCacheDhtPreloadUnloadSelfTest.java
@@ -36,8 +36,8 @@ import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL;
 import static org.apache.ignite.cache.CacheMode.PARTITIONED;
 import static org.apache.ignite.cache.CacheRebalanceMode.ASYNC;
 import static org.apache.ignite.cache.CacheRebalanceMode.SYNC;
-import static org.apache.ignite.configuration.CacheConfiguration.DFLT_REBALANCE_BATCH_SIZE;
 import static org.apache.ignite.configuration.DeploymentMode.CONTINUOUS;
+import static org.apache.ignite.configuration.IgniteConfiguration.DFLT_REBALANCE_BATCH_SIZE;
 
 /**
  * Test large cache counts.
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 d2288d9..fae68ef 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
@@ -75,7 +75,7 @@ public class ConfigVariations {
         Parameters.parameter("setRebalanceBatchSize", 2028 * 1024),
         Parameters.parameter("setRebalanceBatchesPrefetchCount", 5L),
         Parameters.parameter("setRebalanceThreadPoolSize", 5),
-        Parameters.parameter("setRebalanceTimeout", CacheConfiguration.DFLT_REBALANCE_TIMEOUT * 2),
+        Parameters.parameter("setRebalanceTimeout", IgniteConfiguration.DFLT_REBALANCE_TIMEOUT * 2),
         Parameters.parameter("setRebalanceDelay", 1000L)
     );
 
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/IgniteConfigurationParityTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/IgniteConfigurationParityTest.cs
index dddcae6..13f666e 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/IgniteConfigurationParityTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/IgniteConfigurationParityTest.cs
@@ -71,6 +71,10 @@ namespace Apache.Ignite.Core.Tests.ApiParity
         private static readonly string[] MissingProperties =
         {
             "RebalanceThreadPoolSize",
+            "RebalanceTimeout",
+            "RebalanceBatchesPrefetchCount",
+            "RebalanceThrottle",
+            "RebalanceBatchSize",
             "SegmentationPolicy",
             "isWaitForSegmentOnStart",
             "isAllSegmentationResolversPassRequired",


[ignite] 08/31: IGNITE-1903 Missed part

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch gg-19225
in repository https://gitbox.apache.org/repos/asf/ignite.git

commit 61fc6a592ff54603c154a85f363b3a7b54603d6a
Author: Eduard Shangareev <es...@gridgain.com>
AuthorDate: Thu May 30 13:50:49 2019 +0300

    IGNITE-1903 Missed part
---
 .../java/org/apache/ignite/testframework/junits/GridAbstractTest.java  | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/junits/GridAbstractTest.java b/modules/core/src/test/java/org/apache/ignite/testframework/junits/GridAbstractTest.java
index a2ddbac..e60874d 100755
--- a/modules/core/src/test/java/org/apache/ignite/testframework/junits/GridAbstractTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/testframework/junits/GridAbstractTest.java
@@ -1770,7 +1770,8 @@ public abstract class GridAbstractTest extends JUnit3TestLegacySupport {
             afterTest();
         }
         finally {
-            serializedObj.clear();
+            if (!keepSerializedObjects())
+                serializedObj.clear();
 
             Exception err = null;
 


[ignite] 01/31: GG-19132 Add licence to Tests.DotNetCore

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch gg-19225
in repository https://gitbox.apache.org/repos/asf/ignite.git

commit 9e4cdbc8f6e5533ab15c0eef8fc707fd7107bdae
Author: Alexandr Shapkin <as...@gridgain.com>
AuthorDate: Wed May 29 13:06:16 2019 +0300

    GG-19132 Add licence to Tests.DotNetCore
    
    (cherry picked from commit 1cc651843cb7b80d4a1940719ad44e517659ca75)
---
 .../Properties/AssemblyInfo.cs                         | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests.DotNetCore/Properties/AssemblyInfo.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests.DotNetCore/Properties/AssemblyInfo.cs
index 6c19c87..f75ab7b 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests.DotNetCore/Properties/AssemblyInfo.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests.DotNetCore/Properties/AssemblyInfo.cs
@@ -1,4 +1,20 @@
-using System.Reflection;
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+using System.Reflection;
 using System.Runtime.InteropServices;
 
 // General Information about an assembly is controlled through the following 


[ignite] 12/31: GG-18622 [IGNITE-11780] Split command handler on hierarchy of commands -CE licenses

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch gg-19225
in repository https://gitbox.apache.org/repos/asf/ignite.git

commit 25e91d74a34ca6f3ec8083c7947fc111a4be00b4
Author: Eduard Shangareev <es...@gridgain.com>
AuthorDate: Fri May 31 03:00:25 2019 +0300

    GG-18622 [IGNITE-11780] Split command handler on hierarchy of commands
    -CE licenses
---
 .../internal/commandline/ActivateCommand.java      | 25 +++++++++-------------
 .../internal/commandline/BaselineCommand.java      | 24 +++++++++------------
 .../internal/commandline/CommandArgIterator.java   | 24 +++++++++------------
 .../ignite/internal/commandline/CommandList.java   | 24 +++++++++------------
 .../ignite/internal/commandline/CommandLogger.java | 25 +++++++++-------------
 .../internal/commandline/CommonArgParser.java      | 24 +++++++++------------
 .../internal/commandline/DeactivateCommand.java    | 24 +++++++++------------
 .../ignite/internal/commandline/StateCommand.java  | 24 +++++++++------------
 .../ignite/internal/commandline/TaskExecutor.java  | 25 +++++++++-------------
 .../ignite/internal/commandline/TxCommandArg.java  | 25 +++++++++-------------
 .../ignite/internal/commandline/TxCommands.java    | 25 +++++++++-------------
 .../ignite/internal/commandline/WalCommands.java   | 24 +++++++++------------
 .../commandline/baseline/BaselineArguments.java    | 24 +++++++++------------
 .../commandline/baseline/BaselineSubcommands.java  | 24 +++++++++------------
 .../internal/commandline/cache/CacheCommands.java  | 24 +++++++++------------
 .../commandline/cache/CacheContention.java         | 25 +++++++++-------------
 .../commandline/cache/CacheDistribution.java       | 25 +++++++++-------------
 .../commandline/cache/CacheSubcommands.java        | 24 +++++++++------------
 .../commandline/cache/CacheValidateIndexes.java    | 24 +++++++++------------
 .../internal/commandline/cache/CacheViewer.java    | 24 +++++++++------------
 .../commandline/cache/FindAndDeleteGarbage.java    | 24 +++++++++------------
 .../internal/commandline/cache/IdleVerify.java     | 25 +++++++++-------------
 .../commandline/cache/ResetLostPartitions.java     | 24 +++++++++------------
 .../cache/transactions/TxOnCachesStopTest.java     | 13 ++++++-----
 24 files changed, 236 insertions(+), 337 deletions(-)

diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/ActivateCommand.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/ActivateCommand.java
index f18a747..2bdac5f 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/ActivateCommand.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/ActivateCommand.java
@@ -1,24 +1,19 @@
 /*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
  *
- *  * 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.
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
  *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
  *
+ * 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.commandline;
 
 import org.apache.ignite.internal.client.GridClient;
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/BaselineCommand.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/BaselineCommand.java
index 5c73fd5..e5940cb 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/BaselineCommand.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/BaselineCommand.java
@@ -1,21 +1,17 @@
 /*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
  *
- *  * 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.
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
  *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
  *
+ * 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.
  */
 
 
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommandArgIterator.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommandArgIterator.java
index ae36596..b90e972 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommandArgIterator.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommandArgIterator.java
@@ -1,21 +1,17 @@
 /*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
  *
- *  * 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.
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
  *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
  *
+ * 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.commandline;
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommandList.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommandList.java
index 2347a2f..280a40b 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommandList.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommandList.java
@@ -1,21 +1,17 @@
 /*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
  *
- *  * 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.
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
  *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
  *
+ * 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.commandline;
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommandLogger.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommandLogger.java
index 34e44e5..b19ad24 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommandLogger.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommandLogger.java
@@ -1,24 +1,19 @@
 /*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
  *
- *  * 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.
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
  *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
  *
+ * 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.commandline;
 
 import java.util.Map;
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommonArgParser.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommonArgParser.java
index 363a87c..d2bb652 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommonArgParser.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommonArgParser.java
@@ -1,21 +1,17 @@
 /*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
  *
- *  * 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.
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
  *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
  *
+ * 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.commandline;
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/DeactivateCommand.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/DeactivateCommand.java
index 4a93657..ad5e551 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/DeactivateCommand.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/DeactivateCommand.java
@@ -1,21 +1,17 @@
 /*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
  *
- *  * 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.
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
  *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
  *
+ * 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.commandline;
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/StateCommand.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/StateCommand.java
index 15c9ca7..a2a3afd 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/StateCommand.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/StateCommand.java
@@ -1,21 +1,17 @@
 /*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
  *
- *  * 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.
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
  *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
  *
+ * 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.commandline;
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/TaskExecutor.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/TaskExecutor.java
index 0bbbd7e..4600df0 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/TaskExecutor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/TaskExecutor.java
@@ -1,24 +1,19 @@
 /*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
  *
- *  * 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.
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
  *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
  *
+ * 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.commandline;
 
 import java.io.IOException;
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/TxCommandArg.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/TxCommandArg.java
index c2ea6df..7742181 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/TxCommandArg.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/TxCommandArg.java
@@ -1,24 +1,19 @@
 /*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
  *
- *  * 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.
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
  *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
  *
+ * 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.commandline;
 
 import org.apache.ignite.internal.commandline.argument.CommandArg;
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/TxCommands.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/TxCommands.java
index c86c241..1063d13 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/TxCommands.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/TxCommands.java
@@ -1,24 +1,19 @@
 /*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
  *
- *  * 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.
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
  *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
  *
+ * 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.commandline;
 
 import java.util.ArrayList;
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/WalCommands.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/WalCommands.java
index fd22e16..872d732 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/WalCommands.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/WalCommands.java
@@ -1,21 +1,17 @@
 /*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
  *
- *  * 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.
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
  *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
  *
+ * 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.commandline;
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/baseline/BaselineArguments.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/baseline/BaselineArguments.java
index 395a4ef..eb7b476 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/baseline/BaselineArguments.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/baseline/BaselineArguments.java
@@ -1,21 +1,17 @@
 /*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
  *
- *  * 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.
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
  *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
  *
+ * 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.commandline.baseline;
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/baseline/BaselineSubcommands.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/baseline/BaselineSubcommands.java
index e0f656e..ae9595c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/baseline/BaselineSubcommands.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/baseline/BaselineSubcommands.java
@@ -1,21 +1,17 @@
 /*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
  *
- *  * 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.
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
  *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
  *
+ * 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.commandline.baseline;
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheCommands.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheCommands.java
index 342a6ca..aa9a774 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheCommands.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheCommands.java
@@ -1,21 +1,17 @@
 /*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
  *
- *  * 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.
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
  *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
  *
+ * 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.commandline.cache;
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheContention.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheContention.java
index e88eae9..b09e30a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheContention.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheContention.java
@@ -1,24 +1,19 @@
 /*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
  *
- *  * 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.
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
  *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
  *
+ * 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.commandline.cache;
 
 import java.util.UUID;
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheDistribution.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheDistribution.java
index 958787f..bf37ffd 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheDistribution.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheDistribution.java
@@ -1,24 +1,19 @@
 /*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
  *
- *  * 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.
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
  *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
  *
+ * 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.commandline.cache;
 
 import java.util.HashSet;
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheSubcommands.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheSubcommands.java
index 298a882..c61a5b2 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheSubcommands.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheSubcommands.java
@@ -1,21 +1,17 @@
 /*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
  *
- *  * 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.
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
  *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
  *
+ * 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.commandline.cache;
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheValidateIndexes.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheValidateIndexes.java
index f03051d..7789fde 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheValidateIndexes.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheValidateIndexes.java
@@ -1,21 +1,17 @@
 /*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
  *
- *  * 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.
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
  *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
  *
+ * 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.
  */
 
 
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheViewer.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheViewer.java
index 32ed0c9..b5d0f14 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheViewer.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheViewer.java
@@ -1,21 +1,17 @@
 /*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
  *
- *  * 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.
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
  *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
  *
+ * 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.commandline.cache;
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/FindAndDeleteGarbage.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/FindAndDeleteGarbage.java
index 6c976c7..3dfe6c8 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/FindAndDeleteGarbage.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/FindAndDeleteGarbage.java
@@ -1,21 +1,17 @@
 /*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
  *
- *  * 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.
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
  *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
  *
+ * 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.commandline.cache;
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/IdleVerify.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/IdleVerify.java
index b67c5d1..036bce4 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/IdleVerify.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/IdleVerify.java
@@ -1,24 +1,19 @@
 /*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
  *
- *  * 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.
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
  *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
  *
+ * 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.commandline.cache;
 
 import java.util.Arrays;
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/ResetLostPartitions.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/ResetLostPartitions.java
index ed37b43..68f2ca7 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/ResetLostPartitions.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/ResetLostPartitions.java
@@ -1,21 +1,17 @@
 /*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
  *
- *  * 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.
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
  *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
  *
+ * 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.commandline.cache;
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TxOnCachesStopTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TxOnCachesStopTest.java
index 52ec992..02badb9 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TxOnCachesStopTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TxOnCachesStopTest.java
@@ -1,12 +1,11 @@
 /*
- * 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
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,


[ignite] 21/31: GG-19181 Web Console: Add exclusions of org.eclipse.jetty.aggregate artifacts for "hive".

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch gg-19225
in repository https://gitbox.apache.org/repos/asf/ignite.git

commit 6f017656e2a57357b7fbfb9c9ea5ae7f389ac96b
Author: Vladimir Pligin <vo...@yandex.ru>
AuthorDate: Fri May 31 17:47:43 2019 +0300

    GG-19181 Web Console: Add exclusions of org.eclipse.jetty.aggregate artifacts for "hive".
    
    (cherry picked from commit c62afef58d5c4206cbf09fef7e00a9a41fb24a03)
---
 modules/web-console/frontend/app/data/pom-dependencies.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/modules/web-console/frontend/app/data/pom-dependencies.json b/modules/web-console/frontend/app/data/pom-dependencies.json
index b597e6a..8b514fc 100644
--- a/modules/web-console/frontend/app/data/pom-dependencies.json
+++ b/modules/web-console/frontend/app/data/pom-dependencies.json
@@ -16,7 +16,7 @@
         {"groupId": "com.mchange", "artifactId": "mchange-commons-java", "version": "0.2.11"}
     ],
     "Hive": [
-        {"groupId": "org.apache.hive", "artifactId": "hive-jdbc", "version": "3.1.1", "exclude": [{ "groupId": "org.eclipse.jetty", "artifactId": "*" }]},
+        {"groupId": "org.apache.hive", "artifactId": "hive-jdbc", "version": "3.1.1", "exclude": [{ "groupId": "org.eclipse.jetty.aggregate", "artifactId": "*" }]},
         {"groupId": "com.mchange", "artifactId": "c3p0", "version": "0.9.5.2"},
         {"groupId": "com.mchange", "artifactId": "mchange-commons-java", "version": "0.2.11"}
     ],


[ignite] 02/31: GG-19066 [IGNITE-10983] Check that persistenceEnabled is consistent on all nodes.

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch gg-19225
in repository https://gitbox.apache.org/repos/asf/ignite.git

commit 9d9c21af5577189df18ba937f0013a81f9001745
Author: mstepachev <ma...@gmail.com>
AuthorDate: Wed May 29 17:10:50 2019 +0300

    GG-19066 [IGNITE-10983] Check that persistenceEnabled is consistent on all nodes.
---
 .../processors/cache/GridCacheProcessor.java       |  92 ++++-
 .../internal/processors/cache/GridCacheUtils.java  |  38 ++
 ...heWithDifferentDataRegionConfigurationTest.java | 409 +++++++++++++++++++++
 .../ignite/testsuites/IgniteCacheTestSuite.java    |   2 +
 4 files changed, 540 insertions(+), 1 deletion(-)

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 b623801..cb82a37 100644
--- 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
@@ -28,6 +28,7 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.ListIterator;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Set;
 import java.util.UUID;
 import java.util.concurrent.ConcurrentHashMap;
@@ -35,6 +36,7 @@ import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 import javax.cache.configuration.FactoryBuilder;
 import javax.cache.expiry.EternalExpiryPolicy;
 import javax.cache.expiry.ExpiryPolicy;
@@ -56,6 +58,7 @@ import org.apache.ignite.cluster.ClusterGroup;
 import org.apache.ignite.cluster.ClusterNode;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.DataPageEvictionMode;
+import org.apache.ignite.configuration.DataRegionConfiguration;
 import org.apache.ignite.configuration.DataStorageConfiguration;
 import org.apache.ignite.configuration.DeploymentMode;
 import org.apache.ignite.configuration.FileSystemConfiguration;
@@ -207,6 +210,7 @@ import static org.apache.ignite.internal.IgniteComponentType.JTA;
 import static org.apache.ignite.internal.IgniteFeatures.TRANSACTION_OWNER_THREAD_DUMP_PROVIDING;
 import static org.apache.ignite.internal.IgniteNodeAttributes.ATTR_CONSISTENCY_CHECK_SKIPPED;
 import static org.apache.ignite.internal.IgniteNodeAttributes.ATTR_TX_CONFIG;
+import static org.apache.ignite.internal.processors.cache.GridCacheUtils.isDefaultDataRegionPersistent;
 import static org.apache.ignite.internal.processors.cache.GridCacheUtils.isNearEnabled;
 import static org.apache.ignite.internal.processors.cache.GridCacheUtils.isPersistentCache;
 import static org.apache.ignite.internal.util.IgniteUtils.doInParallel;
@@ -224,6 +228,11 @@ public class GridCacheProcessor extends GridProcessorAdapter {
     private static final String MERGE_OF_CONFIG_REQUIRED_MESSAGE = "Failed to join node to the active cluster " +
         "(the config of the cache '%s' has to be merged which is impossible on active grid). " +
         "Deactivate grid and retry node join or clean the joining node.";
+
+    /** Invalid region configuration message. */
+    private static final String INVALID_REGION_CONFIGURATION_MESSAGE = "Failed to join node " +
+        "(Incompatible data region configuration [region=%s, locNodeId=%s, isPersistenceEnabled=%s, rmtNodeId=%s, isPersistenceEnabled=%s])";
+
     /** */
     private final boolean startClientCaches =
         IgniteSystemProperties.getBoolean(IgniteSystemProperties.IGNITE_START_CACHES_ON_JOIN, false);
@@ -2799,7 +2808,7 @@ public class GridCacheProcessor extends GridProcessorAdapter {
 
         String memPlcName = cfg.getDataRegionName();
 
-        DataRegion dataRegion = sharedCtx.database().dataRegion(memPlcName);
+        DataRegion dataRegion = affNode ? sharedCtx.database().dataRegion(memPlcName) : null;
         FreeList freeList = sharedCtx.database().freeList(memPlcName);
         ReuseList reuseList = sharedCtx.database().reuseList(memPlcName);
 
@@ -3127,6 +3136,32 @@ public class GridCacheProcessor extends GridProcessorAdapter {
     }
 
     /**
+     * @param node Remote node to check.
+     * @return Data storage configuration
+     */
+    private DataStorageConfiguration extractDataStorage(ClusterNode rmtNode) {
+        return GridCacheUtils.extractDataStorage(
+            rmtNode,
+            ctx.marshallerContext().jdkMarshaller(),
+            U.resolveClassLoader(ctx.config())
+        );
+    }
+
+    /**
+     * @param dataStorageCfg User-defined data regions.
+     */
+    private Map<String, DataRegionConfiguration> dataRegionCfgs(DataStorageConfiguration dataStorageCfg) {
+        if (dataStorageCfg != null) {
+            return Optional.ofNullable(dataStorageCfg.getDataRegionConfigurations())
+                .map(Stream::of)
+                .orElseGet(Stream::empty)
+                .collect(Collectors.toMap(DataRegionConfiguration::getName, e -> e));
+        }
+
+        return Collections.emptyMap();
+    }
+
+    /**
      * Force checkpoint and remove offheap checkpoint listener after it was finished.
      *
      * @param grpToStop Cache group to stop.
@@ -3417,6 +3452,15 @@ public class GridCacheProcessor extends GridProcessorAdapter {
 
             StringBuilder errorMessage = new StringBuilder();
 
+            if (!node.isClient()) {
+                validateRmtRegions(node).forEach(error -> {
+                    if (errorMessage.length() > 0)
+                        errorMessage.append("\n");
+
+                    errorMessage.append(error);
+                });
+            }
+
             for (CacheJoinNodeDiscoveryData.CacheInfo cacheInfo : nodeData.caches().values()) {
                 try {
                     byte[] secCtxBytes = node.attribute(IgniteNodeAttributes.ATTR_SECURITY_SUBJECT_V2);
@@ -3534,6 +3578,52 @@ public class GridCacheProcessor extends GridProcessorAdapter {
     }
 
     /**
+     * @param rmtNode Joining node.
+     * @return List of validation errors.
+     */
+    private List<String> validateRmtRegions(ClusterNode rmtNode) {
+        List<String> errorMessages = new ArrayList<>();
+
+        DataStorageConfiguration rmtStorageCfg = extractDataStorage(rmtNode);
+        Map<String, DataRegionConfiguration> rmtRegionCfgs = dataRegionCfgs(rmtStorageCfg);
+
+        DataStorageConfiguration locStorageCfg = ctx.config().getDataStorageConfiguration();
+
+        if (isDefaultDataRegionPersistent(locStorageCfg) != isDefaultDataRegionPersistent(rmtStorageCfg)) {
+            errorMessages.add(String.format(
+                INVALID_REGION_CONFIGURATION_MESSAGE,
+                "DEFAULT",
+                ctx.localNodeId(),
+                isDefaultDataRegionPersistent(locStorageCfg),
+                rmtNode.id(),
+                isDefaultDataRegionPersistent(rmtStorageCfg)
+            ));
+        }
+
+        for (ClusterNode clusterNode : ctx.discovery().aliveServerNodes()) {
+            Map<String, DataRegionConfiguration> nodeRegionCfg = dataRegionCfgs(extractDataStorage(clusterNode));
+
+            for (Map.Entry<String, DataRegionConfiguration> nodeRegionCfgEntry : nodeRegionCfg.entrySet()) {
+                String regionName = nodeRegionCfgEntry.getKey();
+
+                DataRegionConfiguration rmtRegionCfg = rmtRegionCfgs.get(regionName);
+
+                if (rmtRegionCfg != null && rmtRegionCfg.isPersistenceEnabled() != nodeRegionCfgEntry.getValue().isPersistenceEnabled())
+                    errorMessages.add(String.format(
+                        INVALID_REGION_CONFIGURATION_MESSAGE,
+                        regionName,
+                        ctx.localNodeId(),
+                        nodeRegionCfgEntry.getValue().isPersistenceEnabled(),
+                        rmtNode.id(),
+                        rmtRegionCfg.isPersistenceEnabled()
+                    ));
+            }
+        }
+
+        return errorMessages;
+    }
+
+    /**
      * Cache statistics clear message received.
      *
      * @param msg Message.
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheUtils.java
index 0d8acd2..a2031a3 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheUtils.java
@@ -98,6 +98,7 @@ import org.apache.ignite.lang.IgniteInClosure;
 import org.apache.ignite.lang.IgnitePredicate;
 import org.apache.ignite.lang.IgniteReducer;
 import org.apache.ignite.lifecycle.LifecycleAware;
+import org.apache.ignite.marshaller.jdk.JdkMarshaller;
 import org.apache.ignite.plugin.CachePluginConfiguration;
 import org.apache.ignite.plugin.security.SecurityException;
 import org.apache.ignite.spi.encryption.EncryptionSpi;
@@ -1873,6 +1874,43 @@ public class GridCacheUtils {
     }
 
     /**
+     * @return {@code true} if persistence is enabled for a default data region, {@code false} if not.
+     */
+    public static boolean isDefaultDataRegionPersistent(DataStorageConfiguration cfg) {
+        if (cfg == null)
+            return false;
+
+        DataRegionConfiguration dfltRegionCfg = cfg.getDefaultDataRegionConfiguration();
+
+        if (dfltRegionCfg == null)
+            return false;
+
+        return dfltRegionCfg.isPersistenceEnabled();
+    }
+
+    /**
+     * Extract and unmarshal data storage configuration from given node.
+     *
+     * @param node Source of data storage configuration.
+     * @return Data storage configuration for given node, or {@code null} if this node has not data storage
+     * configuration.
+     */
+    @Nullable public static DataStorageConfiguration extractDataStorage(ClusterNode node, JdkMarshaller marshaller,
+        ClassLoader clsLdr) {
+        Object dsCfgBytes = node.attribute(IgniteNodeAttributes.ATTR_DATA_STORAGE_CONFIG);
+
+        if (dsCfgBytes instanceof byte[]) {
+            try {
+                return marshaller.unmarshal((byte[])dsCfgBytes, clsLdr);
+            }
+            catch (IgniteCheckedException e) {
+                throw new IgniteException(e);
+            }
+        }
+        return null;
+    }
+
+    /**
      * @return {@code true} if persistence is enabled for at least one data region, {@code false} if not.
      */
     public static boolean isPersistenceEnabled(DataStorageConfiguration cfg) {
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheWithDifferentDataRegionConfigurationTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheWithDifferentDataRegionConfigurationTest.java
new file mode 100644
index 0000000..059b77f
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheWithDifferentDataRegionConfigurationTest.java
@@ -0,0 +1,409 @@
+/*
+ * Copyright 2019 GridGain Systems, Inc. and Contributors.
+ *
+ * Licensed under the GridGain Community Edition License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
+ *
+ * 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.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.DataRegionConfiguration;
+import org.apache.ignite.configuration.DataStorageConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.util.typedef.X;
+import org.apache.ignite.lang.IgnitePredicate;
+import org.apache.ignite.spi.IgniteSpiException;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.jetbrains.annotations.Nullable;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.apache.ignite.testframework.GridTestUtils.assertThrowsWithCause;
+
+/**
+ * Data regions validation test on joining node.
+ */
+public class CacheWithDifferentDataRegionConfigurationTest extends GridCommonAbstractTest {
+    /** Node 1. */
+    private static final int NODE_1 = 0;
+
+    /** Node 2. */
+    private static final int NODE_2 = 1;
+
+    /** Node 3. */
+    private static final int NODE_3 = 2;
+
+    /** Region 1. */
+    private static final String REGION_1 = "region_1";
+
+    /** Region 2. */
+    private static final String REGION_2 = "region_2";
+
+    /** Region 3. */
+    private static final String REGION_3 = "region_3";
+
+    /** Region 4. */
+    private static final String REGION_4 = "region_4";
+
+    /** Cache 1. */
+    private static final String CACHE_1 = "cache_1";
+
+    /** Cache 2. */
+    private static final String CACHE_2 = "cache_2";
+
+    /** Persistence. */
+    private static final boolean PERSISTENCE = true;
+
+    /** Memory. */
+    private static final boolean MEMORY = false;
+
+    /**
+     * @throws Exception If failed.
+     */
+    @After
+    public void tearDown() throws Exception {
+        stopAllGrids();
+        cleanPersistenceDir();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Before
+    public void setUp() throws Exception {
+        super.setUp();
+        cleanPersistenceDir();
+    }
+
+    /**
+     *
+     */
+    @Test
+    public void twoNodesHaveDifferentDefaultConfigurationUnacceptable() throws Exception {
+        node(NODE_1)
+            .withDefaultRegion("defaultName1", MEMORY)
+            .andCache(CACHE_1)
+            .start();
+
+        assertThrowsContainsMessage(() -> node(NODE_2).withDefaultRegion("defaultName2", PERSISTENCE).andCache(CACHE_2).start(),
+            IgniteSpiException.class,
+            "Failed to join node (Incompatible data region configuration [region=DEFAULT"
+        );
+    }
+
+    /**
+     *
+     */
+    @Test
+    public void twoNodesHaveCommonDefaultConfigurationAcceptable() throws Exception {
+        IgniteEx node1 = node(NODE_1)
+            .withDefaultRegion("defaultName1", PERSISTENCE)
+            .andCache(CACHE_1)
+            .start();
+
+        IgniteEx node2 = node(NODE_2)
+            .withDefaultRegion("defaultName2", PERSISTENCE)
+            .andCache(CACHE_2)
+            .start();
+
+        node1.cluster().active(true);
+
+        populateCache(node1, CACHE_1, 1000);
+        populateCache(node2, CACHE_2, 350);
+
+        assertThatCacheContains(node2, CACHE_1, 1000);
+        assertThatCacheContains(node1, CACHE_2, 350);
+    }
+
+    /**
+     *
+     */
+    @Test
+    public void firstNodeHasDefaultAndSecondDefaultWithCustomNameAcceptable() throws Exception {
+        IgniteEx node1 = node(NODE_1)
+            .andCache(CACHE_1)
+            .start();
+
+        IgniteEx node2 = node(NODE_2)
+            .withDefaultRegion("defaultName2", MEMORY)
+            .andCache(CACHE_2)
+            .start();
+
+        node1.cluster().active(true);
+
+        populateCache(node1, CACHE_1, 1000);
+        populateCache(node2, CACHE_2, 350);
+
+        assertThatCacheContains(node2, CACHE_1, 1000);
+        assertThatCacheContains(node1, CACHE_2, 350);
+    }
+
+    /**
+     *
+     */
+    @Test
+    public void firstNodeHasDefaultAndSecondWithTwoRegionsDefaultAndPersistenceAcceptable() throws Exception {
+        IgniteEx node1 = node(NODE_1)
+            .andCache(CACHE_1)
+            .start();
+
+        IgniteEx node2 = node(NODE_2)
+            .withRegion(REGION_1, MEMORY)
+            .withRegion(REGION_2, PERSISTENCE)
+            .andExclusiveCache(CACHE_2, REGION_2)
+            .start();
+
+        node1.cluster().active(true);
+
+        populateCache(node1, CACHE_1, 1000);
+        populateCache(node2, CACHE_2, 350);
+
+        assertThatCacheContains(node2, CACHE_1, 1000);
+        assertThatCacheContains(node1, CACHE_2, 350);
+    }
+
+    /**
+     *
+     */
+    @Test
+    public void twoNodesHaveTwoNonOverlappingRegionsAcceptable() throws Exception {
+        IgniteEx node1 = node(NODE_1)
+            .withRegion(REGION_1, PERSISTENCE)
+            .withRegion(REGION_2, MEMORY)
+            .andExclusiveCache(CACHE_1, REGION_1)
+            .start();
+
+        IgniteEx node2 = node(NODE_2)
+            .withRegion(REGION_3, MEMORY)
+            .withRegion(REGION_4, PERSISTENCE)
+            .andExclusiveCache(CACHE_2, REGION_4)
+            .start();
+
+        node1.cluster().active(true);
+
+        populateCache(node1, CACHE_1, 1000);
+        populateCache(node2, CACHE_2, 350);
+
+        assertThatCacheContains(node2, CACHE_1, 1000);
+        assertThatCacheContains(node1, CACHE_2, 350);
+    }
+
+    /**
+     *
+     */
+    @Test
+    public void twoNodesWithSameRegionsButDifferentPersistenceModeForThemUnacceptable() throws Exception {
+        node(NODE_1)
+            .withRegion(REGION_1, PERSISTENCE)
+            .start();
+
+        assertThrowsContainsMessage(() -> node(NODE_2).withRegion(REGION_1, MEMORY).start(),
+            IgniteSpiException.class,
+            "Failed to join node (Incompatible data region configuration [region=" + REGION_1
+        );
+    }
+
+    /**
+     *
+     */
+    @Test
+    public void secondNodeMustRejectJoinOnThirdNode() throws Exception {
+        node(NODE_1)
+            .start();
+
+        node(NODE_2)
+            .withRegion(REGION_2, PERSISTENCE)
+            .start();
+
+        assertThrowsContainsMessage(() -> node(NODE_3).withRegion(REGION_2, MEMORY).start(),
+            IgniteSpiException.class,
+            "Failed to join node (Incompatible data region configuration [region=" + REGION_2
+        );
+    }
+
+    /**
+     * @param call Callable.
+     * @param cls Class.
+     * @param msg Message.
+     */
+    private void assertThrowsContainsMessage(Callable<?> call, Class<? extends Throwable> cls, String msg) {
+        Throwable throwable = assertThrowsWithCause(call, cls);
+
+        assertTrue("Message mismatch: " + msg, X.hasCause(throwable, msg, cls));
+    }
+
+    /**
+     * @param node Node.
+     * @param cacheName Cache name.
+     * @param size Size.
+     */
+    private void assertThatCacheContains(IgniteEx node, String cacheName, int size) {
+        IgniteCache<Integer, Integer> cache = node.getOrCreateCache(cacheName);
+
+        for (int i = 0; i < size; i++)
+            assertEquals((Integer)i, cache.get(i));
+    }
+
+    /**
+     * @param node Node.
+     * @param cacheName Cache name.
+     * @param size Size.
+     */
+    public void populateCache(IgniteEx node, String cacheName, int size) {
+        IgniteCache<Integer, Integer> cache = node.getOrCreateCache(cacheName);
+
+        for (int i = 0; i < size; i++)
+            cache.put(i, i);
+    }
+
+    /**
+     * @param gridId Grid id.
+     */
+    private ConfigurationBuilder node(int gridId) {
+        return new ConfigurationBuilder(gridId);
+    }
+
+    /**
+     *
+     */
+    private static class NodeFilter implements IgnitePredicate<ClusterNode> {
+        /**
+         *
+         */
+        private final String consistenceId;
+
+        /**
+         *
+         */
+        private NodeFilter(String consistenceId) {
+            this.consistenceId = consistenceId;
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean apply(ClusterNode clusterNode) {
+
+            return clusterNode.consistentId().equals(consistenceId);
+        }
+    }
+
+    /**
+     *
+     */
+    private class ConfigurationBuilder {
+        /** Grid id. */
+        private final String gridName;
+
+        /** Regions. */
+        private final List<DataRegionConfiguration> regions = new ArrayList<>();
+
+        /** Caches. */
+        private final List<CacheConfiguration> caches = new ArrayList<>();
+
+        /** Default region configuration. */
+        @Nullable private DataRegionConfiguration dfltRegionConfiguration;
+
+        /**
+         * @param gridId Grid id.
+         */
+        ConfigurationBuilder(int gridId) {
+            this.gridName = getTestIgniteInstanceName(gridId);
+        }
+
+        /**
+         * @param regionName Region name.
+         * @param persistence Persistence.
+         */
+        ConfigurationBuilder withDefaultRegion(String regionName, boolean persistence) {
+            dfltRegionConfiguration = new DataRegionConfiguration()
+                .setName(regionName)
+                .setInitialSize(100L * 1024 * 1024)
+                .setMaxSize(500L * 1024 * 1024)
+                .setPersistenceEnabled(persistence);
+
+            return this;
+        }
+
+        /**
+         * @param regionName Region name.
+         * @param persistence Persistence.
+         */
+        ConfigurationBuilder withRegion(String regionName, boolean persistence) {
+            regions.add(new DataRegionConfiguration()
+                .setName(regionName)
+                .setInitialSize(100L * 1024 * 1024)
+                .setMaxSize(500L * 1024 * 1024)
+                .setPersistenceEnabled(persistence)
+            );
+
+            return this;
+        }
+
+        /**
+         * @param cacheName Cache name.
+         */
+        ConfigurationBuilder andCache(String cacheName) {
+            return andCache(cacheName, null);
+        }
+
+        /**
+         * @param cacheName Cache name.
+         * @param regionName Region name.
+         */
+        ConfigurationBuilder andCache(String cacheName, String regionName) {
+            caches.add(new CacheConfiguration().setDataRegionName(regionName).setName(cacheName));
+
+            return this;
+        }
+
+        /**
+         * This cache related with node via node filter.
+         *
+         * @param cacheName Cache name.
+         * @param regionName Region name.
+         */
+        ConfigurationBuilder andExclusiveCache(String cacheName, String regionName) {
+            caches.add(new CacheConfiguration()
+                .setNodeFilter(new NodeFilter(gridName))
+                .setDataRegionName(regionName)
+                .setName(cacheName)
+            );
+
+            return this;
+        }
+
+        /** Start node from builder */
+        public IgniteEx start() throws Exception {
+            IgniteConfiguration cfg = getConfiguration(gridName);
+
+            cfg.setConsistentId(gridName);
+
+            DataStorageConfiguration storageCfg = new DataStorageConfiguration();
+            storageCfg.setDataRegionConfigurations(regions.toArray(new DataRegionConfiguration[regions.size()]));
+            cfg.setDataStorageConfiguration(storageCfg);
+
+            if (dfltRegionConfiguration != null)
+                storageCfg.setDefaultDataRegionConfiguration(dfltRegionConfiguration);
+
+            cfg.setCacheConfiguration(caches.toArray(new CacheConfiguration[caches.size()]));
+
+            return startGrid(cfg);
+        }
+    }
+}
\ No newline at end of file
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 8d48ad4..7232874 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
@@ -52,6 +52,7 @@ import org.apache.ignite.internal.processors.cache.CacheNamesSelfTest;
 import org.apache.ignite.internal.processors.cache.CacheNamesWithSpecialCharactersTest;
 import org.apache.ignite.internal.processors.cache.CachePutEventListenerErrorSelfTest;
 import org.apache.ignite.internal.processors.cache.CacheTxFastFinishTest;
+import org.apache.ignite.internal.processors.cache.CacheWithDifferentDataRegionConfigurationTest;
 import org.apache.ignite.internal.processors.cache.DataStorageConfigurationValidationTest;
 import org.apache.ignite.internal.processors.cache.GridCacheAffinityApiSelfTest;
 import org.apache.ignite.internal.processors.cache.GridCacheAffinityMapperSelfTest;
@@ -231,6 +232,7 @@ public class IgniteCacheTestSuite {
         GridTestUtils.addTestIfNeeded(suite, GridCacheConfigurationValidationSelfTest.class, ignoredTests);
         GridTestUtils.addTestIfNeeded(suite, GridCacheConfigurationConsistencySelfTest.class, ignoredTests);
         GridTestUtils.addTestIfNeeded(suite, GridDataStorageConfigurationConsistencySelfTest.class, ignoredTests);
+        GridTestUtils.addTestIfNeeded(suite, CacheWithDifferentDataRegionConfigurationTest.class, ignoredTests);
         GridTestUtils.addTestIfNeeded(suite, DataStorageConfigurationValidationTest.class, ignoredTests);
         GridTestUtils.addTestIfNeeded(suite, GridCacheJdbcBlobStoreSelfTest.class, ignoredTests);
         GridTestUtils.addTestIfNeeded(suite, GridCacheJdbcBlobStoreMultithreadedSelfTest.class, ignoredTests);


[ignite] 18/31: ignoring tests

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch gg-19225
in repository https://gitbox.apache.org/repos/asf/ignite.git

commit 034681fc86728f11292b96734fcc48259801aa6f
Author: Eduard Shangareev <es...@gridgain.com>
AuthorDate: Fri May 31 04:17:42 2019 +0300

    ignoring tests
---
 .../internal/processors/cache/CacheSerializableTransactionsTest.java  | 3 +++
 .../cache/transactions/TxDataConsistencyOnCommitFailureTest.java      | 4 ++--
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheSerializableTransactionsTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheSerializableTransactionsTest.java
index c5d84a8..3e72798 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheSerializableTransactionsTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheSerializableTransactionsTest.java
@@ -72,6 +72,7 @@ import org.apache.ignite.transactions.Transaction;
 import org.apache.ignite.transactions.TransactionConcurrency;
 import org.apache.ignite.transactions.TransactionIsolation;
 import org.apache.ignite.transactions.TransactionOptimisticException;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -2833,6 +2834,7 @@ public class CacheSerializableTransactionsTest extends GridCommonAbstractTest {
     /**
      * @throws Exception If failed.
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9226")
     @Test
     public void testReadWriteTransactionsNoDeadlock() throws Exception {
         checkReadWriteTransactionsNoDeadlock(false);
@@ -2841,6 +2843,7 @@ public class CacheSerializableTransactionsTest extends GridCommonAbstractTest {
     /**
      * @throws Exception If failed.
      */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9226")
     @Test
     public void testReadWriteTransactionsNoDeadlockMultinode() throws Exception {
         checkReadWriteTransactionsNoDeadlock(true);
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TxDataConsistencyOnCommitFailureTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TxDataConsistencyOnCommitFailureTest.java
index 7f824b3..93d3956 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TxDataConsistencyOnCommitFailureTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TxDataConsistencyOnCommitFailureTest.java
@@ -32,11 +32,11 @@ import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxLocal;
 import org.apache.ignite.internal.util.typedef.G;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
-import org.apache.ignite.testsuites.IgniteIgnore;
 import org.apache.ignite.transactions.Transaction;
 import org.apache.ignite.transactions.TransactionConcurrency;
 import org.apache.ignite.transactions.TransactionIsolation;
 import org.jetbrains.annotations.Nullable;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -118,7 +118,7 @@ public class TxDataConsistencyOnCommitFailureTest extends GridCommonAbstractTest
     }
 
     /** */
-    @IgniteIgnore(value = "https://issues.apache.org/jira/browse/IGNITE-9806", forceFailure = false)
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-9806")
     @Test
     public void testCommitErrorOnColocatedNode2PC() throws Exception {
         nodesCnt = 3;


[ignite] 04/31: GG-18749 Web console: Fixed template for "Eviction mode". Fixes #71.

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch gg-19225
in repository https://gitbox.apache.org/repos/asf/ignite.git

commit 374db46d252fffc6e973b6c9806a0dbcee2ac4a6
Author: Vasiliy Sisko <vs...@gridgain.com>
AuthorDate: Thu May 30 13:40:51 2019 +0700

    GG-18749 Web console: Fixed template for "Eviction mode". Fixes #71.
    
    (cherry picked from commit 4aa934999217763965500b6abcf67ab515400058)
---
 .../components/cluster-edit-form/templates/memory.pug          | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cluster-edit-form/templates/memory.pug b/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cluster-edit-form/templates/memory.pug
index ca25dd0..8df0183 100644
--- a/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cluster-edit-form/templates/memory.pug
+++ b/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/cluster-edit-form/templates/memory.pug
@@ -165,11 +165,11 @@ ng-show='$ctrl.available(["2.0.0", "2.3.0"])'
                                             model: '$item.pageEvictionMode',
                                             name: '"MemoryPolicyPageEvictionMode"',
                                             placeholder: 'DISABLED',
-                                            options: `[
-                                                {value: "DISABLED", label: "DISABLED"},
-                                                {value: "RANDOM_LRU", label: "RANDOM_LRU"},
-                                                {value: "RANDOM_2_LRU", label: "RANDOM_2_LRU"}
-                                            ]`,
+                                            options: '[\
+                                                {value: "DISABLED", label: "DISABLED"},\
+                                                {value: "RANDOM_LRU", label: "RANDOM_LRU"},\
+                                                {value: "RANDOM_2_LRU", label: "RANDOM_2_LRU"}\
+                                            ]',
                                             tip: 'An algorithm for memory pages eviction\
                                                  <ul>\
                                                     <li>DISABLED - Eviction is disabled</li>\