ignite-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From akuznet...@apache.org
Subject [23/43] ignite git commit: IEP-4 Baseline topology for persistent caches (Phase 1) Contributed by: Dmitriy Govorukhin <dmitriy.govorukhin@gmail.com> Dmitry Pavlov <dpavlov.spb@gmail.com> Eduard Shangareev <eduard.shangareev@gmail.com> Ily
Date Wed, 17 Jan 2018 12:23:21 GMT
http://git-wip-us.apache.org/repos/asf/ignite/blob/6f7aba85/modules/dev-utils/src/main/java/org/apache/ignite/development/utils/IgniteWalConverter.java
----------------------------------------------------------------------
diff --git a/modules/dev-utils/src/main/java/org/apache/ignite/development/utils/IgniteWalConverter.java b/modules/dev-utils/src/main/java/org/apache/ignite/development/utils/IgniteWalConverter.java
index f3268d9..2da1aa3 100644
--- a/modules/dev-utils/src/main/java/org/apache/ignite/development/utils/IgniteWalConverter.java
+++ b/modules/dev-utils/src/main/java/org/apache/ignite/development/utils/IgniteWalConverter.java
@@ -18,6 +18,7 @@
 package org.apache.ignite.development.utils;
 
 import java.io.File;
+import org.apache.ignite.IgniteSystemProperties;
 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;
@@ -30,6 +31,7 @@ import org.apache.ignite.internal.processors.query.h2.database.io.H2InnerIO;
 import org.apache.ignite.internal.processors.query.h2.database.io.H2LeafIO;
 import org.apache.ignite.lang.IgniteBiTuple;
 import org.apache.ignite.logger.NullLogger;
+import org.jetbrains.annotations.Nullable;
 
 /**
  * Print WAL log data in human-readable form.
@@ -41,7 +43,7 @@ public class IgniteWalConverter {
     public static void main(String[] args) throws Exception {
         if (args.length < 2)
             throw new IllegalArgumentException("\nYou need to provide:\n" +
-                    "\t1. Size of pages (1024, 2048, etc).\n" +
+                    "\t1. Size of pages, which was selected for file store (1024, 2048, 4096, etc).\n" +
                     "\t2. Path to dir with wal files.\n" +
                     "\t3. (Optional) Path to dir with archive wal files.");
 
@@ -49,6 +51,9 @@ public class IgniteWalConverter {
         H2ExtrasInnerIO.register();
         H2ExtrasLeafIO.register();
 
+        boolean printRecords = IgniteSystemProperties.getBoolean("PRINT_RECORDS", false);
+        boolean printStat = IgniteSystemProperties.getBoolean("PRINT_STAT", true);
+
         final IgniteWalIteratorFactory factory = new IgniteWalIteratorFactory(new NullLogger(),
             Integer.parseInt(args[0]),
             null,
@@ -62,11 +67,20 @@ public class IgniteWalConverter {
         if (workFiles == null)
             throw new IllegalArgumentException("No .wal files in dir: " + args[1]);
 
+        @Nullable final WalStat stat = printStat ? new WalStat() : null;
+
         try (WALIterator stIt = factory.iteratorWorkFiles(workFiles)) {
             while (stIt.hasNextX()) {
                 IgniteBiTuple<WALPointer, WALRecord> next = stIt.nextX();
 
-                System.out.println("[W] " + next.get2());
+                final WALPointer pointer = next.get1();
+                final WALRecord record = next.get2();
+
+                if (stat != null)
+                    stat.registerRecord(record, pointer, true);
+
+                if (printRecords)
+                    System.out.println("[W] " + record);
             }
         }
 
@@ -77,9 +91,21 @@ public class IgniteWalConverter {
                 while (stIt.hasNextX()) {
                     IgniteBiTuple<WALPointer, WALRecord> next = stIt.nextX();
 
-                    System.out.println("[A] " + next.get2());
+                    final WALPointer pointer = next.get1();
+                    final WALRecord record = next.get2();
+
+                    if (stat != null)
+                        stat.registerRecord(record, pointer, false);
+
+                    if (printRecords)
+                        System.out.println("[A] " + record);
                 }
             }
         }
+
+        System.err.flush();
+
+        if (stat != null)
+            System.out.println("Statistic collected:\n" + stat.toString());
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/6f7aba85/modules/dev-utils/src/main/java/org/apache/ignite/development/utils/RecordSizeCountStat.java
----------------------------------------------------------------------
diff --git a/modules/dev-utils/src/main/java/org/apache/ignite/development/utils/RecordSizeCountStat.java b/modules/dev-utils/src/main/java/org/apache/ignite/development/utils/RecordSizeCountStat.java
new file mode 100644
index 0000000..1d0a1c0
--- /dev/null
+++ b/modules/dev-utils/src/main/java/org/apache/ignite/development/utils/RecordSizeCountStat.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.development.utils;
+
+/**
+ * Statistic for record size, used to accumulate information about several record and calculating average.
+ */
+public class RecordSizeCountStat {
+    /** Sum of sizes. */
+    private long size = -1;
+
+    /** Count of all records. */
+    private int cnt;
+
+    /**
+     * @param size record size. Negative value means size is unknown for current occurrence. Any negative value resets
+     * accumulated statistics.
+     */
+    void occurrence(int size) {
+        if (size >= 0) {
+            if (this.size < 0)
+                this.size = 0;
+
+            this.size += size;
+        }
+        else {
+            if (this.size > 0)
+                this.size = -1;
+        }
+
+        cnt++;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return (size >= 0 ? size : "") +
+            "\t " + cnt +
+            "\t " + ((size >= 0) ? size / cnt : "");
+    }
+
+    /**
+     * @return average size of one record, as double.
+     */
+    private double averageD() {
+        return 1.0 * size / cnt;
+    }
+
+    /**
+     * @return average size of one record, printable version.
+     */
+    String averageStr() {
+        return cnt == 0 ? "" : String.format("%.2f", averageD());
+    }
+
+    /**
+     * @return Count of all records.
+     */
+    int getCount() {
+        return cnt;
+    }
+
+    /**
+     * @param val other statistic value to reduce with.
+     */
+    void add(RecordSizeCountStat val) {
+        cnt += val.cnt;
+        size += val.size;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/6f7aba85/modules/dev-utils/src/main/java/org/apache/ignite/development/utils/TxWalStat.java
----------------------------------------------------------------------
diff --git a/modules/dev-utils/src/main/java/org/apache/ignite/development/utils/TxWalStat.java b/modules/dev-utils/src/main/java/org/apache/ignite/development/utils/TxWalStat.java
new file mode 100644
index 0000000..a45b8ea
--- /dev/null
+++ b/modules/dev-utils/src/main/java/org/apache/ignite/development/utils/TxWalStat.java
@@ -0,0 +1,318 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.development.utils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import org.apache.ignite.internal.pagemem.wal.record.DataEntry;
+import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
+
+/**
+ * Transactions statistics for WAL.
+ */
+public class TxWalStat {
+    /** Maximum element in popular combinations discovery map before eviction. */
+    private static final int POPULAR_COMBINATION_MAP_MAX_SIZE = 50000;
+
+    /** Usages count, when evict prohibited from popular combinations discovery map. */
+    private static final int USAGES_CNT_EVICT_PROHIBITED = 10;
+
+    /** Transactions in preparing/committing state. When commit is finished, TX is removed from this collection. */
+    private final Map<GridCacheVersion, TxOccurrence> opened = new HashMap<>();
+
+    /** Field for calculating average number of primary nodes involved in Tx. */
+    private final RecordSizeCountStat avgPrimaryNodes = new RecordSizeCountStat();
+
+    /** Field for calculating average number of total nodes involved in Tx. */
+    private final RecordSizeCountStat avgTotalNodes = new RecordSizeCountStat();
+
+    /** Tx statistics: Entries updated count -> count of such Txes. */
+    private final Map<Integer, Integer> txEntriesUpdated = new TreeMap<>();
+
+    /** Tx statistics: Caches Involved  count -> count of such Txes.  */
+    private final Map<Integer, Integer> txCachesInvolved = new TreeMap<>();
+
+    /** Cache IDs combination involved in Tx. Popular combination search map, with possible eviction. */
+    private final LruMap<String> cacheIdsInTx = new LruMap<>(POPULAR_COMBINATION_MAP_MAX_SIZE,
+        USAGES_CNT_EVICT_PROHIBITED);
+
+    /**
+     * Cache IDs combination involved in Tx, weighted using primary nodes in Tx. Used to search popular combinations
+     * mostly involved into highly distributive transactions.
+     */
+    private final LruMap<String> cacheIdsWeightedNodesInTx = new LruMap<>(POPULAR_COMBINATION_MAP_MAX_SIZE,
+        USAGES_CNT_EVICT_PROHIBITED * 90);
+    /**
+     * Cache IDs combination involved in Tx, weighted using total nodes in Tx. Used to search popular combinations
+     * mostly involved into highly distributive transactions.
+     */
+    private final LruMap<String> cacheIdsWeightedTotalNodesInTx = new LruMap<>(POPULAR_COMBINATION_MAP_MAX_SIZE,
+        USAGES_CNT_EVICT_PROHIBITED * 150);
+
+    /**
+     * @param key key (parameter) value found.
+     * @param map map to save increment.
+     * @param <K> type of key.
+     */
+    private static <K> void incrementStat(K key, Map<K, Integer> map) {
+        incrementStat(key, map, 1);
+    }
+
+    /**
+     * @param key key (parameter) value found.
+     * @param map map to save increment.
+     * @param increment value to increment statistic, 1 or weight of current occurrence.
+     * @param <K> type of key.
+     */
+    private static <K> void incrementStat(K key, Map<K, Integer> map, int increment) {
+        Integer val = map.get(key);
+        int recordStat = val == null ? 0 : val;
+
+        recordStat += increment;
+        map.put(key, recordStat);
+    }
+
+    /**
+     * Handles TX prepare: creates TX in {@link #opened} map.
+     * @param nearXidVer near Xid Version. Global transaction identifier within cluster, assigned by transaction
+     * coordinator.
+     * @param nodes primary nodes registered in prepare record.
+     * @param totalNodes all nodes (primary & backup) in prepare record.
+     */
+    void onTxPrepareStart(GridCacheVersion nearXidVer, int nodes, int totalNodes) {
+        txComputeIfAbsent(nearXidVer, nodes, totalNodes);
+    }
+
+    /**
+     * @param nearXidVer near Xid Version. Global transaction identifier within cluster, assigned by transaction
+     * coordinator.
+     * @param nodes primary nodes registered in prepare record.
+     * @param totalNodes all nodes (primary & backup) in prepare record.
+     * @return tx occurrence to accumulate entries into.
+     */
+    private TxOccurrence txComputeIfAbsent(GridCacheVersion nearXidVer, int nodes, int totalNodes) {
+        TxOccurrence occurrence = opened.get(nearXidVer);
+
+        if (occurrence == null)
+            occurrence = new TxOccurrence(nodes, totalNodes);
+
+        opened.put(nearXidVer, occurrence);
+
+        return occurrence;
+    }
+
+    /**
+     * Handles commit or rollback transaction. Finished statistics accumulation.
+     *
+     * @param nearXidVer near Xid Version. Global transaction identifier within cluster, assigned by transaction
+     * coordinator.
+     * @param commit tx committed, flag indicating TX successes.
+     */
+    void onTxEnd(GridCacheVersion nearXidVer, boolean commit) {
+        TxOccurrence occurrence = opened.remove(nearXidVer);
+
+        if (occurrence == null)
+            return;
+
+        if (!commit)
+            return;
+
+        if (occurrence.nodes > 0 && occurrence.totalNodes > 0) {
+            avgPrimaryNodes.occurrence(occurrence.nodes);
+            avgTotalNodes.occurrence(occurrence.totalNodes);
+        }
+
+        incrementStat(occurrence.entriesUpdated, txEntriesUpdated);
+
+        incrementStat(occurrence.caches.size(), txCachesInvolved);
+
+        if (!occurrence.caches.isEmpty()) {
+            final String sortedCachesKey = occurrence.caches.toString();
+
+            incrementStat(sortedCachesKey, cacheIdsInTx.map, 1);
+
+            if (occurrence.nodes > 0)
+                incrementStat(sortedCachesKey, cacheIdsWeightedNodesInTx.map, occurrence.nodes);
+
+            if (occurrence.totalNodes > 0)
+                incrementStat(sortedCachesKey, cacheIdsWeightedTotalNodesInTx.map, occurrence.totalNodes);
+        }
+    }
+
+    /**
+     * Handles Data entry from data record. Entries not under transaction are ignored.
+     *
+     * @param entry object updated.
+     */
+    void onDataEntry(DataEntry entry) {
+        final GridCacheVersion ver = entry.nearXidVersion();
+
+        if (ver == null)
+            return;
+
+        txComputeIfAbsent(ver, -1, -1).onDataEntry(entry);
+    }
+
+    /**
+     * @param sb buffer.
+     * @param mapName display name of map.
+     * @param map values.
+     */
+    private void printSizeCountMap(StringBuilder sb, String mapName, Map<?, Integer> map) {
+        sb.append(mapName).append(": \n");
+        sb.append("key\tcount");
+        sb.append("\n");
+
+        final List<? extends Map.Entry<?, Integer>> entries = new ArrayList<>(map.entrySet());
+
+        Collections.sort(entries, new Comparator<Map.Entry<?, Integer>>() {
+            @Override public int compare(Map.Entry<?, Integer> o1, Map.Entry<?, Integer> o2) {
+                return -Integer.compare(o1.getValue(), o2.getValue());
+            }
+        });
+
+        int othersCnt = 0;
+        int othersSum = 0;
+        int cnt = 0;
+
+        for (Map.Entry<?, Integer> next : entries) {
+            if (cnt < WalStat.DISPLAY_MAX) {
+                sb.append(next.getKey()).append("\t").append(next.getValue()).append("\t");
+                sb.append("\n");
+            }
+            else {
+                othersCnt++;
+                othersSum += next.getValue();
+            }
+            cnt++;
+        }
+
+        if (othersCnt > 0) {
+            sb.append("... other ").append(othersCnt).append(" values").append("\t").append(othersSum).append("\t");
+            sb.append("\n");
+        }
+
+        sb.append("\n");
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        final StringBuilder sb = new StringBuilder();
+        sb.append("Tx stat: remained Opened: \t").append(opened.size()).append("\n").append("\n");
+
+        sb.append("Tx stat: Average Primary Node Count: \t").append(avgPrimaryNodes.averageStr()).append("\n").append("\n");
+
+        sb.append("Tx stat: Average Total Node Count: \t").append(avgTotalNodes.averageStr()).append("\n").append("\n");
+
+        printSizeCountMap(sb, "Tx stat: Entries updated", txEntriesUpdated);
+        printSizeCountMap(sb, "Tx stat: Caches involved", txCachesInvolved);
+        printSizeCountMap(sb, "Tx stat: Caches list in TX, evicted = " + cacheIdsInTx.evicted, cacheIdsInTx.map);
+
+        printSizeCountMap(sb, "Tx stat: Caches list in TX; weighted by primary Nodes, evicted = "
+            + cacheIdsWeightedNodesInTx.evicted, cacheIdsWeightedNodesInTx.map);
+
+        printSizeCountMap(sb, "Tx stat: Caches list in TX; weighted by total Nodes, evicted = "
+            + cacheIdsWeightedNodesInTx.evicted, cacheIdsWeightedNodesInTx.map);
+        return sb.toString();
+    }
+
+    /**
+     * Tx in prepare or in commit state, used to accumulate statistic.
+     */
+    private static class TxOccurrence {
+        /** Primary nodes count from TX record. */
+        private int nodes;
+        /** Primary + backup nodes count from TX record. */
+        private int totalNodes;
+
+        /** Count of entries updated under current transaction on current node. */
+        private int entriesUpdated;
+
+        /** Sorted set of cache IDs updated during this transaction. */
+        private TreeSet<Integer> caches = new TreeSet<>();
+
+        /**
+         * @param nodes Primary nodes count from TX record.
+         * @param totalNodes Primary + backup nodes count from TX record.
+         */
+        TxOccurrence(int nodes, int totalNodes) {
+            this.nodes = nodes;
+            this.totalNodes = totalNodes;
+        }
+
+        /**
+         * Handles data entry from data record.
+         * @param entry object updated.
+         */
+        void onDataEntry(DataEntry entry) {
+            entriesUpdated++;
+
+            caches.add(entry.cacheId());
+        }
+    }
+
+    /**
+     * @param <K> key type parameter.
+     */
+    private static class LruMap<K> {
+        /** Max size of map after which eviction may start. */
+        private int maxSize;
+
+        /**
+         * Evict prohibited boundary. If this number of usages is accumulate in eldest entry it will not be removed
+         * anyway.
+         */
+        private int evictProhibited;
+        /**
+         * Evicted count. Number of entries removed during statistic accumulation. Zero value means all records were
+         * processed, created top (popular combination search) is totally correct. Non zero means top may be not
+         * correct.
+         */
+        private int evicted;
+
+        /** Map with data. */
+        private Map<K, Integer> map = new LinkedHashMap<K, Integer>(16, 0.75F, false) {
+            @Override protected boolean removeEldestEntry(Map.Entry<K, Integer> eldest) {
+                if (size() < maxSize)
+                    return false;
+
+                final boolean evictNow = eldest.getValue() < evictProhibited;
+
+                if (evictNow)
+                    evicted++;
+
+                return evictNow;
+            }
+        };
+
+        /**
+         * @param maxSize Max size of map.
+         * @param evictProhibited usages count, when evict became prohibited.
+         */
+        LruMap(int maxSize, int evictProhibited) {
+            this.maxSize = maxSize;
+            this.evictProhibited = evictProhibited;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/6f7aba85/modules/dev-utils/src/main/java/org/apache/ignite/development/utils/WalStat.java
----------------------------------------------------------------------
diff --git a/modules/dev-utils/src/main/java/org/apache/ignite/development/utils/WalStat.java b/modules/dev-utils/src/main/java/org/apache/ignite/development/utils/WalStat.java
new file mode 100644
index 0000000..36933d8
--- /dev/null
+++ b/modules/dev-utils/src/main/java/org/apache/ignite/development/utils/WalStat.java
@@ -0,0 +1,327 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.development.utils;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.internal.pagemem.FullPageId;
+import org.apache.ignite.internal.pagemem.PageIdUtils;
+import org.apache.ignite.internal.pagemem.wal.WALPointer;
+import org.apache.ignite.internal.pagemem.wal.record.DataEntry;
+import org.apache.ignite.internal.pagemem.wal.record.DataRecord;
+import org.apache.ignite.internal.pagemem.wal.record.PageSnapshot;
+import org.apache.ignite.internal.pagemem.wal.record.TxRecord;
+import org.apache.ignite.internal.pagemem.wal.record.WALRecord;
+import org.apache.ignite.internal.processors.cache.persistence.tree.io.PageIO;
+import org.apache.ignite.internal.processors.cache.persistence.wal.FileWALPointer;
+import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
+import org.apache.ignite.internal.util.GridUnsafe;
+import org.apache.ignite.transactions.TransactionState;
+import sun.nio.ch.DirectBuffer;
+
+/**
+ * Statistic for overall WAL file
+ */
+public class WalStat {
+    /** Display max: top lines before merging other values */
+    static final int DISPLAY_MAX = 80;
+
+    /** Tx statistics. */
+    private TxWalStat txStat = new TxWalStat();
+
+    /** Segments source: work/archive  -> records loaded count & sizes. */
+    private final Map<String, RecordSizeCountStat> segmentsFolder = new TreeMap<>();
+
+    /** Segments index -> records loaded count & sizes. */
+    private final Map<String, RecordSizeCountStat> segmentsIndexes = new TreeMap<>();
+
+    /** Record type -> its count & sizes. */
+    private final Map<String, RecordSizeCountStat> recTypeSizes = new TreeMap<>();
+
+    /** Data Record: entries count */
+    private final Map<Integer, RecordSizeCountStat> dataRecordEntriesCnt = new TreeMap<>();
+
+    /** Data Record: is under TX */
+    private final Map<Boolean, RecordSizeCountStat> dataRecordUnderTx = new TreeMap<>();
+
+    /** Data Entry: operation performed */
+    private final Map<String, RecordSizeCountStat> dataEntryOperation = new TreeMap<>();
+
+    /** Data Entry: cache groups. */
+    private final Map<Integer, RecordSizeCountStat> dataEntryCacheId = new TreeMap<>();
+
+    /** Tx Record: action */
+    private final Map<String, RecordSizeCountStat> txRecordAct = new TreeMap<>();
+
+    /** Tx Record: participating primary nodes */
+    private final Map<Integer, RecordSizeCountStat> txRecordPrimNodesCnt = new TreeMap<>();
+
+    /** Tx Record: participating primary nodes */
+    private final Map<Integer, RecordSizeCountStat> txRecordNodesCnt = new TreeMap<>();
+
+    /** Page snapshot types. */
+    private final Map<String, RecordSizeCountStat> pageSnapshotTypes = new TreeMap<>();
+
+    /** Page snapshot indexes. */
+    private final Map<String, RecordSizeCountStat> pageSnapshotIndexes = new TreeMap<>();
+
+    /** Page snapshot cache groups. */
+    private final Map<Integer, RecordSizeCountStat> pageSnapshotCacheGrp = new TreeMap<>();
+
+    /** Page snapshot: partition ID. */
+    private final Map<Integer, RecordSizeCountStat> pageSnapshotPartId = new TreeMap<>();
+
+    /**
+     * @param key key (parameter) value.
+     * @param record record corresponding to {@code key}.
+     * @param map map to save statistics.
+     * @param <K> key type.
+     */
+    private static <K> void incrementStat(K key, WALRecord record, Map<K, RecordSizeCountStat> map) {
+        incrementStat(key, map, record.size());
+    }
+
+    /**
+     * @param key key (parameter) value.
+     * @param map  to save statistics.
+     * @param size record size for record corresponding to {@code key}. Negative value of size means size is unknown for current row.
+     * @param <K>  key type.
+     */
+    private static <K> void incrementStat(K key, Map<K, RecordSizeCountStat> map, int size) {
+        final RecordSizeCountStat val = map.get(key);
+        final RecordSizeCountStat recordStat = val == null ? new RecordSizeCountStat() : val;
+        recordStat.occurrence(size);
+        map.put(key, recordStat);
+    }
+
+    /**
+     * Handles WAL record.
+     *
+     * @param record record to handle.
+     * @param walPointer pointer, used to extract segment index.
+     * @param workDir true for work, false for archive folder.
+     */
+    void registerRecord(WALRecord record, WALPointer walPointer, boolean workDir) {
+        WALRecord.RecordType type = record.type();
+
+        if (type == WALRecord.RecordType.PAGE_RECORD)
+            registerPageSnapshot((PageSnapshot)record);
+        else if (type == WALRecord.RecordType.DATA_RECORD)
+            registerDataRecord((DataRecord)record);
+        else if (type == WALRecord.RecordType.TX_RECORD)
+            registerTxRecord((TxRecord)record);
+
+        incrementStat(type.toString(), record, recTypeSizes);
+
+        if (walPointer instanceof FileWALPointer) {
+            final FileWALPointer fPtr = (FileWALPointer)walPointer;
+
+            incrementStat(Long.toString(fPtr.index()), record, segmentsIndexes);
+            incrementStat(workDir ? "work" : "archive", record, segmentsFolder);
+        }
+    }
+
+    /**
+     * @param txRecord TX record to handle.
+     */
+    private void registerTxRecord(TxRecord txRecord) {
+        final TransactionState state = txRecord.state();
+
+        incrementStat(state.toString(), txRecord, txRecordAct);
+
+        int totalNodes = 0;
+        final Map<Short, Collection<Short>> map = txRecord.participatingNodes();
+
+        if (map != null) {
+            incrementStat(map.size(), txRecord, txRecordPrimNodesCnt);
+
+            final HashSet<Object> set = new HashSet<>(150);
+
+            for (Map.Entry<Short, Collection<Short>> next : map.entrySet()) {
+                set.add(next.getKey());
+                set.addAll(next.getValue());
+            }
+
+            totalNodes = set.size();
+
+            incrementStat(totalNodes, txRecord, txRecordNodesCnt);
+        }
+
+        final GridCacheVersion ver = txRecord.nearXidVersion();
+        if (ver != null) {
+            switch (state) {
+                case PREPARING:
+                case PREPARED:
+                    txStat.onTxPrepareStart(ver, map != null ? map.size() : 0, totalNodes);
+                    break;
+                case COMMITTED:
+                    txStat.onTxEnd(ver, true);
+                    break;
+                default:
+                    txStat.onTxEnd(ver, false);
+            }
+        }
+    }
+
+    /**
+     * @param record page snapshot record to handle.
+     */
+    private void registerPageSnapshot(PageSnapshot record) {
+        FullPageId fullPageId = record.fullPageId();
+        long pageId = fullPageId.pageId();
+
+        incrementStat(getPageType(record), record, pageSnapshotTypes);
+
+        final int idx = PageIdUtils.pageIndex(pageId);
+        final String idxAsStr = idx <= 100 ? Integer.toString(idx) : ">100";
+
+        incrementStat(idxAsStr, record, pageSnapshotIndexes);
+        incrementStat(fullPageId.groupId(), record, pageSnapshotCacheGrp);
+        incrementStat(PageIdUtils.partId(pageId), record, pageSnapshotPartId);
+    }
+
+    /**
+     * @param record data record to handle.
+     */
+    private void registerDataRecord(DataRecord record) {
+        final List<DataEntry> dataEntries = record.writeEntries();
+        if (!dataEntries.isEmpty()) {
+            boolean underTx = false;
+            for (DataEntry next : dataEntries) {
+                final int size = dataEntries.size() > 1 ? -1 : record.size();
+                incrementStat(next.op().toString(), dataEntryOperation, size);
+
+                incrementStat(next.cacheId(), dataEntryCacheId, size);
+
+                txStat.onDataEntry(next);
+
+                underTx |= next.nearXidVersion() != null;
+            }
+
+            incrementStat(underTx, record, dataRecordUnderTx);
+        }
+
+        incrementStat(dataEntries.size(), record, dataRecordEntriesCnt);
+    }
+
+    /**
+     * @param record page snapshot record.
+     * @return string identifier of page (IO) type.
+     */
+    private static String getPageType(PageSnapshot record) {
+        byte[] pageData = record.pageData();
+        ByteBuffer buf = ByteBuffer.allocateDirect(pageData.length);
+
+        try {
+            buf.order(ByteOrder.nativeOrder());
+            buf.put(pageData);
+
+            long addr = GridUnsafe.bufferAddress(buf);
+
+            int type = PageIO.getType(addr);
+            int ver = PageIO.getVersion(addr);
+
+            return PageIO.getPageIO(type, ver).getClass().getSimpleName();
+        }
+        catch (IgniteCheckedException ignored) {
+        }
+        finally {
+            ((DirectBuffer)buf).cleaner().clean();
+        }
+        return "";
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        final StringBuilder sb = new StringBuilder();
+
+        printSizeCountMap(sb, "WAL Segments: Source folder", segmentsFolder);
+        printSizeCountMap(sb, "WAL Segments: File index", segmentsIndexes);
+
+        printSizeCountMap(sb, "Record type", recTypeSizes);
+
+        printSizeCountMap(sb, "Tx Record: Action", txRecordAct);
+        printSizeCountMap(sb, "Tx Record: Primary nodes count", txRecordPrimNodesCnt);
+        printSizeCountMap(sb, "Tx Record: Nodes count", txRecordNodesCnt);
+
+        printSizeCountMap(sb, "Data Record: Entries count", dataRecordEntriesCnt);
+        printSizeCountMap(sb, "Data Record: Under TX", dataRecordUnderTx);
+
+        printSizeCountMap(sb, "Data Entry: Operations", dataEntryOperation);
+        printSizeCountMap(sb, "Data Entry: Cache ID", dataEntryCacheId);
+
+        printSizeCountMap(sb, "Page Snapshot: Page Types", pageSnapshotTypes);
+        printSizeCountMap(sb, "Page Snapshot: Indexes", pageSnapshotIndexes);
+        printSizeCountMap(sb, "Page Snapshot: Cache Groups", pageSnapshotCacheGrp);
+        printSizeCountMap(sb, "Page Snapshot: Partition ID", pageSnapshotPartId);
+
+        sb.append(txStat.toString());
+
+        return sb.toString();
+    }
+
+    /**
+     * @param sb buffer.
+     * @param mapName display name of map.
+     * @param map data.
+     */
+    private void printSizeCountMap(StringBuilder sb, String mapName, Map<?, RecordSizeCountStat> map) {
+        sb.append(mapName).append(": \n");
+        sb.append("key\tsize\tcount\tavg.size");
+        sb.append("\n");
+
+        final List<? extends Map.Entry<?, RecordSizeCountStat>> entries = new ArrayList<>(map.entrySet());
+
+        Collections.sort(entries, new Comparator<Map.Entry<?, RecordSizeCountStat>>() {
+            @Override public int compare(Map.Entry<?, RecordSizeCountStat> o1, Map.Entry<?, RecordSizeCountStat> o2) {
+                return -Integer.compare(o1.getValue().getCount(), o2.getValue().getCount());
+            }
+        });
+
+        RecordSizeCountStat others = new RecordSizeCountStat();
+        int otherRecords = 0;
+        int cnt = 0;
+
+        for (Map.Entry<?, RecordSizeCountStat> next : entries) {
+            if (cnt < DISPLAY_MAX) {
+                sb.append(next.getKey()).append("\t").append(next.getValue()).append("\t");
+                sb.append("\n");
+            }
+            else {
+                otherRecords++;
+                others.add(next.getValue());
+            }
+            cnt++;
+        }
+
+        if (otherRecords > 0) {
+            sb.append("... other ").append(otherRecords).append(" values").append("\t").append(others).append("\t");
+            sb.append("\n");
+        }
+
+        sb.append("\n");
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/6f7aba85/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java
index c803a36..c4a8c08 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java
@@ -458,8 +458,6 @@ public class GridH2Table extends TableBase {
                     replaced = prevRow0 != null;
                 }
 
-                assert (replaced && prevRow0 != null) || (!replaced && prevRow0 == null) : "Replaced: " + replaced;
-
                 if (!replaced)
                     size.increment();
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/6f7aba85/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteBinaryObjectFieldsQuerySelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteBinaryObjectFieldsQuerySelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteBinaryObjectFieldsQuerySelfTest.java
index 6c34373..62515c3 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteBinaryObjectFieldsQuerySelfTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteBinaryObjectFieldsQuerySelfTest.java
@@ -103,11 +103,16 @@ public class IgniteBinaryObjectFieldsQuerySelfTest extends GridCommonAbstractTes
 
     /** {@inheritDoc} */
     @Override protected void beforeTestsStarted() throws Exception {
-        extClassLoader = getExternalClassLoader();
+        initExtClassLoader();
 
         startGrids(GRID_CNT);
     }
 
+    /** */
+    protected void initExtClassLoader() {
+        extClassLoader = getExternalClassLoader();
+    }
+
     /** {@inheritDoc} */
     @Override protected void afterTestsStopped() throws Exception {
         stopAllGrids();

http://git-wip-us.apache.org/repos/asf/ignite/blob/6f7aba85/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheLockPartitionOnAffinityRunAbstractTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheLockPartitionOnAffinityRunAbstractTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheLockPartitionOnAffinityRunAbstractTest.java
index 83f5015..9af75ed 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheLockPartitionOnAffinityRunAbstractTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheLockPartitionOnAffinityRunAbstractTest.java
@@ -198,7 +198,7 @@ public class IgniteCacheLockPartitionOnAffinityRunAbstractTest extends GridCache
     /**
      * @throws Exception If failed.
      */
-    private void fillCaches() throws Exception {
+    protected void fillCaches() throws Exception {
         grid(0).createCache(Organization.class.getSimpleName());
         grid(0).createCache(Person.class.getSimpleName());
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/6f7aba85/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheLockPartitionOnAffinityRunAtomicCacheOpTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheLockPartitionOnAffinityRunAtomicCacheOpTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheLockPartitionOnAffinityRunAtomicCacheOpTest.java
index 71e737f..a4f398f 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheLockPartitionOnAffinityRunAtomicCacheOpTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheLockPartitionOnAffinityRunAtomicCacheOpTest.java
@@ -94,7 +94,7 @@ public class IgniteCacheLockPartitionOnAffinityRunAtomicCacheOpTest extends Igni
      * @param mode Atomicity mode.
      * @throws Exception If failed.
      */
-    private void createCache(String cacheName, CacheAtomicityMode mode) throws Exception {
+    protected void createCache(String cacheName, CacheAtomicityMode mode) throws Exception {
         CacheConfiguration ccfg = cacheConfiguration(grid(0).name());
         ccfg.setName(cacheName);
 
@@ -109,17 +109,27 @@ public class IgniteCacheLockPartitionOnAffinityRunAtomicCacheOpTest extends Igni
     @Override protected void beforeTest() throws Exception {
         super.beforeTest();
 
+        createCaches();
+
+        awaitPartitionMapExchange();
+    }
+
+    /** */
+    protected void createCaches() throws Exception {
         key.set(0);
         createCache(ATOMIC_CACHE, CacheAtomicityMode.ATOMIC);
         createCache(TRANSACT_CACHE, CacheAtomicityMode.TRANSACTIONAL);
+    }
 
-        awaitPartitionMapExchange();
+    /** */
+    protected void destroyCaches() throws Exception {
+        grid(0).destroyCache(ATOMIC_CACHE);
+        grid(0).destroyCache(TRANSACT_CACHE);
     }
 
     /** {@inheritDoc} */
     @Override protected void afterTest() throws Exception {
-        grid(0).destroyCache(ATOMIC_CACHE);
-        grid(0).destroyCache(TRANSACT_CACHE);
+        destroyCaches();
 
         super.afterTest();
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/6f7aba85/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/IgniteCacheQueryNodeRestartSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/IgniteCacheQueryNodeRestartSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/IgniteCacheQueryNodeRestartSelfTest.java
index 0c644e3..fc1cea6 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/IgniteCacheQueryNodeRestartSelfTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/IgniteCacheQueryNodeRestartSelfTest.java
@@ -105,7 +105,6 @@ public class IgniteCacheQueryNodeRestartSelfTest extends GridCacheAbstractSelfTe
     public void testRestarts() throws Exception {
         int duration = 60 * 1000;
         int qryThreadNum = 10;
-        final long nodeLifeTime = 2 * 1000;
         final int logFreq = 50;
 
         final IgniteCache<Integer, Integer> cache = grid(0).cache(DEFAULT_CACHE_NAME);
@@ -158,27 +157,7 @@ public class IgniteCacheQueryNodeRestartSelfTest extends GridCacheAbstractSelfTe
         for (int i = 0; i < GRID_CNT; i++)
             grid(i).events().localListen(lsnr, EventType.EVT_CACHE_REBALANCE_STOPPED);
 
-        IgniteInternalFuture<?> fut2 = multithreadedAsync(new Callable<Object>() {
-            @SuppressWarnings({"BusyWait"})
-            @Override public Object call() throws Exception {
-                while (!done.get()) {
-                    int idx = GRID_CNT;
-
-                    startGrid(idx);
-
-                    Thread.sleep(nodeLifeTime);
-
-                    stopGrid(idx);
-
-                    int c = restartCnt.incrementAndGet();
-
-                    if (c % logFreq == 0)
-                        info("Node restarts: " + c);
-                }
-
-                return true;
-            }
-        }, 1, "restart-thread");
+        IgniteInternalFuture<?> fut2 = createRestartAction(done, restartCnt);
 
         Thread.sleep(duration);
 
@@ -204,6 +183,39 @@ public class IgniteCacheQueryNodeRestartSelfTest extends GridCacheAbstractSelfTe
         assert success;
     }
 
+    /**
+     *
+     */
+    protected IgniteInternalFuture createRestartAction(final AtomicBoolean done, final AtomicInteger restartCnt) throws Exception {
+        return multithreadedAsync(new Callable<Object>() {
+            /** */
+            private final long nodeLifeTime = 2 * 1000;
+
+            /** */
+            private final int logFreq = 50;
+
+            @SuppressWarnings({"BusyWait"})
+            @Override public Object call() throws Exception {
+                while (!done.get()) {
+                    int idx = GRID_CNT;
+
+                    startGrid(idx);
+
+                    Thread.sleep(nodeLifeTime);
+
+                    stopGrid(idx);
+
+                    int c = restartCnt.incrementAndGet();
+
+                    if (c % logFreq == 0)
+                        info("Node restarts: " + c);
+                }
+
+                return true;
+            }
+        }, 1, "restart-thread");
+    }
+
     /** Listener that will wait for specified number of events received. */
     private class CollectingEventListener implements IgnitePredicate<Event> {
         /** Registered events count. */

http://git-wip-us.apache.org/repos/asf/ignite/blob/6f7aba85/modules/indexing/src/test/java/org/apache/ignite/internal/processors/database/baseline/IgniteBaselineLockPartitionOnAffinityRunAtomicCacheTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/database/baseline/IgniteBaselineLockPartitionOnAffinityRunAtomicCacheTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/database/baseline/IgniteBaselineLockPartitionOnAffinityRunAtomicCacheTest.java
new file mode 100644
index 0000000..c7663ea
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/database/baseline/IgniteBaselineLockPartitionOnAffinityRunAtomicCacheTest.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ignite.internal.processors.database.baseline;
+
+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.processors.cache.IgniteCacheLockPartitionOnAffinityRunAtomicCacheOpTest;
+import org.apache.ignite.testframework.GridTestUtils;
+
+/**
+ *
+ */
+public class IgniteBaselineLockPartitionOnAffinityRunAtomicCacheTest extends IgniteCacheLockPartitionOnAffinityRunAtomicCacheOpTest {
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
+
+        cfg.setDataStorageConfiguration(
+            new DataStorageConfiguration()
+                .setDefaultDataRegionConfiguration(
+                    new DataRegionConfiguration()
+                        .setInitialSize(200 * 1024 * 1024)
+                        .setMaxSize(200 * 1024 * 1024)
+                        .setPersistenceEnabled(true)
+                )
+        );
+
+        return cfg;
+    }
+
+    @Override protected CacheConfiguration cacheConfiguration(String igniteInstanceName) throws Exception {
+        CacheConfiguration ccfg = super.cacheConfiguration(igniteInstanceName);
+
+        ccfg.setBackups(2);
+
+        return ccfg;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        GridTestUtils.deleteDbFiles();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTest() throws Exception {
+        GridTestUtils.deleteDbFiles();
+
+        int gridCnt = gridCount();
+
+        startGrids(gridCnt + 1);
+
+        grid(0).active(true);
+
+        stopGrid(gridCnt);
+
+        startGrid(gridCnt + 1);
+
+        fillCaches();
+
+        createCaches();
+
+        awaitPartitionMapExchange();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        destroyCaches();
+
+        stopAllGrids();
+
+        GridTestUtils.deleteDbFiles();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTestsStopped() throws Exception {
+        stopAllGrids();
+
+        GridTestUtils.deleteDbFiles();
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/6f7aba85/modules/indexing/src/test/java/org/apache/ignite/internal/processors/database/baseline/IgniteBaselineLockPartitionOnAffinityRunTxCacheTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/database/baseline/IgniteBaselineLockPartitionOnAffinityRunTxCacheTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/database/baseline/IgniteBaselineLockPartitionOnAffinityRunTxCacheTest.java
new file mode 100644
index 0000000..8812829
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/database/baseline/IgniteBaselineLockPartitionOnAffinityRunTxCacheTest.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ignite.internal.processors.database.baseline;
+
+import org.apache.ignite.configuration.DataRegionConfiguration;
+import org.apache.ignite.configuration.DataStorageConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.processors.cache.IgniteCacheLockPartitionOnAffinityRunTxCacheOpTest;
+import org.apache.ignite.testframework.GridTestUtils;
+
+/**
+ *
+ */
+public class IgniteBaselineLockPartitionOnAffinityRunTxCacheTest extends IgniteCacheLockPartitionOnAffinityRunTxCacheOpTest {
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
+
+        cfg.setDataStorageConfiguration(
+            new DataStorageConfiguration()
+                .setDefaultDataRegionConfiguration(
+                    new DataRegionConfiguration()
+                        .setInitialSize(200 * 1024 * 1024)
+                        .setMaxSize(200 * 1024 * 1024)
+                        .setPersistenceEnabled(true)
+                )
+        );
+
+        return cfg;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        GridTestUtils.deleteDbFiles();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTest() throws Exception {
+        GridTestUtils.deleteDbFiles();
+
+        int gridCnt = gridCount();
+
+        startGrids(gridCnt + 1);
+
+        grid(0).active(true);
+
+        stopGrid(gridCnt);
+
+        startGrid(gridCnt + 1);
+
+        fillCaches();
+
+        createCaches();
+
+        awaitPartitionMapExchange();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        destroyCaches();
+
+        stopAllGrids();
+
+        GridTestUtils.deleteDbFiles();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTestsStopped() throws Exception {
+        stopAllGrids();
+
+        GridTestUtils.deleteDbFiles();
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/6f7aba85/modules/indexing/src/test/java/org/apache/ignite/internal/processors/database/baseline/IgniteChangingBaselineCacheQueryNodeRestartSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/database/baseline/IgniteChangingBaselineCacheQueryNodeRestartSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/database/baseline/IgniteChangingBaselineCacheQueryNodeRestartSelfTest.java
new file mode 100644
index 0000000..357d8e6
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/database/baseline/IgniteChangingBaselineCacheQueryNodeRestartSelfTest.java
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.database.baseline;
+
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.concurrent.Callable;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import org.apache.ignite.cluster.BaselineNode;
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.configuration.DataRegionConfiguration;
+import org.apache.ignite.configuration.DataStorageConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.IgniteInternalFuture;
+import org.apache.ignite.internal.processors.cache.distributed.near.IgniteCacheQueryNodeRestartSelfTest;
+import org.apache.ignite.testframework.GridTestUtils;
+
+/**
+ *
+ */
+public class IgniteChangingBaselineCacheQueryNodeRestartSelfTest extends IgniteCacheQueryNodeRestartSelfTest {
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
+
+        cfg.setDataStorageConfiguration(
+            new DataStorageConfiguration()
+                .setDefaultDataRegionConfiguration(
+                    new DataRegionConfiguration()
+                        .setMaxSize(200 * 1024 * 1024)
+                        .setPersistenceEnabled(true)
+                )
+        );
+
+        return cfg;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        GridTestUtils.deleteDbFiles();
+
+        startGrids(gridCount());
+
+        initStoreStrategy();
+
+        grid(0).active(true);
+
+        awaitPartitionMapExchange();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTestsStopped() throws Exception {
+        stopAllGrids();
+
+        GridTestUtils.deleteDbFiles();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected IgniteInternalFuture createRestartAction(final AtomicBoolean done, final AtomicInteger restartCnt) throws Exception {
+        return multithreadedAsync(new Callable<Object>() {
+            /** */
+            private final long baselineTopChangeInterval = 30 * 1000;
+
+            /** */
+            private final int logFreq = 50;
+
+            /** flag to indicate that last operation was changing BaselineTopology up (add node) */
+            private boolean lastOpChangeUp;
+
+            @SuppressWarnings({"BusyWait"})
+            @Override public Object call() throws Exception {
+                while (!done.get()) {
+                    if (lastOpChangeUp) {
+                        //need to do change down: stop node, set new BLT without it
+                        stopGrid(gridCount());
+
+                        lastOpChangeUp = false;
+                    }
+                    else {
+                        startGrid(gridCount());
+
+                        lastOpChangeUp = true;
+                    }
+
+                    grid(0).cluster().setBaselineTopology(baselineNodes(grid(0).cluster().forServers().nodes()));
+
+                    Thread.sleep(baselineTopChangeInterval);
+
+                    int c = restartCnt.incrementAndGet();
+
+                    if (c % logFreq == 0)
+                        info("BaselineTopology changes: " + c);
+                }
+
+                return true;
+            }
+        }, 1, "restart-thread");
+    }
+
+    /** */
+    private Collection<BaselineNode> baselineNodes(Collection<ClusterNode> clNodes) {
+        Collection<BaselineNode> res = new ArrayList<>(clNodes.size());
+
+        for (ClusterNode clN : clNodes)
+            res.add(clN);
+
+        return res;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/6f7aba85/modules/indexing/src/test/java/org/apache/ignite/internal/processors/database/baseline/IgniteStableBaselineBinObjFieldsQuerySelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/database/baseline/IgniteStableBaselineBinObjFieldsQuerySelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/database/baseline/IgniteStableBaselineBinObjFieldsQuerySelfTest.java
new file mode 100644
index 0000000..e9d1b79
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/database/baseline/IgniteStableBaselineBinObjFieldsQuerySelfTest.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.database.baseline;
+
+import org.apache.ignite.configuration.DataRegionConfiguration;
+import org.apache.ignite.configuration.DataStorageConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.processors.cache.IgniteBinaryObjectFieldsQuerySelfTest;
+import org.apache.ignite.testframework.GridTestUtils;
+
+/**
+ *
+ */
+public class IgniteStableBaselineBinObjFieldsQuerySelfTest extends IgniteBinaryObjectFieldsQuerySelfTest {
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
+
+        cfg.setDataStorageConfiguration(
+            new DataStorageConfiguration()
+                .setDefaultDataRegionConfiguration(
+                    new DataRegionConfiguration()
+                        .setMaxSize(200 * 1024 * 1024)
+                        .setPersistenceEnabled(true)
+                )
+        );
+
+        return cfg;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        GridTestUtils.deleteDbFiles();
+
+        initExtClassLoader();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTest() throws Exception {
+        GridTestUtils.deleteDbFiles();
+
+        startGrids(GRID_CNT + 1);
+
+        grid(0).active(true);
+
+        stopGrid(GRID_CNT);
+
+        startGrid(GRID_CNT + 1);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        stopAllGrids();
+
+        GridTestUtils.deleteDbFiles();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTestsStopped() throws Exception {
+        super.afterTestsStopped();
+
+        GridTestUtils.deleteDbFiles();
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/6f7aba85/modules/indexing/src/test/java/org/apache/ignite/internal/processors/database/baseline/IgniteStableBaselineCacheQueryNodeRestartsSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/database/baseline/IgniteStableBaselineCacheQueryNodeRestartsSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/database/baseline/IgniteStableBaselineCacheQueryNodeRestartsSelfTest.java
new file mode 100644
index 0000000..849bbb6
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/database/baseline/IgniteStableBaselineCacheQueryNodeRestartsSelfTest.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ignite.internal.processors.database.baseline;
+
+import org.apache.ignite.configuration.DataRegionConfiguration;
+import org.apache.ignite.configuration.DataStorageConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.processors.cache.distributed.near.IgniteCacheQueryNodeRestartSelfTest;
+import org.apache.ignite.testframework.GridTestUtils;
+
+/**
+ *
+ */
+public class IgniteStableBaselineCacheQueryNodeRestartsSelfTest extends IgniteCacheQueryNodeRestartSelfTest {
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
+
+        cfg.setDataStorageConfiguration(
+            new DataStorageConfiguration()
+                .setDefaultDataRegionConfiguration(
+                    new DataRegionConfiguration()
+                        .setMaxSize(200 * 1024 * 1024)
+                        .setPersistenceEnabled(true)
+                )
+        );
+
+        return cfg;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        GridTestUtils.deleteDbFiles();
+
+        startGrids(gridCount() + 1);
+
+        initStoreStrategy();
+
+        grid(0).active(true);
+
+        stopGrid(gridCount());
+
+        startGrid(gridCount() + 1);
+
+        awaitPartitionMapExchange();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTestsStopped() throws Exception {
+        stopAllGrids();
+
+        GridTestUtils.deleteDbFiles();
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/6f7aba85/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheAffinityRunTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheAffinityRunTestSuite.java b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheAffinityRunTestSuite.java
index ef00fc3..e9c7b79 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheAffinityRunTestSuite.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheAffinityRunTestSuite.java
@@ -22,6 +22,8 @@ import org.apache.ignite.internal.processors.cache.IgniteCacheLockPartitionOnAff
 import org.apache.ignite.internal.processors.cache.IgniteCacheLockPartitionOnAffinityRunTest;
 import org.apache.ignite.internal.processors.cache.IgniteCacheLockPartitionOnAffinityRunTxCacheOpTest;
 import org.apache.ignite.internal.processors.cache.IgniteCacheLockPartitionOnAffinityRunWithCollisionSpiTest;
+import org.apache.ignite.internal.processors.database.baseline.IgniteBaselineLockPartitionOnAffinityRunAtomicCacheTest;
+import org.apache.ignite.internal.processors.database.baseline.IgniteBaselineLockPartitionOnAffinityRunTxCacheTest;
 
 /**
  * Compute and Cache tests for affinityRun/Call. These tests is extracted into separate suite
@@ -38,6 +40,8 @@ public class IgniteCacheAffinityRunTestSuite extends TestSuite {
         suite.addTestSuite(IgniteCacheLockPartitionOnAffinityRunTest.class);
         suite.addTestSuite(IgniteCacheLockPartitionOnAffinityRunWithCollisionSpiTest.class);
         suite.addTestSuite(IgniteCacheLockPartitionOnAffinityRunAtomicCacheOpTest.class);
+        suite.addTestSuite(IgniteBaselineLockPartitionOnAffinityRunAtomicCacheTest.class);
+        suite.addTestSuite(IgniteBaselineLockPartitionOnAffinityRunTxCacheTest.class);
         suite.addTestSuite(IgniteCacheLockPartitionOnAffinityRunTxCacheOpTest.class);
 
         return suite;

http://git-wip-us.apache.org/repos/asf/ignite/blob/6f7aba85/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java
index cf5c9a6..8cfa14e 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java
@@ -136,6 +136,7 @@ import org.apache.ignite.internal.processors.cache.query.IgniteCacheQueryCacheDe
 import org.apache.ignite.internal.processors.cache.query.IndexingSpiQuerySelfTest;
 import org.apache.ignite.internal.processors.cache.query.IndexingSpiQueryTxSelfTest;
 import org.apache.ignite.internal.processors.client.ClientConnectorConfigurationValidationSelfTest;
+import org.apache.ignite.internal.processors.database.baseline.IgniteStableBaselineBinObjFieldsQuerySelfTest;
 import org.apache.ignite.internal.processors.query.IgniteSqlDefaultValueTest;
 import org.apache.ignite.internal.processors.query.IgniteSqlDistributedJoinSelfTest;
 import org.apache.ignite.internal.processors.query.IgniteSqlSkipReducerOnUpdateDmlFlagSelfTest;
@@ -248,6 +249,7 @@ public class IgniteCacheQuerySelfTestSuite extends TestSuite {
         suite.addTestSuite(GridCacheCrossCacheQuerySelfTest.class);
         suite.addTestSuite(GridCacheQuerySerializationSelfTest.class);
         suite.addTestSuite(IgniteBinaryObjectFieldsQuerySelfTest.class);
+        suite.addTestSuite(IgniteStableBaselineBinObjFieldsQuerySelfTest.class);
         suite.addTestSuite(IgniteBinaryWrappedObjectFieldsQuerySelfTest.class);
         suite.addTestSuite(IgniteCacheQueryH2IndexingLeakTest.class);
         suite.addTestSuite(IgniteCacheQueryNoRebalanceSelfTest.class);

http://git-wip-us.apache.org/repos/asf/ignite/blob/6f7aba85/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite2.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite2.java b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite2.java
index abe06ec..11d98e2 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite2.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite2.java
@@ -42,6 +42,8 @@ import org.apache.ignite.internal.processors.cache.index.DynamicIndexPartitioned
 import org.apache.ignite.internal.processors.cache.index.DynamicIndexReplicatedAtomicConcurrentSelfTest;
 import org.apache.ignite.internal.processors.cache.index.DynamicIndexReplicatedTransactionalConcurrentSelfTest;
 import org.apache.ignite.internal.processors.cache.query.ScanQueryOffheapExpiryPolicySelfTest;
+import org.apache.ignite.internal.processors.database.baseline.IgniteChangingBaselineCacheQueryNodeRestartSelfTest;
+import org.apache.ignite.internal.processors.database.baseline.IgniteStableBaselineCacheQueryNodeRestartsSelfTest;
 import org.apache.ignite.internal.processors.query.IgniteCacheGroupsCompareQueryTest;
 import org.apache.ignite.internal.processors.query.IgniteCacheGroupsSqlDistributedJoinSelfTest;
 import org.apache.ignite.internal.processors.query.IgniteCacheGroupsSqlSegmentedIndexMultiNodeSelfTest;
@@ -85,6 +87,8 @@ public class IgniteCacheQuerySelfTestSuite2 extends TestSuite {
         suite.addTestSuite(IgniteCacheClientQueryReplicatedNodeRestartSelfTest.class);
         suite.addTestSuite(IgniteCacheQueryNodeFailTest.class);
         suite.addTestSuite(IgniteCacheQueryNodeRestartSelfTest.class);
+        suite.addTestSuite(IgniteChangingBaselineCacheQueryNodeRestartSelfTest.class);
+        suite.addTestSuite(IgniteStableBaselineCacheQueryNodeRestartsSelfTest.class);
         suite.addTestSuite(IgniteCacheQueryNodeRestartSelfTest2.class);
         suite.addTestSuite(IgniteCacheQueryNodeRestartTxSelfTest.class);
         suite.addTestSuite(IgniteCacheSqlQueryMultiThreadedSelfTest.class);

http://git-wip-us.apache.org/repos/asf/ignite/blob/6f7aba85/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/ClusterParityTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/ClusterParityTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/ClusterParityTest.cs
index b940d09..4b4279f 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/ClusterParityTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/ClusterParityTest.cs
@@ -38,7 +38,11 @@
         /** Members that are missing on .NET side and should be added in future. */
         private static readonly string[] MissingMembers =
         {
-            "enableStatistics"  // IGNITE-7276
+            "enableStatistics",  // IGNITE-7276
+            
+            // IGNITE-7301
+            "active",
+            "setBaselineTopology"
         };
 
         /// <summary>

http://git-wip-us.apache.org/repos/asf/ignite/blob/6f7aba85/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/IgniteConfigurationParityTest.cs
----------------------------------------------------------------------
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 235b177..410d911 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/IgniteConfigurationParityTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/IgniteConfigurationParityTest.cs
@@ -78,7 +78,8 @@ namespace Apache.Ignite.Core.Tests.ApiParity
             "isCacheSanityCheckEnabled",
             "TimeServerPortBase",
             "TimeServerPortRange",
-            "IncludeProperties"
+            "IncludeProperties",
+            "isAutoActivationEnabled"  // IGNITE-7301
         };
 
         /// <summary>


Mime
View raw message