You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by vo...@apache.org on 2018/09/26 09:38:28 UTC

[1/9] ignite git commit: IGNITE-9538: MVCC: update partition counters on prepare phase. This closes #4795.

Repository: ignite
Updated Branches:
  refs/heads/ignite-2.7 5f5f17360 -> b023375c1


http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/core/src/test/java/org/apache/ignite/internal/processors/database/CacheFreeListImplSelfTest.java
----------------------------------------------------------------------
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/CacheFreeListImplSelfTest.java
index 17aa9b0..7422815 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/CacheFreeListImplSelfTest.java
@@ -480,6 +480,11 @@ public class CacheFreeListImplSelfTest extends GridCommonAbstractTest {
         @Override public byte newMvccTxState() {
             return 0;
         }
+
+        /** {@inheritDoc} */
+        @Override public boolean isKeyAbsentBefore() {
+            return false;
+        }
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Row.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Row.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Row.java
index 2133e1a..6246aa5 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Row.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Row.java
@@ -126,6 +126,10 @@ public abstract class GridH2Row extends GridH2SearchRowAdapter implements CacheD
         return row.newMvccTxState();
     }
 
+    /** {@inheritDoc} */
+    @Override public boolean isKeyAbsentBefore() {
+        return row.isKeyAbsentBefore();
+    }
 
     /** {@inheritDoc} */
     @Override public boolean indexSearchRow() {

http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/CacheMvccSqlUpdateCountersTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/CacheMvccSqlUpdateCountersTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/CacheMvccSqlUpdateCountersTest.java
new file mode 100644
index 0000000..407248d
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/CacheMvccSqlUpdateCountersTest.java
@@ -0,0 +1,549 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.mvcc;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicLong;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.IgniteTransactions;
+import org.apache.ignite.cache.CacheMode;
+import org.apache.ignite.cache.affinity.Affinity;
+import org.apache.ignite.cache.query.FieldsQueryCursor;
+import org.apache.ignite.cache.query.SqlFieldsQuery;
+import org.apache.ignite.internal.processors.cache.IgniteCacheProxy;
+import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtLocalPartition;
+import org.apache.ignite.internal.util.lang.GridInClosure3;
+import org.apache.ignite.internal.util.typedef.G;
+import org.apache.ignite.lang.IgniteInClosure;
+import org.apache.ignite.transactions.Transaction;
+
+import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
+import static org.apache.ignite.internal.processors.cache.mvcc.CacheMvccAbstractTest.ReadMode.SQL;
+import static org.apache.ignite.transactions.TransactionConcurrency.PESSIMISTIC;
+import static org.apache.ignite.transactions.TransactionIsolation.REPEATABLE_READ;
+
+/**
+ * Test for MVCC caches update counters behaviour.
+ */
+@SuppressWarnings("unchecked")
+public class CacheMvccSqlUpdateCountersTest extends CacheMvccAbstractTest {
+    /** {@inheritDoc} */
+    @Override protected CacheMode cacheMode() {
+        return CacheMode.PARTITIONED;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testUpdateCountersInsertSimple() throws Exception {
+        ccfg = cacheConfiguration(cacheMode(), FULL_SYNC, 2, DFLT_PARTITION_COUNT)
+            .setIndexedTypes(Integer.class, Integer.class);
+
+        Ignite node = startGridsMultiThreaded(3);
+
+        IgniteCache cache = node.cache(DEFAULT_CACHE_NAME);
+
+        Affinity aff = affinity(cache);
+
+        Integer key1 = 1;
+
+        int part1 = aff.partition(key1);
+
+        try (Transaction tx = node.transactions().txStart(PESSIMISTIC, REPEATABLE_READ)) {
+            SqlFieldsQuery qry = new SqlFieldsQuery("INSERT INTO Integer (_key, _val) values (" + key1 + ",1)");
+
+            cache.query(qry).getAll();
+
+            tx.commit();
+        }
+
+        checkUpdateCounters(DEFAULT_CACHE_NAME, part1, 1);
+
+        try (Transaction tx = node.transactions().txStart(PESSIMISTIC, REPEATABLE_READ)) {
+            SqlFieldsQuery qry = new SqlFieldsQuery("UPDATE Integer SET _val=2 WHERE _key=" + key1);
+
+            cache.query(qry).getAll();
+
+            tx.commit();
+        }
+
+        checkUpdateCounters(DEFAULT_CACHE_NAME, part1, 2);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testUpdateCountersDoubleUpdate() throws Exception {
+        ccfg = cacheConfiguration(cacheMode(), FULL_SYNC, 2, DFLT_PARTITION_COUNT)
+            .setIndexedTypes(Integer.class, Integer.class);
+
+        Ignite node = startGridsMultiThreaded(3);
+
+        IgniteCache cache = node.cache(DEFAULT_CACHE_NAME);
+
+        Affinity aff = affinity(cache);
+
+        int key1 = 1;
+
+        int part1 = aff.partition(key1);
+
+        try (Transaction tx = node.transactions().txStart(PESSIMISTIC, REPEATABLE_READ)) {
+            SqlFieldsQuery qry = new SqlFieldsQuery("INSERT INTO Integer (_key, _val) values (" + key1 + ",1)");
+
+            cache.query(qry).getAll();
+
+            qry = new SqlFieldsQuery("UPDATE Integer SET _val=2 WHERE _key=" + key1);
+
+            cache.query(qry).getAll();
+
+            tx.commit();
+        }
+
+        checkUpdateCounters(DEFAULT_CACHE_NAME, part1, 1);
+
+        try (Transaction tx = node.transactions().txStart(PESSIMISTIC, REPEATABLE_READ)) {
+            SqlFieldsQuery qry = new SqlFieldsQuery("MERGE INTO Integer (_key, _val) values (" + key1 + ",1)");
+
+            cache.query(qry).getAll();
+
+            qry = new SqlFieldsQuery("UPDATE Integer SET _val=2 WHERE _key=" + key1);
+
+            cache.query(qry).getAll();
+
+            tx.commit();
+        }
+
+        checkUpdateCounters(DEFAULT_CACHE_NAME, part1, 2);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testUpdateCountersRollback() throws Exception {
+        ccfg = cacheConfiguration(cacheMode(), FULL_SYNC, 2, DFLT_PARTITION_COUNT)
+            .setIndexedTypes(Integer.class, Integer.class);
+
+        Ignite node = startGridsMultiThreaded(3);
+
+        IgniteCache cache = node.cache(DEFAULT_CACHE_NAME);
+
+        Affinity aff = affinity(cache);
+
+        int key1 = 1;
+
+        int part1 = aff.partition(key1);
+
+        try (Transaction tx = node.transactions().txStart(PESSIMISTIC, REPEATABLE_READ)) {
+            SqlFieldsQuery qry = new SqlFieldsQuery("INSERT INTO Integer (_key, _val) values (" + key1 + ",1)");
+
+            cache.query(qry).getAll();
+
+            qry = new SqlFieldsQuery("UPDATE Integer SET _val=2 WHERE _key=" + key1);
+
+            cache.query(qry).getAll();
+
+            tx.rollback();
+        }
+
+        checkUpdateCounters(DEFAULT_CACHE_NAME, part1, 0);
+
+        try (Transaction tx = node.transactions().txStart(PESSIMISTIC, REPEATABLE_READ)) {
+            SqlFieldsQuery qry = new SqlFieldsQuery("MERGE INTO Integer (_key, _val) values (" + key1 + ",1)");
+
+            cache.query(qry).getAll();
+
+            qry = new SqlFieldsQuery("UPDATE Integer SET _val=2 WHERE _key=" + key1);
+
+            cache.query(qry).getAll();
+
+            tx.rollback();
+        }
+
+        checkUpdateCounters(DEFAULT_CACHE_NAME, part1, 0);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testDeleteOwnKey() throws Exception {
+        ccfg = cacheConfiguration(cacheMode(), FULL_SYNC, 2, 1)
+            .setCacheMode(CacheMode.REPLICATED)
+            .setIndexedTypes(Integer.class, Integer.class);
+
+        Ignite node = startGridsMultiThreaded(1);
+
+        IgniteCache cache = node.cache(DEFAULT_CACHE_NAME);
+
+        Affinity aff = affinity(cache);
+
+        int key1 = 1;
+
+        int part1 = aff.partition(key1);
+
+        try (Transaction tx = node.transactions().txStart(PESSIMISTIC, REPEATABLE_READ)) {
+            SqlFieldsQuery qry = new SqlFieldsQuery("INSERT INTO Integer (_key, _val) values (" + key1 + ",1)");
+
+            cache.query(qry).getAll();
+
+            qry = new SqlFieldsQuery("MERGE INTO Integer (_key, _val) values (" + key1 + ",2)");
+
+            cache.query(qry).getAll();
+
+            qry = new SqlFieldsQuery("MERGE INTO Integer (_key, _val) values (" + key1 + ",3)");
+
+            cache.query(qry).getAll();
+
+            qry = new SqlFieldsQuery("DELETE FROM Integer WHERE _key=" + key1);
+
+            cache.query(qry).getAll();
+
+            qry = new SqlFieldsQuery("MERGE INTO Integer (_key, _val) values (" + key1 + ",4)");
+
+            cache.query(qry).getAll();
+
+            qry = new SqlFieldsQuery("MERGE INTO Integer (_key, _val) values (" + key1 + ",5)");
+
+            cache.query(qry).getAll();
+
+            qry = new SqlFieldsQuery("DELETE FROM Integer WHERE _key=" + key1);
+
+            cache.query(qry).getAll();
+
+            tx.commit();
+        }
+
+        checkUpdateCounters(DEFAULT_CACHE_NAME, part1, 0);
+
+        try (Transaction tx = node.transactions().txStart(PESSIMISTIC, REPEATABLE_READ)) {
+            SqlFieldsQuery qry = new SqlFieldsQuery("MERGE INTO Integer (_key, _val) values (" + key1 + ",1)");
+
+            cache.query(qry).getAll();
+
+            tx.commit();
+        }
+
+        checkUpdateCounters(DEFAULT_CACHE_NAME, part1, 1);
+
+        try (Transaction tx = node.transactions().txStart(PESSIMISTIC, REPEATABLE_READ)) {
+            SqlFieldsQuery qry = new SqlFieldsQuery("DELETE FROM Integer WHERE _key=" + key1);
+
+            cache.query(qry).getAll();
+
+            tx.commit();
+        }
+
+        checkUpdateCounters(DEFAULT_CACHE_NAME, part1, 2);
+
+        try (Transaction tx = node.transactions().txStart(PESSIMISTIC, REPEATABLE_READ)) {
+            SqlFieldsQuery qry = new SqlFieldsQuery("DELETE FROM Integer WHERE _key=" + key1);
+
+            cache.query(qry).getAll();
+
+            tx.commit();
+        }
+
+        checkUpdateCounters(DEFAULT_CACHE_NAME, part1, 2);
+
+        try (Transaction tx = node.transactions().txStart(PESSIMISTIC, REPEATABLE_READ)) {
+            SqlFieldsQuery qry  = new SqlFieldsQuery("MERGE INTO Integer (_key, _val) values (" + key1 + ",5)");
+
+            cache.query(qry).getAll();
+
+            tx.commit();
+        }
+
+        checkUpdateCounters(DEFAULT_CACHE_NAME, part1, 3);
+
+        try (Transaction tx = node.transactions().txStart(PESSIMISTIC, REPEATABLE_READ)) {
+            SqlFieldsQuery qry = new SqlFieldsQuery("DELETE FROM Integer WHERE _key=" + key1);
+
+            cache.query(qry).getAll();
+
+            qry  = new SqlFieldsQuery("MERGE INTO Integer (_key, _val) values (" + key1 + ",5)");
+
+            cache.query(qry).getAll();
+
+            qry = new SqlFieldsQuery("DELETE FROM Integer WHERE _key=" + key1);
+
+            cache.query(qry).getAll();
+
+            tx.commit();
+        }
+
+        checkUpdateCounters(DEFAULT_CACHE_NAME, part1, 4);
+
+        try (Transaction tx = node.transactions().txStart(PESSIMISTIC, REPEATABLE_READ)) {
+            SqlFieldsQuery qry  = new SqlFieldsQuery("MERGE INTO Integer (_key, _val) values (" + key1 + ",6)");
+
+            cache.query(qry).getAll();
+
+            tx.commit();
+        }
+
+        checkUpdateCounters(DEFAULT_CACHE_NAME, part1, 5);
+
+        try (Transaction tx = node.transactions().txStart(PESSIMISTIC, REPEATABLE_READ)) {
+            SqlFieldsQuery qry = new SqlFieldsQuery("DELETE FROM Integer WHERE _key=" + key1);
+
+            cache.query(qry).getAll();
+
+            qry  = new SqlFieldsQuery("MERGE INTO Integer (_key, _val) values (" + key1 + ",5)");
+
+            cache.query(qry).getAll();
+
+            tx.commit();
+        }
+
+        checkUpdateCounters(DEFAULT_CACHE_NAME, part1, 6);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testUpdateCountersMultithreaded() throws Exception {
+        final int writers = 4;
+
+        final int readers = 0;
+
+        int parts = 8;
+
+        int keys = 20;
+
+        final Map<Integer, AtomicLong> tracker = new ConcurrentHashMap<>();
+
+        for (int i = 0; i< keys; i++)
+            tracker.put(i, new AtomicLong(1));
+
+        final IgniteInClosure<IgniteCache<Object, Object>> init = new IgniteInClosure<IgniteCache<Object, Object>>() {
+            @Override public void apply(IgniteCache<Object, Object> cache) {
+                final IgniteTransactions txs = cache.unwrap(Ignite.class).transactions();
+                try (Transaction tx = txs.txStart(PESSIMISTIC, REPEATABLE_READ)) {
+                    SqlFieldsQuery qry = new SqlFieldsQuery("INSERT INTO MvccTestAccount(_key, val, updateCnt) VALUES " +
+                        "(?, 0, 1)");
+
+                    for (int i = 0; i < keys; i++) {
+                        try (FieldsQueryCursor<List<?>> cur = cache.query(qry.setArgs(i))) {
+                            assertEquals(1L, cur.iterator().next().get(0));
+                        }
+
+                        tx.commit();
+                    }
+                }
+            }
+        };
+
+        GridInClosure3<Integer, List<TestCache>, AtomicBoolean> writer =
+            new GridInClosure3<Integer, List<TestCache>, AtomicBoolean>() {
+                @Override public void apply(Integer idx, List<TestCache> caches, AtomicBoolean stop) {
+                    ThreadLocalRandom rnd = ThreadLocalRandom.current();
+
+                    Map<Integer, AtomicLong> acc = new HashMap<>();
+
+                    int v = 0;
+
+                    while (!stop.get()) {
+                        int cnt = rnd.nextInt(keys / 3);
+
+                        if (cnt == 0)
+                            cnt = 2;
+
+                        // Generate key set to be changed in tx.
+                        while (acc.size() < cnt)
+                            acc.put(rnd.nextInt(cnt), new AtomicLong());
+
+                        TestCache<Integer, Integer> cache = randomCache(caches, rnd);
+
+                        boolean success = true;
+
+                        try {
+                            IgniteTransactions txs = cache.cache.unwrap(Ignite.class).transactions();
+
+                            try (Transaction tx = txs.txStart(PESSIMISTIC, REPEATABLE_READ)) {
+                                Map<Integer, MvccTestAccount> allVals = readAllByMode(cache.cache, tracker.keySet(), SQL, ACCOUNT_CODEC);
+
+                                boolean rmv = allVals.size() > keys * 2 / 3;
+
+                                for (Map.Entry<Integer, AtomicLong> e : acc.entrySet()) {
+                                    int key = e.getKey();
+
+                                    AtomicLong accCntr = e.getValue();
+
+                                    boolean exists = allVals.containsKey(key);
+
+                                    int delta = 0;
+
+                                    boolean createdInTx = false;
+
+                                    if (rmv && rnd.nextBoolean()) {
+                                        if (exists)
+                                            delta = 1;
+
+                                        SqlFieldsQuery qry = new SqlFieldsQuery("DELETE FROM MvccTestAccount WHERE _key=" + key);
+
+                                        cache.cache.query(qry).getAll();
+                                    }
+                                    else {
+                                        delta = 1;
+
+                                        if (!exists)
+                                            createdInTx = true;
+
+                                        SqlFieldsQuery qry = new SqlFieldsQuery("MERGE INTO MvccTestAccount " +
+                                            "(_key, val, updateCnt) VALUES (" + key + ",  " + rnd.nextInt(100) + ", 1)");
+
+                                        cache.cache.query(qry).getAll();
+                                    }
+
+                                    if (rnd.nextBoolean()) {
+                                        if (createdInTx)
+                                            delta = 0; // Do not count cases when key created and removed in the same tx.
+
+                                        SqlFieldsQuery qry = new SqlFieldsQuery("DELETE FROM MvccTestAccount WHERE _key=" + key);
+
+                                        cache.cache.query(qry).getAll();
+                                    }
+                                    else {
+                                        delta = 1;
+
+                                        SqlFieldsQuery qry = new SqlFieldsQuery("MERGE INTO MvccTestAccount " +
+                                            "(_key, val, updateCnt) VALUES (" + key + ",  " + rnd.nextInt(100) + ", 1)");
+
+                                        cache.cache.query(qry).getAll();
+                                    }
+
+                                    accCntr.addAndGet(delta);
+                                }
+
+                                tx.commit();
+                            }
+                        }
+                        catch (Exception e) {
+                            handleTxException(e);
+
+                            success = false;
+
+                            int r= 0;
+
+                            for (Map.Entry<Integer, AtomicLong> en : acc.entrySet()) {
+                                if (((IgniteCacheProxy)cache.cache).context().affinity().partition(en.getKey()) == 0)
+                                    r += en.getValue().intValue();
+                            }
+                        }
+                        finally {
+                            cache.readUnlock();
+
+                            if (success) {
+                                v++;
+
+                                for (Map.Entry<Integer, AtomicLong> e : acc.entrySet()) {
+                                    int k = e.getKey();
+                                    long updCntr = e.getValue().get();
+
+                                    tracker.get(k).addAndGet(updCntr);
+                                }
+
+                                int r= 0;
+
+                                for (Map.Entry<Integer, AtomicLong> en : acc.entrySet()) {
+                                    if (((IgniteCacheProxy)cache.cache).context().affinity().partition(en.getKey()) == 0)
+                                        r += en.getValue().intValue();
+                                }
+                            }
+
+                            acc.clear();
+                        }
+                    }
+
+                    info("Writer done, updates: " + v);
+                }
+            };
+
+        GridInClosure3<Integer, List<TestCache>, AtomicBoolean> reader =
+            new GridInClosure3<Integer, List<TestCache>, AtomicBoolean>() {
+                @Override public void apply(Integer idx, List<TestCache> caches, AtomicBoolean stop) {
+                    // No-op.
+                }
+            };
+
+        readWriteTest(
+            null,
+            4,
+            1,
+            2,
+            parts,
+            writers,
+            readers,
+            30_000,
+            new InitIndexing(Integer.class, MvccTestAccount.class),
+            init,
+            writer,
+            reader);
+
+        Map<Integer, AtomicLong> updPerParts = new HashMap<>(parts);
+
+        Affinity aff = grid(1).cachex(DEFAULT_CACHE_NAME).affinity();
+
+        for (Map.Entry<Integer, AtomicLong> e : tracker.entrySet()) {
+            int k = e.getKey();
+            long updCntr = e.getValue().get();
+
+            int p = aff.partition(k);
+
+            AtomicLong cntr = updPerParts.get(p);
+
+            if (cntr == null) {
+                cntr = new AtomicLong();
+
+                updPerParts.putIfAbsent(p, cntr);
+            }
+
+            cntr.addAndGet(updCntr);
+        }
+
+        for (Map.Entry<Integer, AtomicLong> e : updPerParts.entrySet())
+            checkUpdateCounters(DEFAULT_CACHE_NAME, e.getKey(), e.getValue().get());
+    }
+
+    /**
+     * Checks update counter value on all nodes.
+     *
+     * @param cacheName Cache name.
+     * @param p Part number.
+     * @param val Expected partition counter value.
+     */
+    private void checkUpdateCounters(String cacheName, int p, long val) {
+        for (Ignite node : G.allGrids()) {
+            if (!node.configuration().isClientMode()) {
+                IgniteCacheProxy cache = (IgniteCacheProxy)node.cache(cacheName);
+
+
+                GridDhtLocalPartition part = cache.context().topology().localPartition(p);
+
+                if (!cache.context().mvccEnabled() || part == null)
+                    continue;
+
+                assertEquals("part=" + p, val, part.updateCounter());
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheMvccSqlTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheMvccSqlTestSuite.java b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheMvccSqlTestSuite.java
index 888b1ba..726c4e9 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheMvccSqlTestSuite.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheMvccSqlTestSuite.java
@@ -39,6 +39,7 @@ import org.apache.ignite.internal.processors.cache.mvcc.CacheMvccScanQueryWithCo
 import org.apache.ignite.internal.processors.cache.mvcc.CacheMvccSizeTest;
 import org.apache.ignite.internal.processors.cache.mvcc.CacheMvccSizeWithConcurrentJdbcTransactionTest;
 import org.apache.ignite.internal.processors.cache.mvcc.CacheMvccSqlConfigurationValidationTest;
+import org.apache.ignite.internal.processors.cache.mvcc.CacheMvccSqlUpdateCountersTest;
 import org.apache.ignite.internal.processors.cache.mvcc.CacheMvccSqlLockTimeoutTest;
 import org.apache.ignite.internal.processors.cache.mvcc.CacheMvccStreamingInsertTest;
 import org.apache.ignite.internal.processors.query.h2.GridIndexRebuildWithMvccEnabledSelfTest;
@@ -58,6 +59,7 @@ public class IgniteCacheMvccSqlTestSuite extends TestSuite {
         suite.addTestSuite(CacheMvccDmlSimpleTest.class);
         suite.addTestSuite(SqlTransactionsCommandsWithMvccEnabledSelfTest.class);
         suite.addTestSuite(CacheMvccSizeTest.class);
+        suite.addTestSuite(CacheMvccSqlUpdateCountersTest.class);
         suite.addTestSuite(CacheMvccSqlLockTimeoutTest.class);
 
         suite.addTestSuite(GridIndexRebuildWithMvccEnabledSelfTest.class);


[9/9] ignite git commit: IGNITE-9629: JDBC: improved type conversions for thick driver. This closes #4761.

Posted by vo...@apache.org.
IGNITE-9629: JDBC: improved type conversions for thick driver. This closes #4761.


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

Branch: refs/heads/ignite-2.7
Commit: b023375c12a81a3ed17825ac61c8c967124b26d6
Parents: 20f5246
Author: tledkov-gridgain <tl...@gridgain.com>
Authored: Wed Sep 26 11:17:50 2018 +0300
Committer: devozerov <vo...@gridgain.com>
Committed: Wed Sep 26 12:38:07 2018 +0300

----------------------------------------------------------------------
 .../internal/jdbc2/JdbcResultSetSelfTest.java   | 272 ++++++++++-
 .../ignite/jdbc/JdbcErrorsAbstractSelfTest.java |   4 +-
 .../jdbc/thin/JdbcThinResultSetSelfTest.java    |  45 +-
 .../ignite/internal/jdbc2/JdbcResultSet.java    | 487 +++++++++++++++----
 4 files changed, 682 insertions(+), 126 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/b023375c/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcResultSetSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcResultSetSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcResultSetSelfTest.java
index 9e60c25..bd73bcd 100644
--- a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcResultSetSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcResultSetSelfTest.java
@@ -151,7 +151,7 @@ public class JdbcResultSetSelfTest extends GridCommonAbstractTest {
         o.floatVal = 1.0f;
         o.doubleVal = 1.0d;
         o.bigVal = new BigDecimal(1);
-        o.strVal = "str";
+        o.strVal = "1";
         o.arrVal = new byte[] {1};
         o.dateVal = new Date(1, 1, 1);
         o.timeVal = new Time(1, 1, 1);
@@ -173,12 +173,72 @@ public class JdbcResultSetSelfTest extends GridCommonAbstractTest {
             if (cnt == 0) {
                 assert rs.getBoolean("boolVal");
                 assert rs.getBoolean(2);
+                assert rs.getByte(2) == 1;
+                assert rs.getInt(2) == 1;
+                assert rs.getShort(2) == 1;
+                assert rs.getLong(2) == 1;
+                assert rs.getDouble(2) == 1.0;
+                assert rs.getFloat(2) == 1.0f;
+                assert rs.getBigDecimal(2).equals(new BigDecimal(1));
+                assert rs.getString(2).equals("true");
+
+                assert rs.getObject(2, Boolean.class);
+                assert rs.getObject(2, Byte.class) == 1;
+                assert rs.getObject(2, Short.class) == 1;
+                assert rs.getObject(2, Integer.class) == 1;
+                assert rs.getObject(2, Long.class) == 1;
+                assert rs.getObject(2, Float.class) == 1.f;
+                assert rs.getObject(2, Double.class) == 1;
+                assert rs.getObject(2, BigDecimal.class).equals(new BigDecimal(1));
+                assert rs.getObject(2, String.class).equals("true");
             }
 
             cnt++;
         }
 
         assert cnt == 1;
+
+        ResultSet rs0 = stmt.executeQuery("select 1");
+
+        assert rs0.next();
+        assert rs0.getBoolean(1);
+
+        rs0 = stmt.executeQuery("select 0");
+
+        assert rs0.next();
+        assert !rs0.getBoolean(1);
+
+        rs0 = stmt.executeQuery("select '1'");
+
+        assert rs0.next();
+        assert rs0.getBoolean(1);
+
+        rs0 = stmt.executeQuery("select '0'");
+
+        assert rs0.next();
+        assert !rs0.getBoolean(1);
+
+        GridTestUtils.assertThrowsAnyCause(log, new Callable<Void>() {
+            @Override public Void call() throws Exception {
+                ResultSet rs0 = stmt.executeQuery("select ''");
+
+                assert rs0.next();
+                assert rs0.getBoolean(1);
+
+                return null;
+            }
+        }, SQLException.class, "Cannot convert to boolean: ");
+
+        GridTestUtils.assertThrowsAnyCause(log, new Callable<Void>() {
+            @Override public Void call() throws Exception {
+                ResultSet rs0 = stmt.executeQuery("select 'qwe'");
+
+                assert rs0.next();
+                assert rs0.getBoolean(1);
+
+                return null;
+            }
+        }, SQLException.class, "Cannot convert to boolean: qwe");
     }
 
     /**
@@ -253,6 +313,26 @@ public class JdbcResultSetSelfTest extends GridCommonAbstractTest {
             if (cnt == 0) {
                 assert rs.getByte("byteVal") == 1;
                 assert rs.getByte(3) == 1;
+
+                assert rs.getBoolean(3);
+                assert rs.getByte(3) == 1;
+                assert rs.getInt(3) == 1;
+                assert rs.getShort(3) == 1;
+                assert rs.getLong(3) == 1;
+                assert rs.getDouble(3) == 1.0;
+                assert rs.getFloat(3) == 1.0f;
+                assert rs.getBigDecimal(3).equals(new BigDecimal(1));
+                assert rs.getString(3).equals("1");
+
+                assert rs.getObject(3, Boolean.class);
+                assert rs.getObject(3, Byte.class) == 1;
+                assert rs.getObject(3, Short.class) == 1;
+                assert rs.getObject(3, Integer.class) == 1;
+                assert rs.getObject(3, Long.class) == 1;
+                assert rs.getObject(3, Float.class) == 1.f;
+                assert rs.getObject(3, Double.class) == 1;
+                assert rs.getObject(3, BigDecimal.class).equals(new BigDecimal(1));
+                assert rs.getObject(3, String.class).equals("1");
             }
 
             cnt++;
@@ -273,6 +353,26 @@ public class JdbcResultSetSelfTest extends GridCommonAbstractTest {
             if (cnt == 0) {
                 assert rs.getShort("shortVal") == 1;
                 assert rs.getShort(4) == 1;
+
+                assert rs.getBoolean(4);
+                assert rs.getByte(4) == 1;
+                assert rs.getShort(4) == 1;
+                assert rs.getInt(4) == 1;
+                assert rs.getLong(4) == 1;
+                assert rs.getDouble(4) == 1.0;
+                assert rs.getFloat(4) == 1.0f;
+                assert rs.getBigDecimal(4).equals(new BigDecimal(1));
+                assert rs.getString(4).equals("1");
+
+                assert rs.getObject(4, Boolean.class);
+                assert rs.getObject(4, Byte.class) == 1;
+                assert rs.getObject(4, Short.class) == 1;
+                assert rs.getObject(4, Integer.class) == 1;
+                assert rs.getObject(4, Long.class) == 1;
+                assert rs.getObject(4, Float.class) == 1.f;
+                assert rs.getObject(4, Double.class) == 1;
+                assert rs.getObject(4, BigDecimal.class).equals(new BigDecimal(1));
+                assert rs.getObject(4, String.class).equals("1");
             }
 
             cnt++;
@@ -293,6 +393,26 @@ public class JdbcResultSetSelfTest extends GridCommonAbstractTest {
             if (cnt == 0) {
                 assert rs.getInt("intVal") == 1;
                 assert rs.getInt(5) == 1;
+
+                assert rs.getBoolean(5);
+                assert rs.getByte(5) == 1;
+                assert rs.getShort(5) == 1;
+                assert rs.getInt(5) == 1;
+                assert rs.getLong(5) == 1;
+                assert rs.getDouble(5) == 1.0;
+                assert rs.getFloat(5) == 1.0f;
+                assert rs.getBigDecimal(5).equals(new BigDecimal(1));
+                assert rs.getString(5).equals("1");
+
+                assert rs.getObject(5, Boolean.class);
+                assert rs.getObject(5, Byte.class) == 1;
+                assert rs.getObject(5, Short.class) == 1;
+                assert rs.getObject(5, Integer.class) == 1;
+                assert rs.getObject(5, Long.class) == 1;
+                assert rs.getObject(5, Float.class) == 1.f;
+                assert rs.getObject(5, Double.class) == 1;
+                assert rs.getObject(5, BigDecimal.class).equals(new BigDecimal(1));
+                assert rs.getObject(5, String.class).equals("1");
             }
 
             cnt++;
@@ -313,6 +433,26 @@ public class JdbcResultSetSelfTest extends GridCommonAbstractTest {
             if (cnt == 0) {
                 assert rs.getLong("longVal") == 1;
                 assert rs.getLong(6) == 1;
+
+                assert rs.getBoolean(6);
+                assert rs.getByte(6) == 1;
+                assert rs.getShort(6) == 1;
+                assert rs.getInt(6) == 1;
+                assert rs.getLong(6) == 1;
+                assert rs.getDouble(6) == 1.0;
+                assert rs.getFloat(6) == 1.0f;
+                assert rs.getBigDecimal(6).equals(new BigDecimal(1));
+                assert rs.getString(6).equals("1");
+
+                assert rs.getObject(6, Boolean.class);
+                assert rs.getObject(6, Byte.class) == 1;
+                assert rs.getObject(6, Short.class) == 1;
+                assert rs.getObject(6, Integer.class) == 1;
+                assert rs.getObject(6, Long.class) == 1;
+                assert rs.getObject(6, Float.class) == 1.f;
+                assert rs.getObject(6, Double.class) == 1;
+                assert rs.getObject(6, BigDecimal.class).equals(new BigDecimal(1));
+                assert rs.getObject(6, String.class).equals("1");
             }
 
             cnt++;
@@ -333,6 +473,26 @@ public class JdbcResultSetSelfTest extends GridCommonAbstractTest {
             if (cnt == 0) {
                 assert rs.getFloat("floatVal") == 1.0;
                 assert rs.getFloat(7) == 1.0;
+
+                assert rs.getBoolean(7);
+                assert rs.getByte(7) == 1;
+                assert rs.getShort(7) == 1;
+                assert rs.getInt(7) == 1;
+                assert rs.getLong(7) == 1;
+                assert rs.getDouble(7) == 1.0;
+                assert rs.getFloat(7) == 1.0f;
+                assert rs.getBigDecimal(7).equals(new BigDecimal(1));
+                assert rs.getString(7).equals("1.0");
+
+                assert rs.getObject(7, Boolean.class);
+                assert rs.getObject(7, Byte.class) == 1;
+                assert rs.getObject(7, Short.class) == 1;
+                assert rs.getObject(7, Integer.class) == 1;
+                assert rs.getObject(7, Long.class) == 1;
+                assert rs.getObject(7, Float.class) == 1.f;
+                assert rs.getObject(7, Double.class) == 1;
+                assert rs.getObject(7, BigDecimal.class).equals(new BigDecimal(1));
+                assert rs.getObject(7, String.class).equals("1.0");
             }
 
             cnt++;
@@ -353,6 +513,26 @@ public class JdbcResultSetSelfTest extends GridCommonAbstractTest {
             if (cnt == 0) {
                 assert rs.getDouble("doubleVal") == 1.0;
                 assert rs.getDouble(8) == 1.0;
+
+                assert rs.getBoolean(8);
+                assert rs.getByte(8) == 1;
+                assert rs.getShort(8) == 1;
+                assert rs.getInt(8) == 1;
+                assert rs.getLong(8) == 1;
+                assert rs.getDouble(8) == 1.0;
+                assert rs.getFloat(8) == 1.0f;
+                assert rs.getBigDecimal(8).equals(new BigDecimal(1));
+                assert rs.getString(8).equals("1.0");
+
+                assert rs.getObject(8, Boolean.class);
+                assert rs.getObject(8, Byte.class) == 1;
+                assert rs.getObject(8, Short.class) == 1;
+                assert rs.getObject(8, Integer.class) == 1;
+                assert rs.getObject(8, Long.class) == 1;
+                assert rs.getObject(8, Float.class) == 1.f;
+                assert rs.getObject(8, Double.class) == 1;
+                assert rs.getObject(8, BigDecimal.class).equals(new BigDecimal(1));
+                assert rs.getObject(8, String.class).equals("1.0");
             }
 
             cnt++;
@@ -373,6 +553,26 @@ public class JdbcResultSetSelfTest extends GridCommonAbstractTest {
             if (cnt == 0) {
                 assert rs.getBigDecimal("bigVal").intValue() == 1;
                 assert rs.getBigDecimal(9).intValue() == 1;
+
+                assert rs.getBoolean(9);
+                assert rs.getByte(9) == 1;
+                assert rs.getShort(9) == 1;
+                assert rs.getInt(9) == 1;
+                assert rs.getLong(9) == 1;
+                assert rs.getDouble(9) == 1.0;
+                assert rs.getFloat(9) == 1.0f;
+                assert rs.getBigDecimal(9).equals(new BigDecimal(1));
+                assert rs.getString(9).equals("1");
+
+                assert rs.getObject(9, Boolean.class);
+                assert rs.getObject(9, Byte.class) == 1;
+                assert rs.getObject(9, Short.class) == 1;
+                assert rs.getObject(9, Integer.class) == 1;
+                assert rs.getObject(9, Long.class) == 1;
+                assert rs.getObject(9, Float.class) == 1.f;
+                assert rs.getObject(9, Double.class) == 1;
+                assert rs.getObject(9, BigDecimal.class).equals(new BigDecimal(1));
+                assert rs.getObject(9, String.class).equals("1");
             }
 
             cnt++;
@@ -384,6 +584,30 @@ public class JdbcResultSetSelfTest extends GridCommonAbstractTest {
     /**
      * @throws Exception If failed.
      */
+    public void testBigDecimalScale() throws Exception {
+        assert "0.12".equals(convertStringToBigDecimalViaJdbc("0.1234", 2).toString());
+        assert "1.001".equals(convertStringToBigDecimalViaJdbc("1.0005", 3).toString());
+        assert "1E+3".equals(convertStringToBigDecimalViaJdbc("1205.5", -3).toString());
+        assert "1.3E+4".equals(convertStringToBigDecimalViaJdbc("12505.5", -3).toString());
+    }
+
+    /**
+     * @param strDec String representation of a decimal value.
+     * @param scale Scale.
+     * @return BigDecimal object.
+     * @throws SQLException On error.
+     */
+    private BigDecimal convertStringToBigDecimalViaJdbc(String strDec, int scale) throws SQLException {
+        try(ResultSet rs = stmt.executeQuery("select '" + strDec + "'")) {
+            assert rs.next();
+
+            return rs.getBigDecimal(1, scale);
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
     public void testString() throws Exception {
         ResultSet rs = stmt.executeQuery(SQL);
 
@@ -391,8 +615,27 @@ public class JdbcResultSetSelfTest extends GridCommonAbstractTest {
 
         while (rs.next()) {
             if (cnt == 0) {
-                assert "str".equals(rs.getString("strVal"));
-                assert "str".equals(rs.getString(10));
+                assert "1".equals(rs.getString("strVal"));
+
+                assert rs.getBoolean(10);
+                assert rs.getByte(10) == 1;
+                assert rs.getShort(10) == 1;
+                assert rs.getInt(10) == 1;
+                assert rs.getLong(10) == 1;
+                assert rs.getDouble(10) == 1.0;
+                assert rs.getFloat(10) == 1.0f;
+                assert rs.getBigDecimal(10).equals(new BigDecimal("1"));
+                assert rs.getString(10).equals("1");
+
+                assert rs.getObject(10, Boolean.class);
+                assert rs.getObject(10, Byte.class) == 1;
+                assert rs.getObject(10, Short.class) == 1;
+                assert rs.getObject(10, Integer.class) == 1;
+                assert rs.getObject(10, Long.class) == 1;
+                assert rs.getObject(10, Float.class) == 1.f;
+                assert rs.getObject(10, Double.class) == 1;
+                assert rs.getObject(10, BigDecimal.class).equals(new BigDecimal(1));
+                assert rs.getObject(10, String.class).equals("1");
             }
 
             cnt++;
@@ -433,7 +676,14 @@ public class JdbcResultSetSelfTest extends GridCommonAbstractTest {
         while (rs.next()) {
             if (cnt == 0) {
                 assert rs.getDate("dateVal").equals(new Date(1, 1, 1));
+
                 assert rs.getDate(12).equals(new Date(1, 1, 1));
+                assert rs.getTime(12).equals(new Time(new Date(1, 1, 1).getTime()));
+                assert rs.getTimestamp(12).equals(new Timestamp(new Date(1, 1, 1).getTime()));
+
+                assert rs.getObject(12, Date.class).equals(new Date(1, 1, 1));
+                assert rs.getObject(12, Time.class).equals(new Time(new Date(1, 1, 1).getTime()));
+                assert rs.getObject(12, Timestamp.class).equals(new Timestamp(new Date(1, 1, 1).getTime()));
             }
 
             cnt++;
@@ -454,7 +704,14 @@ public class JdbcResultSetSelfTest extends GridCommonAbstractTest {
         while (rs.next()) {
             if (cnt == 0) {
                 assert rs.getTime("timeVal").equals(new Time(1, 1, 1));
+
+                assert rs.getDate(13).equals(new Date(new Time(1, 1, 1).getTime()));
                 assert rs.getTime(13).equals(new Time(1, 1, 1));
+                assert rs.getTimestamp(13).equals(new Timestamp(new Time(1, 1, 1).getTime()));
+
+                assert rs.getObject(13, Date.class).equals(new Date(new Time(1, 1, 1).getTime()));
+                assert rs.getObject(13, Time.class).equals(new Time(1, 1, 1));
+                assert rs.getObject(13, Timestamp.class).equals(new Timestamp(new Time(1, 1, 1).getTime()));
             }
 
             cnt++;
@@ -474,7 +731,14 @@ public class JdbcResultSetSelfTest extends GridCommonAbstractTest {
         while (rs.next()) {
             if (cnt == 0) {
                 assert rs.getTimestamp("tsVal").getTime() == 1;
-                assert rs.getTimestamp(14).getTime() == 1;
+
+                assert rs.getDate(14).equals(new Date(new Timestamp(1).getTime()));
+                assert rs.getTime(14).equals(new Time(new Timestamp(1).getTime()));
+                assert rs.getTimestamp(14).equals(new Timestamp(1));
+
+                assert rs.getObject(14, Date.class).equals(new Date(new Timestamp(1).getTime()));
+                assert rs.getObject(14, Time.class).equals(new Time(new Timestamp(1).getTime()));
+                assert rs.getObject(14, Timestamp.class).equals(new Timestamp(1));
             }
 
             cnt++;

http://git-wip-us.apache.org/repos/asf/ignite/blob/b023375c/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcErrorsAbstractSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcErrorsAbstractSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcErrorsAbstractSelfTest.java
index 59535f8..c44e007 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcErrorsAbstractSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcErrorsAbstractSelfTest.java
@@ -260,10 +260,10 @@ public abstract class JdbcErrorsAbstractSelfTest extends GridCommonAbstractTest
 
                     rs.next();
 
-                    rs.getLong(1);
+                    rs.getInt(1);
                 }
             }
-        }, "0700B", "Cannot convert to long");
+        }, "0700B", "Cannot convert to int");
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/b023375c/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinResultSetSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinResultSetSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinResultSetSelfTest.java
index 6b7cdf4..36a0a15 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinResultSetSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinResultSetSelfTest.java
@@ -38,7 +38,6 @@ import java.util.Arrays;
 import java.util.GregorianCalendar;
 import java.util.concurrent.Callable;
 import org.apache.ignite.IgniteCache;
-import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.cache.query.annotations.QuerySqlField;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
@@ -151,7 +150,7 @@ public class JdbcThinResultSetSelfTest extends JdbcThinAbstractSelfTest {
         o.floatVal = 1.0f;
         o.doubleVal = 1.0d;
         o.bigVal = new BigDecimal(1);
-        o.strVal = "1.0";
+        o.strVal = "1";
         o.arrVal = new byte[] {1};
         o.dateVal = new Date(1, 1, 1);
         o.timeVal = new Time(1, 1, 1);
@@ -548,27 +547,27 @@ public class JdbcThinResultSetSelfTest extends JdbcThinAbstractSelfTest {
 
         while (rs.next()) {
             if (cnt == 0) {
-                assert "1.0".equals(rs.getString("strVal"));
-
-                assert rs.getBoolean(7);
-                assert rs.getByte(7) == 1;
-                assert rs.getShort(7) == 1;
-                assert rs.getInt(7) == 1;
-                assert rs.getLong(7) == 1;
-                assert rs.getDouble(7) == 1.0;
-                assert rs.getFloat(7) == 1.0f;
-                assert rs.getBigDecimal(7).equals(new BigDecimal(1));
-                assert rs.getString(7).equals("1.0");
-
-                assert rs.getObject(7, Boolean.class);
-                assert rs.getObject(7, Byte.class) == 1;
-                assert rs.getObject(7, Short.class) == 1;
-                assert rs.getObject(7, Integer.class) == 1;
-                assert rs.getObject(7, Long.class) == 1;
-                assert rs.getObject(7, Float.class) == 1.f;
-                assert rs.getObject(7, Double.class) == 1;
-                assert rs.getObject(7, BigDecimal.class).equals(new BigDecimal(1));
-                assert rs.getObject(7, String.class).equals("1.0");
+                assert "1".equals(rs.getString("strVal"));
+
+                assert rs.getBoolean(10);
+                assert rs.getByte(10) == 1;
+                assert rs.getShort(10) == 1;
+                assert rs.getInt(10) == 1;
+                assert rs.getLong(10) == 1;
+                assert rs.getDouble(10) == 1.0;
+                assert rs.getFloat(10) == 1.0f;
+                assert rs.getBigDecimal(10).equals(new BigDecimal("1"));
+                assert rs.getString(10).equals("1");
+
+                assert rs.getObject(10, Boolean.class);
+                assert rs.getObject(10, Byte.class) == 1;
+                assert rs.getObject(10, Short.class) == 1;
+                assert rs.getObject(10, Integer.class) == 1;
+                assert rs.getObject(10, Long.class) == 1;
+                assert rs.getObject(10, Float.class) == 1.f;
+                assert rs.getObject(10, Double.class) == 1;
+                assert rs.getObject(10, BigDecimal.class).equals(new BigDecimal(1));
+                assert rs.getObject(10, String.class).equals("1");
             }
 
             cnt++;

http://git-wip-us.apache.org/repos/asf/ignite/blob/b023375c/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcResultSet.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcResultSet.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcResultSet.java
index e6e8488..2025b90 100755
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcResultSet.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcResultSet.java
@@ -20,6 +20,7 @@ package org.apache.ignite.internal.jdbc2;
 import java.io.InputStream;
 import java.io.Reader;
 import java.math.BigDecimal;
+import java.net.MalformedURLException;
 import java.net.URL;
 import java.sql.Array;
 import java.sql.Blob;
@@ -37,6 +38,9 @@ import java.sql.SQLXML;
 import java.sql.Statement;
 import java.sql.Time;
 import java.sql.Timestamp;
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.text.ParseException;
 import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.Collections;
@@ -55,6 +59,25 @@ import static org.apache.ignite.internal.jdbc2.JdbcUtils.convertToSqlException;
  * JDBC result set implementation.
  */
 public class JdbcResultSet implements ResultSet {
+    /** Decimal format to convert streing to decimal. */
+    private static final ThreadLocal<DecimalFormat> decimalFormat = new ThreadLocal<DecimalFormat>() {
+        /** {@inheritDoc} */
+        @Override protected DecimalFormat initialValue() {
+            DecimalFormatSymbols symbols = new DecimalFormatSymbols();
+
+            symbols.setGroupingSeparator(',');
+            symbols.setDecimalSeparator('.');
+
+            String ptrn = "#,##0.0#";
+
+            DecimalFormat decimalFormat = new DecimalFormat(ptrn, symbols);
+
+            decimalFormat.setParseBigDecimal(true);
+
+            return decimalFormat;
+        }
+    };
+
     /** Is query. */
     private final boolean isQry;
 
@@ -189,7 +212,9 @@ public class JdbcResultSet implements ResultSet {
     }
 
     /**
+     * Fetch next results page.
      *
+     * @throws SQLException On error.
      */
     private void fetchPage() throws SQLException {
         JdbcConnection conn = (JdbcConnection)stmt.getConnection();
@@ -253,81 +278,277 @@ public class JdbcResultSet implements ResultSet {
 
     /** {@inheritDoc} */
     @Override public String getString(int colIdx) throws SQLException {
-        return getTypedValue(colIdx, String.class);
+        Object val = getValue(colIdx);
+
+        return val == null ? null : String.valueOf(val);
     }
 
     /** {@inheritDoc} */
     @Override public boolean getBoolean(int colIdx) throws SQLException {
-        Boolean val = getTypedValue(colIdx, Boolean.class);
+        Object val = getValue(colIdx);
+
+        if (val == null)
+            return false;
+
+        Class<?> cls = val.getClass();
 
-        return val != null ? val : false;
+        if (cls == Boolean.class)
+            return ((Boolean)val);
+        else if (val instanceof Number)
+            return ((Number)val).intValue() != 0;
+        else if (cls == String.class || cls == Character.class) {
+            try {
+                return Integer.parseInt(val.toString()) != 0;
+            }
+            catch (NumberFormatException e) {
+                throw new SQLException("Cannot convert to boolean: " + val, SqlStateCode.CONVERSION_FAILED, e);
+            }
+        }
+        else
+            throw new SQLException("Cannot convert to boolean: " + val, SqlStateCode.CONVERSION_FAILED);
     }
 
     /** {@inheritDoc} */
     @Override public byte getByte(int colIdx) throws SQLException {
-        Byte val = getTypedValue(colIdx, Byte.class);
+        Object val = getValue(colIdx);
+
+        if (val == null)
+            return 0;
 
-        return val != null ? val : 0;
+        Class<?> cls = val.getClass();
+
+        if (val instanceof Number)
+            return ((Number)val).byteValue();
+        else if (cls == Boolean.class)
+            return (Boolean) val ? (byte) 1 : (byte) 0;
+        else if (cls == String.class || cls == Character.class) {
+            try {
+                return Byte.parseByte(val.toString());
+            }
+            catch (NumberFormatException e) {
+                throw new SQLException("Cannot convert to byte: " + val, SqlStateCode.CONVERSION_FAILED, e);
+            }
+        }
+        else
+            throw new SQLException("Cannot convert to byte: " + val, SqlStateCode.CONVERSION_FAILED);
     }
 
     /** {@inheritDoc} */
     @Override public short getShort(int colIdx) throws SQLException {
-        Short val = getTypedValue(colIdx, Short.class);
+        Object val = getValue(colIdx);
+
+        if (val == null)
+            return 0;
+
+        Class<?> cls = val.getClass();
 
-        return val != null ? val : 0;
+        if (val instanceof Number)
+            return ((Number) val).shortValue();
+        else if (cls == Boolean.class)
+            return (Boolean) val ? (short) 1 : (short) 0;
+        else if (cls == String.class || cls == Character.class) {
+            try {
+                return Short.parseShort(val.toString());
+            }
+            catch (NumberFormatException e) {
+                throw new SQLException("Cannot convert to short: " + val, SqlStateCode.CONVERSION_FAILED, e);
+            }
+        }
+        else
+            throw new SQLException("Cannot convert to short: " + val, SqlStateCode.CONVERSION_FAILED);
     }
 
     /** {@inheritDoc} */
     @Override public int getInt(int colIdx) throws SQLException {
-        Integer val = getTypedValue(colIdx, Integer.class);
+        Object val = getValue(colIdx);
 
-        return val != null ? val : 0;
+        if (val == null)
+            return 0;
+
+        Class<?> cls = val.getClass();
+
+        if (val instanceof Number)
+            return ((Number) val).intValue();
+        else if (cls == Boolean.class)
+            return (Boolean) val ? 1 : 0;
+        else if (cls == String.class || cls == Character.class) {
+            try {
+                return Integer.parseInt(val.toString());
+            }
+            catch (NumberFormatException e) {
+                throw new SQLException("Cannot convert to int: " + val, SqlStateCode.CONVERSION_FAILED, e);
+            }
+        }
+        else
+            throw new SQLException("Cannot convert to int: " + val, SqlStateCode.CONVERSION_FAILED);
     }
 
     /** {@inheritDoc} */
     @Override public long getLong(int colIdx) throws SQLException {
-        Long val = getTypedValue(colIdx, Long.class);
+        Object val = getValue(colIdx);
+
+        if (val == null)
+            return 0;
+
+        Class<?> cls = val.getClass();
 
-        return val != null ? val : 0;
+        if (val instanceof Number)
+            return ((Number)val).longValue();
+        else if (cls == Boolean.class)
+            return (long) ((Boolean) val ? 1 : 0);
+        else if (cls == String.class || cls == Character.class) {
+            try {
+                return Long.parseLong(val.toString());
+            }
+            catch (NumberFormatException e) {
+                throw new SQLException("Cannot convert to long: " + val, SqlStateCode.CONVERSION_FAILED, e);
+            }
+        }
+        else
+            throw new SQLException("Cannot convert to long: " + val, SqlStateCode.CONVERSION_FAILED);
     }
 
     /** {@inheritDoc} */
     @Override public float getFloat(int colIdx) throws SQLException {
-        Float val = getTypedValue(colIdx, Float.class);
+        Object val = getValue(colIdx);
 
-        return val != null ? val : 0;
+        if (val == null)
+            return 0;
+
+        Class<?> cls = val.getClass();
+
+        if (val instanceof Number)
+            return ((Number) val).floatValue();
+        else if (cls == Boolean.class)
+            return (float) ((Boolean) val ? 1 : 0);
+        else if (cls == String.class || cls == Character.class) {
+            try {
+                return Float.parseFloat(val.toString());
+            }
+            catch (NumberFormatException e) {
+                throw new SQLException("Cannot convert to float: " + val, SqlStateCode.CONVERSION_FAILED, e);
+            }
+        }
+        else
+            throw new SQLException("Cannot convert to float: " + val, SqlStateCode.CONVERSION_FAILED);
     }
 
     /** {@inheritDoc} */
     @Override public double getDouble(int colIdx) throws SQLException {
-        Double val = getTypedValue(colIdx, Double.class);
+        Object val = getValue(colIdx);
+
+        if (val == null)
+            return 0;
+
+        Class<?> cls = val.getClass();
 
-        return val != null ? val : 0;
+        if (val instanceof Number)
+            return ((Number) val).doubleValue();
+        else if (cls == Boolean.class)
+            return (double)((Boolean) val ? 1 : 0);
+        else if (cls == String.class || cls == Character.class) {
+            try {
+                return Double.parseDouble(val.toString());
+            }
+            catch (NumberFormatException e) {
+                throw new SQLException("Cannot convert to double: " + val, SqlStateCode.CONVERSION_FAILED, e);
+            }
+        }
+        else
+            throw new SQLException("Cannot convert to double: " + val, SqlStateCode.CONVERSION_FAILED);
     }
 
     /** {@inheritDoc} */
     @Override public BigDecimal getBigDecimal(int colIdx, int scale) throws SQLException {
-        return getTypedValue(colIdx, BigDecimal.class);
+        BigDecimal val = getBigDecimal(colIdx);
+
+        return val == null ? null : val.setScale(scale, BigDecimal.ROUND_HALF_UP);
     }
 
     /** {@inheritDoc} */
     @Override public byte[] getBytes(int colIdx) throws SQLException {
-        return getTypedValue(colIdx, byte[].class);
+        Object val = getValue(colIdx);
+
+        if (val == null)
+            return null;
+
+        Class<?> cls = val.getClass();
+
+        if (cls == byte[].class)
+            return (byte[])val;
+        else if (cls == Byte.class)
+            return new byte[] {(byte)val};
+        else if (cls == Short.class) {
+            short x = (short)val;
+
+            return new byte[] {(byte)(x >> 8), (byte)x};
+        }
+        else if (cls == Integer.class) {
+            int x = (int)val;
+
+            return new byte[] { (byte) (x >> 24), (byte) (x >> 16), (byte) (x >> 8), (byte) x};
+        }
+        else if (cls == Long.class) {
+            long x = (long)val;
+
+            return new byte[] {(byte) (x >> 56), (byte) (x >> 48), (byte) (x >> 40), (byte) (x >> 32),
+                (byte) (x >> 24), (byte) (x >> 16), (byte) (x >> 8), (byte) x};
+        }
+        else if (cls == String.class)
+            return ((String)val).getBytes();
+        else
+            throw new SQLException("Cannot convert to byte[]: " + val, SqlStateCode.CONVERSION_FAILED);
     }
 
     /** {@inheritDoc} */
     @Override public Date getDate(int colIdx) throws SQLException {
-        return getTypedValue(colIdx, Date.class);
+        Object val = getValue(colIdx);
+
+        if (val == null)
+            return null;
+
+        Class<?> cls = val.getClass();
+
+        if (cls == Date.class)
+            return (Date)val;
+        else if (cls == java.util.Date.class || cls == Time.class || cls == Timestamp.class)
+            return new Date(((java.util.Date)val).getTime());
+        else
+            throw new SQLException("Cannot convert to date: " + val, SqlStateCode.CONVERSION_FAILED);
     }
 
     /** {@inheritDoc} */
     @Override public Time getTime(int colIdx) throws SQLException {
-        return getTypedValue(colIdx, Time.class);
+        Object val = getValue(colIdx);
+
+        if (val == null)
+            return null;
+
+        Class<?> cls = val.getClass();
+
+        if (cls == Time.class)
+            return (Time)val;
+        else if (cls == java.util.Date.class || cls == Date.class || cls == Timestamp.class)
+            return new Time(((java.util.Date)val).getTime());
+        else
+            throw new SQLException("Cannot convert to time: " + val, SqlStateCode.CONVERSION_FAILED);
     }
 
     /** {@inheritDoc} */
     @Override public Timestamp getTimestamp(int colIdx) throws SQLException {
-        return getTypedValue(colIdx, Timestamp.class);
+        Object val = getValue(colIdx);
+
+        if (val == null)
+            return null;
+
+        Class<?> cls = val.getClass();
+
+        if (cls == Timestamp.class)
+            return (Timestamp)val;
+        else if (cls == java.util.Date.class || cls == Date.class || cls == Time.class)
+            return new Timestamp(((java.util.Date)val).getTime());
+        else
+            throw new SQLException("Cannot convert to timestamp: " + val, SqlStateCode.CONVERSION_FAILED);
     }
 
     /** {@inheritDoc} */
@@ -353,81 +574,93 @@ public class JdbcResultSet implements ResultSet {
 
     /** {@inheritDoc} */
     @Override public String getString(String colLb) throws SQLException {
-        return getTypedValue(colLb, String.class);
+        int colIdx = findColumn(colLb);
+
+        return getString(colIdx);
     }
 
     /** {@inheritDoc} */
     @Override public boolean getBoolean(String colLb) throws SQLException {
-        Boolean val = getTypedValue(colLb, Boolean.class);
+        int colIdx = findColumn(colLb);
 
-        return val != null ? val : false;
+        return getBoolean(colIdx);
     }
 
     /** {@inheritDoc} */
     @Override public byte getByte(String colLb) throws SQLException {
-        Byte val = getTypedValue(colLb, Byte.class);
+        int colIdx = findColumn(colLb);
 
-        return val != null ? val : 0;
+        return getByte(colIdx);
     }
 
     /** {@inheritDoc} */
     @Override public short getShort(String colLb) throws SQLException {
-        Short val = getTypedValue(colLb, Short.class);
+        int colIdx = findColumn(colLb);
 
-        return val != null ? val : 0;
+        return getShort(colIdx);
     }
 
     /** {@inheritDoc} */
     @Override public int getInt(String colLb) throws SQLException {
-        Integer val = getTypedValue(colLb, Integer.class);
+        int colIdx = findColumn(colLb);
 
-        return val != null ? val : 0;
+        return getInt(colIdx);
     }
 
     /** {@inheritDoc} */
     @Override public long getLong(String colLb) throws SQLException {
-        Long val = getTypedValue(colLb, Long.class);
+        int colIdx = findColumn(colLb);
 
-        return val != null ? val : 0;
+        return getLong(colIdx);
     }
 
     /** {@inheritDoc} */
     @Override public float getFloat(String colLb) throws SQLException {
-        Float val = getTypedValue(colLb, Float.class);
+        int colIdx = findColumn(colLb);
 
-        return val != null ? val : 0;
+        return getFloat(colIdx);
     }
 
     /** {@inheritDoc} */
     @Override public double getDouble(String colLb) throws SQLException {
-        Double val = getTypedValue(colLb, Double.class);
+        int colIdx = findColumn(colLb);
 
-        return val != null ? val : 0;
+        return getDouble(colIdx);
     }
 
     /** {@inheritDoc} */
     @Override public BigDecimal getBigDecimal(String colLb, int scale) throws SQLException {
-        return getTypedValue(colLb, BigDecimal.class);
+        int colIdx = findColumn(colLb);
+
+        return getBigDecimal(colIdx, scale);
     }
 
     /** {@inheritDoc} */
     @Override public byte[] getBytes(String colLb) throws SQLException {
-        return getTypedValue(colLb, byte[].class);
+        int colIdx = findColumn(colLb);
+
+        return getBytes(colIdx);
     }
 
     /** {@inheritDoc} */
     @Override public Date getDate(String colLb) throws SQLException {
-        return getTypedValue(colLb, Date.class);
+        int colIdx = findColumn(colLb);
+
+        return getDate(colIdx);
     }
 
     /** {@inheritDoc} */
     @Override public Time getTime(String colLb) throws SQLException {
-        return getTypedValue(colLb, Time.class);
+        int colIdx = findColumn(colLb);
+
+        return getTime(colIdx);
     }
 
     /** {@inheritDoc} */
     @Override public Timestamp getTimestamp(String colLb) throws SQLException {
-        return getTypedValue(colLb, Timestamp.class);
+        int colIdx = findColumn(colLb);
+
+        return getTimestamp(colIdx);
     }
 
     /** {@inheritDoc} */
@@ -482,12 +715,14 @@ public class JdbcResultSet implements ResultSet {
 
     /** {@inheritDoc} */
     @Override public Object getObject(int colIdx) throws SQLException {
-        return getTypedValue(colIdx, Object.class);
+        return getValue(colIdx);
     }
 
     /** {@inheritDoc} */
     @Override public Object getObject(String colLb) throws SQLException {
-        return getTypedValue(colLb, Object.class);
+        int colIdx = findColumn(colLb);
+
+        return getValue(colIdx);
     }
 
     /** {@inheritDoc} */
@@ -499,6 +734,8 @@ public class JdbcResultSet implements ResultSet {
         if (idx == -1)
             throw new SQLException("Column not found: " + colLb);
 
+        assert idx >= 0;
+
         return idx + 1;
     }
 
@@ -518,12 +755,36 @@ public class JdbcResultSet implements ResultSet {
 
     /** {@inheritDoc} */
     @Override public BigDecimal getBigDecimal(int colIdx) throws SQLException {
-        return getTypedValue(colIdx, BigDecimal.class);
+        Object val = getValue(colIdx);
+
+        if (val == null)
+            return null;
+
+        Class<?> cls = val.getClass();
+
+        if (cls == BigDecimal.class)
+            return (BigDecimal)val;
+        else if (val instanceof Number)
+            return new BigDecimal(((Number)val).doubleValue());
+        else if (cls == Boolean.class)
+            return new BigDecimal((Boolean)val ? 1 : 0);
+        else if (cls == String.class || cls == Character.class) {
+            try {
+                return (BigDecimal)decimalFormat.get().parse(val.toString());
+            }
+            catch (ParseException e) {
+                throw new SQLException("Cannot convert to BigDecimal: " + val, SqlStateCode.CONVERSION_FAILED, e);
+            }
+        }
+        else
+            throw new SQLException("Cannot convert to BigDecimal: " + val, SqlStateCode.CONVERSION_FAILED);
     }
 
     /** {@inheritDoc} */
     @Override public BigDecimal getBigDecimal(String colLb) throws SQLException {
-        return getTypedValue(colLb, BigDecimal.class);
+        int colIdx = findColumn(colLb);
+
+        return getBigDecimal(colIdx);
     }
 
     /** {@inheritDoc} */
@@ -997,7 +1258,7 @@ public class JdbcResultSet implements ResultSet {
 
     /** {@inheritDoc} */
     @Override public Object getObject(int colIdx, Map<String, Class<?>> map) throws SQLException {
-        return getTypedValue(colIdx, Object.class);
+        throw new SQLFeatureNotSupportedException("SQL structured type are not supported.");
     }
 
     /** {@inheritDoc} */
@@ -1028,7 +1289,7 @@ public class JdbcResultSet implements ResultSet {
 
     /** {@inheritDoc} */
     @Override public Object getObject(String colLb, Map<String, Class<?>> map) throws SQLException {
-        return getTypedValue(colLb, Object.class);
+        throw new SQLFeatureNotSupportedException("SQL structured type are not supported.");
     }
 
     /** {@inheritDoc} */
@@ -1059,42 +1320,62 @@ public class JdbcResultSet implements ResultSet {
 
     /** {@inheritDoc} */
     @Override public Date getDate(int colIdx, Calendar cal) throws SQLException {
-        return getTypedValue(colIdx, Date.class);
+        return getDate(colIdx);
     }
 
     /** {@inheritDoc} */
     @Override public Date getDate(String colLb, Calendar cal) throws SQLException {
-        return getTypedValue(colLb, Date.class);
+        return getDate(colLb);
     }
 
     /** {@inheritDoc} */
     @Override public Time getTime(int colIdx, Calendar cal) throws SQLException {
-        return getTypedValue(colIdx, Time.class);
+        return getTime(colIdx);
     }
 
     /** {@inheritDoc} */
     @Override public Time getTime(String colLb, Calendar cal) throws SQLException {
-        return getTypedValue(colLb, Time.class);
+        return getTime(colLb);
     }
 
     /** {@inheritDoc} */
     @Override public Timestamp getTimestamp(int colIdx, Calendar cal) throws SQLException {
-        return getTypedValue(colIdx, Timestamp.class);
+        return getTimestamp(colIdx);
     }
 
     /** {@inheritDoc} */
     @Override public Timestamp getTimestamp(String colLb, Calendar cal) throws SQLException {
-        return getTypedValue(colLb, Timestamp.class);
+        return getTimestamp(colLb);
     }
 
     /** {@inheritDoc} */
     @Override public URL getURL(int colIdx) throws SQLException {
-        return getTypedValue(colIdx, URL.class);
+        Object val = getValue(colIdx);
+
+        if (val == null)
+            return null;
+
+        Class<?> cls = val.getClass();
+
+        if (cls == URL.class)
+            return (URL)val;
+        else if (cls == String.class) {
+            try {
+                return new URL(val.toString());
+            }
+            catch (MalformedURLException e) {
+                throw new SQLException("Cannot convert to URL: " + val, SqlStateCode.CONVERSION_FAILED, e);
+            }
+        }
+        else
+            throw new SQLException("Cannot convert to URL: " + val, SqlStateCode.CONVERSION_FAILED);
     }
 
     /** {@inheritDoc} */
     @Override public URL getURL(String colLb) throws SQLException {
-        return getTypedValue(colLb, URL.class);
+        int colIdx = findColumn(colLb);
+
+        return getURL(colIdx);
     }
 
     /** {@inheritDoc} */
@@ -1486,57 +1767,77 @@ public class JdbcResultSet implements ResultSet {
     }
 
     /** {@inheritDoc} */
-    @Override public <T> T getObject(int colIdx, Class<T> type) throws SQLException {
-        return getTypedValue(colIdx, type);
+    @Override public <T> T getObject(int colIdx, Class<T> targetCls) throws SQLException {
+        return (T)getObject0(colIdx, targetCls);
     }
 
     /** {@inheritDoc} */
-    @Override public <T> T getObject(String colLb, Class<T> type) throws SQLException {
-        return getTypedValue(colLb, type);
+    @Override public <T> T getObject(String colLb, Class<T> targetCls) throws SQLException {
+        int colIdx = findColumn(colLb);
+
+        return getObject(colIdx, targetCls);
     }
 
     /**
-     * Gets casted field value by label.
-     *
-     * @param colLb Column label.
-     * @param cls Value class.
-     * @return Casted field value.
-     * @throws SQLException In case of error.
+     * @param colIdx Column index.
+     * @param targetCls Class representing the Java data type to convert the designated column to.
+     * @return Converted object.
+     * @throws SQLException On error.
      */
-    private <T> T getTypedValue(String colLb, Class<T> cls) throws SQLException {
-        ensureNotClosed();
-        ensureHasCurrentRow();
-
-        String name = colLb.toUpperCase();
-
-        Integer idx = stmt.fieldsIdxs.get(name);
-
-        int colIdx;
-
-        if (idx != null)
-            colIdx = idx;
+    private Object getObject0(int colIdx, Class<?> targetCls) throws SQLException {
+        if (targetCls == Boolean.class)
+            return getBoolean(colIdx);
+        else if (targetCls == Byte.class)
+            return getByte(colIdx);
+        else if (targetCls == Short.class)
+            return getShort(colIdx);
+        else if (targetCls == Integer.class)
+            return getInt(colIdx);
+        else if (targetCls == Long.class)
+            return getLong(colIdx);
+        else if (targetCls == Float.class)
+            return getFloat(colIdx);
+        else if (targetCls == Double.class)
+            return getDouble(colIdx);
+        else if (targetCls == String.class)
+            return getString(colIdx);
+        else if (targetCls == BigDecimal.class)
+            return getBigDecimal(colIdx);
+        else if (targetCls == Date.class)
+            return getDate(colIdx);
+        else if (targetCls == Time.class)
+            return getTime(colIdx);
+        else if (targetCls == Timestamp.class)
+            return getTimestamp(colIdx);
+        else if (targetCls == byte[].class)
+            return getBytes(colIdx);
+        else if (targetCls == URL.class)
+            return getURL(colIdx);
         else {
-            colIdx = cols.indexOf(name) + 1;
+            Object val = getValue(colIdx);
 
-            if (colIdx <= 0)
-                throw new SQLException("Invalid column label: " + colLb);
+            if (val == null)
+                return null;
 
-            stmt.fieldsIdxs.put(name, colIdx);
-        }
+            Class<?> cls = val.getClass();
 
-        return getTypedValue(colIdx, cls);
+            if (targetCls == cls)
+                return val;
+            else
+                throw new SQLException("Cannot convert to " + targetCls.getName() + ": " + val,
+                    SqlStateCode.CONVERSION_FAILED);
+        }
     }
 
     /**
-     * Gets casted field value by index.
+     * Gets object field value by index.
      *
      * @param colIdx Column index.
-     * @param cls Value class.
-     * @return Casted field value.
+     * @return Object field value.
      * @throws SQLException In case of error.
      */
     @SuppressWarnings("unchecked")
-    private <T> T getTypedValue(int colIdx, Class<T> cls) throws SQLException {
+    private Object getValue(int colIdx) throws SQLException {
         ensureNotClosed();
         ensureHasCurrentRow();
 
@@ -1545,18 +1846,10 @@ public class JdbcResultSet implements ResultSet {
 
             wasNull = val == null;
 
-            if (val == null)
-                return null;
-            else if (cls == String.class)
-                return (T)String.valueOf(val);
-            else
-                return cls.cast(val);
-        }
-        catch (IndexOutOfBoundsException ignored) {
-            throw new SQLException("Invalid column index: " + colIdx);
+            return val;
         }
-        catch (ClassCastException ignored) {
-            throw new SQLException("Cannot convert to " + cls.getSimpleName().toLowerCase(), SqlStateCode.CONVERSION_FAILED);
+        catch (IndexOutOfBoundsException e) {
+            throw new SQLException("Invalid column index: " + colIdx, e);
         }
     }
 


[6/9] ignite git commit: Updated Ignite description

Posted by vo...@apache.org.
Updated Ignite description


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

Branch: refs/heads/ignite-2.7
Commit: e73137cb7e1d75d36fb8740bebdb5ba949c4acac
Parents: 32165db
Author: Denis Magda <dm...@gridgain.com>
Authored: Tue Sep 25 23:10:10 2018 -0700
Committer: devozerov <vo...@gridgain.com>
Committed: Wed Sep 26 12:37:31 2018 +0300

----------------------------------------------------------------------
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/e73137cb/README.md
----------------------------------------------------------------------
diff --git a/README.md b/README.md
index e6f5abf..80c8a92 100644
--- a/README.md
+++ b/README.md
@@ -22,7 +22,7 @@ You can find the full Apache Ignite documentation here: [Full documentation][doc
 
 <p align="center">
     <a href="https://ignite.apache.org/whatisignite.html">
-        <img src="https://ignite.apache.org/images/ignite_architecture.png" width="900px"/>
+        <img src="https://ignite.apache.org/images/ignite_architecture.png" width="600px"/>
     </a>
 </p>
 


[3/9] ignite git commit: IGNITE-9538: MVCC: update partition counters on prepare phase. This closes #4795.

Posted by vo...@apache.org.
IGNITE-9538: MVCC: update partition counters on prepare phase. This closes #4795.


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

Branch: refs/heads/ignite-2.7
Commit: cc9db58eed278ba30dafc1d20bd622bfb1b860ab
Parents: 5f5f173
Author: rkondakov <ko...@mail.ru>
Authored: Tue Sep 25 16:55:43 2018 +0300
Committer: devozerov <vo...@gridgain.com>
Committed: Wed Sep 26 12:37:02 2018 +0300

----------------------------------------------------------------------
 .../communication/GridIoMessageFactory.java     |   5 +-
 .../processors/cache/GridCacheEntryEx.java      |   6 -
 .../processors/cache/GridCacheMapEntry.java     | 132 ++---
 .../cache/GridCacheMvccEntryInfo.java           |  14 +-
 .../cache/GridCacheSharedContext.java           |   1 -
 .../cache/IgniteCacheOffheapManager.java        |  18 +-
 .../cache/IgniteCacheOffheapManagerImpl.java    |  70 +--
 .../cache/PartitionUpdateCounter.java           | 209 +++++++
 .../GridDistributedTxRemoteAdapter.java         |  81 +--
 .../distributed/dht/GridDhtCacheEntry.java      |   5 -
 .../distributed/dht/GridDhtLocalPartition.java  |  38 +-
 .../dht/GridDhtTransactionalCacheAdapter.java   |   2 +-
 .../dht/GridDhtTxAbstractEnlistFuture.java      |  62 +--
 .../distributed/dht/GridDhtTxFinishFuture.java  |  13 +-
 .../distributed/dht/GridDhtTxFinishRequest.java |  31 +-
 .../distributed/dht/GridDhtTxLocalAdapter.java  |  39 +-
 .../distributed/dht/GridDhtTxPrepareFuture.java |   8 +-
 .../dht/GridDhtTxPrepareRequest.java            |  37 +-
 .../dht/GridDhtTxQueryEnlistRequest.java        |  32 +-
 .../dht/GridDhtTxQueryFirstEnlistRequest.java   |  45 +-
 .../cache/distributed/dht/GridDhtTxRemote.java  |   8 +-
 .../dht/NearTxQueryEnlistResultHandler.java     |  25 +-
 .../dht/PartitionUpdateCounters.java            | 123 -----
 .../dht/PartitionUpdateCountersMessage.java     | 259 +++++++++
 .../near/GridNearTxFinishFuture.java            |   1 +
 .../cache/distributed/near/GridNearTxLocal.java |   9 +-
 .../near/GridNearTxQueryEnlistResponse.java     |  35 +-
 .../GridNearTxQueryResultsEnlistFuture.java     |  10 +-
 .../GridNearTxQueryResultsEnlistResponse.java   |  41 +-
 .../cache/mvcc/MvccProcessorImpl.java           |   8 +-
 .../cache/mvcc/MvccUpdateVersionAware.java      |   5 +
 .../processors/cache/mvcc/MvccUtils.java        |  30 +-
 .../cache/persistence/CacheDataRowAdapter.java  |   5 +
 .../persistence/GridCacheOffheapManager.java    |  30 +-
 .../cache/persistence/tree/io/DataPageIO.java   |  15 +-
 .../cache/persistence/tree/io/PageIO.java       |   6 -
 .../cache/transactions/IgniteTxAdapter.java     |   4 +-
 .../cache/transactions/IgniteTxHandler.java     |  16 +-
 .../transactions/IgniteTxLocalAdapter.java      | 120 ++--
 .../cache/transactions/TxCounters.java          | 111 ++--
 .../cache/tree/mvcc/data/MvccDataRow.java       |  22 +-
 .../cache/tree/mvcc/data/MvccUpdateDataRow.java |  37 +-
 .../cache/tree/mvcc/data/MvccUpdateResult.java  |  10 +
 .../processors/cache/GridCacheTestEntryEx.java  |   5 +-
 .../CacheMvccConfigurationValidationTest.java   |   4 +-
 .../database/CacheFreeListImplSelfTest.java     |   5 +
 .../processors/query/h2/opt/GridH2Row.java      |   4 +
 .../mvcc/CacheMvccSqlUpdateCountersTest.java    | 549 +++++++++++++++++++
 .../testsuites/IgniteCacheMvccSqlTestSuite.java |   2 +
 49 files changed, 1698 insertions(+), 649 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java
index 04f6b5f..41c75be 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java
@@ -79,7 +79,7 @@ import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtTxQuer
 import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtTxQueryEnlistResponse;
 import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtTxQueryFirstEnlistRequest;
 import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtUnlockRequest;
-import org.apache.ignite.internal.processors.cache.distributed.dht.PartitionUpdateCounters;
+import org.apache.ignite.internal.processors.cache.distributed.dht.PartitionUpdateCountersMessage;
 import org.apache.ignite.internal.processors.cache.distributed.dht.atomic.GridDhtAtomicDeferredUpdateResponse;
 import org.apache.ignite.internal.processors.cache.distributed.dht.atomic.GridDhtAtomicNearResponse;
 import org.apache.ignite.internal.processors.cache.distributed.dht.atomic.GridDhtAtomicSingleUpdateRequest;
@@ -103,7 +103,6 @@ import org.apache.ignite.internal.processors.cache.distributed.dht.preloader.Gri
 import org.apache.ignite.internal.processors.cache.distributed.dht.preloader.GridDhtPartitionsFullMessage;
 import org.apache.ignite.internal.processors.cache.distributed.dht.preloader.GridDhtPartitionsSingleMessage;
 import org.apache.ignite.internal.processors.cache.distributed.dht.preloader.GridDhtPartitionsSingleRequest;
-import org.apache.ignite.internal.processors.cache.distributed.dht.preloader.latch.LatchAckMessage;
 import org.apache.ignite.internal.processors.cache.distributed.near.CacheVersionedValue;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearGetRequest;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearGetResponse;
@@ -1058,7 +1057,7 @@ public class GridIoMessageFactory implements MessageFactory {
                 break;
 
             case 157:
-                msg = new PartitionUpdateCounters();
+                msg = new PartitionUpdateCountersMessage();
 
                 break;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheEntryEx.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheEntryEx.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheEntryEx.java
index 3a2af5d..1f38eb7 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheEntryEx.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheEntryEx.java
@@ -348,7 +348,6 @@ public interface GridCacheEntryEx {
      * @param val Value to set.
      * @param ttl0 TTL.
      * @param topVer Topology version.
-     * @param updateCntr Update counter.
      * @param mvccVer Mvcc version.
      * @param op Cache operation.
      * @param needHistory Whether to collect rows created or affected by the current tx.
@@ -364,7 +363,6 @@ public interface GridCacheEntryEx {
         CacheObject val,
         long ttl0,
         AffinityTopologyVersion topVer,
-        @Nullable Long updateCntr,
         MvccSnapshot mvccVer,
         GridCacheOperation op,
         boolean needHistory,
@@ -374,7 +372,6 @@ public interface GridCacheEntryEx {
      * @param tx Cache transaction.
      * @param affNodeId Partitioned node iD.
      * @param topVer Topology version.
-     * @param updateCntr Update counter.
      * @param mvccVer Mvcc version.
      * @param needHistory Whether to collect rows created or affected by the current tx.
      * @return Tuple containing success flag and old value. If success is {@code false},
@@ -386,7 +383,6 @@ public interface GridCacheEntryEx {
         @Nullable IgniteInternalTx tx,
         UUID affNodeId,
         AffinityTopologyVersion topVer,
-        @Nullable Long updateCntr,
         MvccSnapshot mvccVer,
         boolean needHistory) throws IgniteCheckedException, GridCacheEntryRemovedException;
 
@@ -1157,7 +1153,6 @@ public interface GridCacheEntryEx {
      * @param tx Transaction.
      * @param affNodeId Affinity node id.
      * @param topVer Topology version.
-     * @param updateCntr Update counter.
      * @param op Cache operation.
      * @param mvccVer Mvcc version.  @return Update result.
      * @throws IgniteCheckedException, If failed.
@@ -1167,7 +1162,6 @@ public interface GridCacheEntryEx {
         IgniteInternalTx tx,
         UUID affNodeId,
         AffinityTopologyVersion topVer,
-        Long updateCntr,
         List<GridCacheEntryInfo> entries,
         GridCacheOperation op,
         MvccSnapshot mvccVer)

http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java
index fd8b2cd..cdb5656 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java
@@ -39,7 +39,6 @@ import org.apache.ignite.internal.IgniteInternalFuture;
 import org.apache.ignite.internal.NodeStoppingException;
 import org.apache.ignite.internal.UnregisteredBinaryTypeException;
 import org.apache.ignite.internal.UnregisteredClassException;
-import org.apache.ignite.internal.processors.cache.persistence.StorageException;
 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;
@@ -61,11 +60,13 @@ import org.apache.ignite.internal.processors.cache.mvcc.txlog.TxState;
 import org.apache.ignite.internal.processors.cache.persistence.CacheDataRow;
 import org.apache.ignite.internal.processors.cache.persistence.CacheDataRowAdapter;
 import org.apache.ignite.internal.processors.cache.persistence.DataRegion;
+import org.apache.ignite.internal.processors.cache.persistence.StorageException;
 import org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryListener;
 import org.apache.ignite.internal.processors.cache.transactions.IgniteInternalTx;
 import org.apache.ignite.internal.processors.cache.transactions.IgniteTxEntry;
 import org.apache.ignite.internal.processors.cache.transactions.IgniteTxKey;
 import org.apache.ignite.internal.processors.cache.transactions.IgniteTxLocalAdapter;
+import org.apache.ignite.internal.processors.cache.transactions.TxCounters;
 import org.apache.ignite.internal.processors.cache.tree.mvcc.data.MvccUpdateResult;
 import org.apache.ignite.internal.processors.cache.tree.mvcc.data.ResultType;
 import org.apache.ignite.internal.processors.cache.version.GridCacheLazyPlainVersionedEntry;
@@ -111,11 +112,11 @@ import static org.apache.ignite.internal.processors.cache.GridCacheOperation.DEL
 import static org.apache.ignite.internal.processors.cache.GridCacheOperation.READ;
 import static org.apache.ignite.internal.processors.cache.GridCacheOperation.TRANSFORM;
 import static org.apache.ignite.internal.processors.cache.GridCacheOperation.UPDATE;
+import static org.apache.ignite.internal.processors.cache.GridCacheUpdateAtomicResult.UpdateOutcome.INVOKE_NO_OP;
+import static org.apache.ignite.internal.processors.cache.GridCacheUpdateAtomicResult.UpdateOutcome.REMOVE_NO_VAL;
 import static org.apache.ignite.internal.processors.cache.persistence.CacheDataRowAdapter.RowData.NO_KEY;
 import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.CONCURRENT_UPDATE;
 import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.DUPLICATE_KEY;
-import static org.apache.ignite.internal.processors.cache.GridCacheUpdateAtomicResult.UpdateOutcome.INVOKE_NO_OP;
-import static org.apache.ignite.internal.processors.cache.GridCacheUpdateAtomicResult.UpdateOutcome.REMOVE_NO_VAL;
 import static org.apache.ignite.internal.processors.dr.GridDrType.DR_BACKUP;
 import static org.apache.ignite.internal.processors.dr.GridDrType.DR_NONE;
 import static org.apache.ignite.internal.processors.dr.GridDrType.DR_PRIMARY;
@@ -1042,7 +1043,6 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
         CacheObject val,
         long ttl0,
         AffinityTopologyVersion topVer,
-        @Nullable Long updateCntr,
         MvccSnapshot mvccVer,
         GridCacheOperation op,
         boolean needHistory,
@@ -1111,7 +1111,7 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
 
                 IgniteInternalFuture<?> lockFut = cctx.kernalContext().coordinators().waitFor(cctx, lockVer);
 
-                lockFut.listen(new MvccUpdateLockListener(tx, this, affNodeId, topVer, val, ttl0, updateCntr, mvccVer,
+                lockFut.listen(new MvccUpdateLockListener(tx, this, affNodeId, topVer, val, ttl0, mvccVer,
                     op, needHistory, noCreate, resFut));
 
                 return new GridCacheUpdateTxResult(false, resFut);
@@ -1123,13 +1123,23 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
             if (cctx.deferredDelete() && deletedUnlocked() && !detached())
                 deletedUnlocked(false);
 
-            assert tx.local() && updateCntr == null || !tx.local() && updateCntr != null && updateCntr > 0;
+            if (res.resultType() == ResultType.PREV_NULL) {
+                TxCounters counters = tx.txCounters(true);
 
-            if (tx.local())
-                updateCntr = nextMvccPartitionCounter();
+                if (res.isOwnValueOverridden()) {
+                    if (res.isKeyAbsentBefore())
+                        counters.incrementUpdateCounter(cctx.cacheId(), partition());
+                }
+                else
+                    counters.incrementUpdateCounter(cctx.cacheId(), partition());
+
+                counters.accumulateSizeDelta(cctx.cacheId(), partition(), 1);
+            }
+            else if (res.resultType() == ResultType.PREV_NOT_NULL && !res.isOwnValueOverridden()) {
+                TxCounters counters = tx.txCounters(true);
 
-            if (res.resultType() == ResultType.PREV_NULL)
-                tx.txCounters(true).accumulateSizeDelta(cctx.cacheId(), partition(), 1);
+                counters.incrementUpdateCounter(cctx.cacheId(), partition());
+            }
 
             if (cctx.group().persistenceEnabled() && cctx.group().walEnabled())
                 logPtr = cctx.shared().wal().log(new DataRecord(new DataEntry(
@@ -1141,7 +1151,7 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
                         newVer,
                         expireTime,
                         key.partition(),
-                        updateCntr)));
+                        0L)));
 
             update(val, expireTime, ttl, newVer, true);
 
@@ -1157,9 +1167,9 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
             }
         }
 
-        onUpdateFinished(updateCntr);
+        onUpdateFinished(0L);
 
-        GridCacheUpdateTxResult updRes = valid ? new GridCacheUpdateTxResult(true, updateCntr, logPtr) :
+        GridCacheUpdateTxResult updRes = valid ? new GridCacheUpdateTxResult(true, 0L, logPtr) :
             new GridCacheUpdateTxResult(false, logPtr);
 
         updRes.mvccHistory(res.history());
@@ -1172,7 +1182,6 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
         IgniteInternalTx tx,
         UUID affNodeId,
         AffinityTopologyVersion topVer,
-        @Nullable Long updateCntr,
         MvccSnapshot mvccVer,
         boolean needHistory) throws IgniteCheckedException, GridCacheEntryRemovedException {
         assert tx != null;
@@ -1212,7 +1221,7 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
 
                 IgniteInternalFuture<?> lockFut = cctx.kernalContext().coordinators().waitFor(cctx, lockVer);
 
-                lockFut.listen(new MvccRemoveLockListener(tx, this, affNodeId, topVer, updateCntr, mvccVer, needHistory,
+                lockFut.listen(new MvccRemoveLockListener(tx, this, affNodeId, topVer, mvccVer, needHistory,
                     resFut));
 
                 return new GridCacheUpdateTxResult(false, resFut);
@@ -1221,16 +1230,21 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
             if (cctx.deferredDelete() && deletedUnlocked() && !detached())
                 deletedUnlocked(false);
 
-            assert tx.local() && updateCntr == null || !tx.local() && updateCntr != null && updateCntr > 0;
+            if (res.resultType() == ResultType.PREV_NOT_NULL) {
+                TxCounters counters = tx.txCounters(true);
 
-            if (tx.local())
-                updateCntr = nextMvccPartitionCounter();
+                if (res.isOwnValueOverridden()) {
+                    if (res.isKeyAbsentBefore()) // Do not count own update removal.
+                        counters.decrementUpdateCounter(cctx.cacheId(), partition());
+                }
+                else
+                    counters.incrementUpdateCounter(cctx.cacheId(), partition());
 
-            if (res.resultType() == ResultType.PREV_NOT_NULL)
-                tx.txCounters(true).accumulateSizeDelta(cctx.cacheId(), partition(), -1);
+                counters.accumulateSizeDelta(cctx.cacheId(), partition(), -1);
+            }
 
             if (cctx.group().persistenceEnabled() && cctx.group().walEnabled())
-                logPtr = logTxUpdate(tx, null, 0, updateCntr);
+                logPtr = logTxUpdate(tx, null, 0, 0L);
 
             update(null, 0, 0, newVer, true);
 
@@ -1246,9 +1260,9 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
             }
         }
 
-        onUpdateFinished(updateCntr);
+        onUpdateFinished(0L);
 
-        GridCacheUpdateTxResult updRes = valid ? new GridCacheUpdateTxResult(true, updateCntr, logPtr) :
+        GridCacheUpdateTxResult updRes = valid ? new GridCacheUpdateTxResult(true, 0L, logPtr) :
             new GridCacheUpdateTxResult(false, logPtr);
 
         updRes.mvccHistory(res.history());
@@ -3420,14 +3434,6 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
         return 0;
     }
 
-    /**
-     * @return Next mvcc update counter.
-     */
-    protected long nextMvccPartitionCounter() {
-        return 0;
-    }
-
-
     /** {@inheritDoc} */
     @Override public GridCacheVersionedEntryEx versionedEntry(final boolean keepBinary)
         throws IgniteCheckedException, GridCacheEntryRemovedException {
@@ -4929,9 +4935,6 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
         private final MvccSnapshot mvccVer;
 
         /** */
-        private final Long updateCntr;
-
-        /** */
         private final boolean needHistory;
 
         /** */
@@ -4945,7 +4948,6 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
             GridCacheMapEntry entry,
             UUID affNodeId,
             AffinityTopologyVersion topVer,
-            Long updateCntr,
             MvccSnapshot mvccVer,
             boolean needHistory,
             GridFutureAdapter<GridCacheUpdateTxResult> resFut) {
@@ -4954,7 +4956,6 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
             this.topVer = topVer;
             this.affNodeId = affNodeId;
             this.mvccVer = mvccVer;
-            this.updateCntr = updateCntr;
             this.needHistory = needHistory;
             this.resFut = resFut;
         }
@@ -4962,7 +4963,6 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
         /** {@inheritDoc} */
         @Override public void apply(IgniteInternalFuture lockFut) {
             WALPointer logPtr = null;
-            long updateCntr0;
             boolean valid;
 
             GridCacheContext cctx = entry.context();
@@ -5019,15 +5019,18 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
                 if (cctx.deferredDelete() && entry.deletedUnlocked() && !entry.detached())
                     entry.deletedUnlocked(false);
 
-                assert tx.local() && updateCntr == null || !tx.local() && updateCntr != null && updateCntr > 0;
+                if (res.resultType() == ResultType.PREV_NOT_NULL) {
+                    TxCounters counters = tx.txCounters(true);
 
-                updateCntr0 = tx.local() ? entry.nextMvccPartitionCounter() : updateCntr;
-
-                if (updateCntr != null && updateCntr != 0)
-                    updateCntr0 = updateCntr;
+                    if (res.isOwnValueOverridden()) {
+                        if (res.isKeyAbsentBefore()) // Do not count own update removal.
+                            counters.decrementUpdateCounter(cctx.cacheId(), entry.partition());
+                    }
+                    else
+                        counters.incrementUpdateCounter(cctx.cacheId(), entry.partition());
 
-                if (res.resultType() == ResultType.PREV_NOT_NULL)
-                    tx.txCounters(true).accumulateSizeDelta(cctx.cacheId(), entry.partition(), -1);
+                    counters.accumulateSizeDelta(cctx.cacheId(), entry.partition(), -1);
+                }
 
                 if (cctx.group().persistenceEnabled() && cctx.group().walEnabled())
                     logPtr = cctx.shared().wal().log(new DataRecord(new DataEntry(
@@ -5039,7 +5042,7 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
                             tx.writeVersion(),
                             0,
                             entry.key().partition(),
-                            updateCntr0)));
+                            0)));
 
                 entry.update(null, 0, 0, newVer, true);
 
@@ -5060,9 +5063,9 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
                 }
             }
 
-            entry.onUpdateFinished(updateCntr0);
+            entry.onUpdateFinished(0L);
 
-            GridCacheUpdateTxResult updRes = valid ? new GridCacheUpdateTxResult(true, updateCntr0, logPtr)
+            GridCacheUpdateTxResult updRes = valid ? new GridCacheUpdateTxResult(true, 0L, logPtr)
                 : new GridCacheUpdateTxResult(false, logPtr);
 
             updRes.mvccHistory(res.history());
@@ -5189,9 +5192,6 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
         private final long ttl;
 
         /** */
-        private final Long updateCntr;
-
-        /** */
         private final MvccSnapshot mvccVer;
 
         /** */
@@ -5216,7 +5216,6 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
             AffinityTopologyVersion topVer,
             CacheObject val,
             long ttl,
-            Long updateCntr,
             MvccSnapshot mvccVer,
             GridCacheOperation op,
             boolean needHistory,
@@ -5228,7 +5227,6 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
             this.topVer = topVer;
             this.val = val;
             this.ttl = ttl;
-            this.updateCntr = updateCntr;
             this.mvccVer = mvccVer;
             this.op = op;
             this.needHistory = needHistory;
@@ -5239,7 +5237,6 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
         /** {@inheritDoc} */
         @Override public void apply(IgniteInternalFuture lockFut) {
             WALPointer logPtr = null;
-            long updateCntr0;
             boolean valid;
 
             GridCacheContext cctx = entry.context();
@@ -5312,12 +5309,23 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
                 if (cctx.deferredDelete() && entry.deletedUnlocked() && !entry.detached())
                     entry.deletedUnlocked(false);
 
-                assert tx.local() && updateCntr == null || !tx.local() && updateCntr != null && updateCntr > 0;
+                if (res.resultType() == ResultType.PREV_NULL) {
+                    TxCounters counters = tx.txCounters(true);
+
+                    if (res.isOwnValueOverridden()) {
+                        if (res.isKeyAbsentBefore())
+                            counters.incrementUpdateCounter(cctx.cacheId(), entry.partition());
+                    }
+                    else
+                        counters.incrementUpdateCounter(cctx.cacheId(), entry.partition());
 
-                updateCntr0 = tx.local() ? entry.nextMvccPartitionCounter() : updateCntr;
+                    counters.accumulateSizeDelta(cctx.cacheId(), entry.partition(), 1);
+                }
+                else if (res.resultType() == ResultType.PREV_NOT_NULL && !res.isOwnValueOverridden()) {
+                    TxCounters counters = tx.txCounters(true);
 
-                if (res.resultType() == ResultType.PREV_NULL)
-                    tx.txCounters(true).accumulateSizeDelta(cctx.cacheId(), entry.partition(), 1);
+                    counters.incrementUpdateCounter(cctx.cacheId(), entry.partition());
+                }
 
                 if (cctx.group().persistenceEnabled() && cctx.group().walEnabled())
                     logPtr = cctx.shared().wal().log(new DataRecord(new DataEntry(
@@ -5329,7 +5337,7 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
                             newVer,
                             expireTime,
                             entry.key().partition(),
-                            updateCntr0)));
+                            0L)));
 
                 entry.update(val, expireTime, ttl, newVer, true);
 
@@ -5350,9 +5358,9 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
                 }
             }
 
-            entry.onUpdateFinished(updateCntr0);
+            entry.onUpdateFinished(0L);
 
-            GridCacheUpdateTxResult updRes = valid ? new GridCacheUpdateTxResult(true, updateCntr0, logPtr)
+            GridCacheUpdateTxResult updRes = valid ? new GridCacheUpdateTxResult(true, 0L, logPtr)
                 : new GridCacheUpdateTxResult(false, logPtr);
 
             updRes.mvccHistory(res.history());
@@ -6451,12 +6459,10 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
         IgniteInternalTx tx,
         UUID affNodeId,
         AffinityTopologyVersion topVer,
-        Long updateCntr,
         List<GridCacheEntryInfo> entries,
         GridCacheOperation op,
         MvccSnapshot mvccVer)
         throws IgniteCheckedException, GridCacheEntryRemovedException {
-        assert updateCntr != null && updateCntr > 0 && !tx.local();
 
         WALPointer logPtr = null;
 
@@ -6506,7 +6512,7 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
                     ver,
                     CU.EXPIRE_TIME_ETERNAL,
                     key.partition(),
-                    updateCntr)));
+                    0L)));
 
             update(val, expireTime, ttl, ver, true);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvccEntryInfo.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvccEntryInfo.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvccEntryInfo.java
index a80ddc0..bd4146e 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvccEntryInfo.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvccEntryInfo.java
@@ -24,8 +24,9 @@ import org.apache.ignite.internal.util.typedef.internal.S;
 import org.apache.ignite.plugin.extensions.communication.MessageReader;
 import org.apache.ignite.plugin.extensions.communication.MessageWriter;
 
-import static org.apache.ignite.internal.processors.cache.persistence.tree.io.PageIO.MVCC_HINTS_BIT_OFF;
-import static org.apache.ignite.internal.processors.cache.persistence.tree.io.PageIO.MVCC_HINTS_MASK;
+import static org.apache.ignite.internal.processors.cache.mvcc.MvccUtils.MVCC_HINTS_BIT_OFF;
+import static org.apache.ignite.internal.processors.cache.mvcc.MvccUtils.MVCC_HINTS_MASK;
+import static org.apache.ignite.internal.processors.cache.mvcc.MvccUtils.MVCC_OP_COUNTER_MASK;
 
 /**
  *
@@ -64,7 +65,7 @@ public class GridCacheMvccEntryInfo extends GridCacheEntryInfo implements MvccVe
 
     /** {@inheritDoc} */
     @Override public int newMvccOperationCounter() {
-        return newMvccOpCntr & ~MVCC_HINTS_MASK;
+        return newMvccOpCntr & ~MVCC_OP_COUNTER_MASK;
     }
 
     /** {@inheritDoc} */
@@ -84,7 +85,7 @@ public class GridCacheMvccEntryInfo extends GridCacheEntryInfo implements MvccVe
 
     /** {@inheritDoc} */
     @Override public int mvccOperationCounter() {
-        return mvccOpCntr & ~MVCC_HINTS_MASK;
+        return mvccOpCntr & ~MVCC_OP_COUNTER_MASK;
     }
 
     /** {@inheritDoc} */
@@ -121,6 +122,11 @@ public class GridCacheMvccEntryInfo extends GridCacheEntryInfo implements MvccVe
     }
 
     /** {@inheritDoc} */
+    @Override public boolean isKeyAbsentBefore() {
+        return false;
+    }
+
+    /** {@inheritDoc} */
     @Override public boolean writeTo(ByteBuffer buf, MessageWriter writer) {
         writer.setBuffer(buf);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheSharedContext.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheSharedContext.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheSharedContext.java
index a234a86..4698db4 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
@@ -43,7 +43,6 @@ import org.apache.ignite.internal.pagemem.store.IgnitePageStoreManager;
 import org.apache.ignite.internal.pagemem.wal.IgniteWriteAheadLogManager;
 import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
 import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtPartitionTopology;
-import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtTopologyFuture;
 import org.apache.ignite.internal.processors.cache.distributed.dht.PartitionsEvictManager;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxLocal;
 import org.apache.ignite.internal.processors.cache.jta.CacheJtaManagerAdapter;

http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManager.java
----------------------------------------------------------------------
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 fdf42fe..c30f9e6 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
@@ -638,19 +638,25 @@ public interface IgniteCacheOffheapManager {
         void updateCounter(long val);
 
         /**
-         * @return Next update counter.
+         * Updates counters from start value by delta value.
+         *
+         * @param start Start.
+         * @param delta Delta
          */
-        public long nextUpdateCounter();
+        void updateCounter(long start, long delta);
 
         /**
-         * @return Next mvcc update counter.
+         * @return Next update counter.
          */
-        long nextMvccUpdateCounter();
+        public long nextUpdateCounter();
 
         /**
-         * @return Current mvcc update counter value.
+         * Returns current value and updates counter by delta.
+         *
+         * @param delta Delta.
+         * @return Current value.
          */
-        long mvccUpdateCounter();
+        public long getAndIncrementUpdateCounter(long delta);
 
         /**
          * @return Initial update counter.

http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java
index 9919240..dd4b452 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
@@ -110,6 +110,8 @@ import static org.apache.ignite.internal.processors.cache.distributed.dht.GridDh
 import static org.apache.ignite.internal.processors.cache.mvcc.MvccUtils.INITIAL_VERSION;
 import static org.apache.ignite.internal.processors.cache.mvcc.MvccUtils.MVCC_COUNTER_NA;
 import static org.apache.ignite.internal.processors.cache.mvcc.MvccUtils.MVCC_CRD_COUNTER_NA;
+import static org.apache.ignite.internal.processors.cache.mvcc.MvccUtils.MVCC_HINTS_BIT_OFF;
+import static org.apache.ignite.internal.processors.cache.mvcc.MvccUtils.MVCC_OP_COUNTER_MASK;
 import static org.apache.ignite.internal.processors.cache.mvcc.MvccUtils.MVCC_OP_COUNTER_NA;
 import static org.apache.ignite.internal.processors.cache.mvcc.MvccUtils.compare;
 import static org.apache.ignite.internal.processors.cache.mvcc.MvccUtils.compareNewVersion;
@@ -119,8 +121,6 @@ import static org.apache.ignite.internal.processors.cache.mvcc.MvccUtils.state;
 import static org.apache.ignite.internal.processors.cache.mvcc.MvccUtils.unexpectedStateException;
 import static org.apache.ignite.internal.processors.cache.persistence.GridCacheOffheapManager.EMPTY_CURSOR;
 import static org.apache.ignite.internal.processors.cache.persistence.tree.io.DataPageIO.MVCC_INFO_SIZE;
-import static org.apache.ignite.internal.processors.cache.persistence.tree.io.PageIO.MVCC_HINTS_BIT_OFF;
-import static org.apache.ignite.internal.processors.cache.persistence.tree.io.PageIO.MVCC_HINTS_MASK;
 import static org.apache.ignite.internal.util.IgniteTree.OperationType.NOOP;
 import static org.apache.ignite.internal.util.IgniteTree.OperationType.PUT;
 
@@ -1401,14 +1401,7 @@ public class IgniteCacheOffheapManagerImpl implements IgniteCacheOffheapManager
         private final CacheDataTree dataTree;
 
         /** Update counter. */
-        protected final AtomicLong cntr = new AtomicLong();
-
-        /**
-         * Mvcc update counter. This counter is used for an mvcc-style entries updates where this counter is
-         * incremented on each entry write (which happens before commit), but main update counter is updated
-         * on commit phase only.
-         */
-        protected final AtomicLong mvccUpdCntr = new AtomicLong();
+        protected final PartitionUpdateCounter pCntr = new PartitionUpdateCounter(log);
 
         /** Partition size. */
         private final AtomicLong storageSize = new AtomicLong();
@@ -1416,9 +1409,6 @@ public class IgniteCacheOffheapManagerImpl implements IgniteCacheOffheapManager
         /** */
         private final ConcurrentMap<Integer, AtomicLong> cacheSizes = new ConcurrentHashMap<>();
 
-        /** Initial update counter. */
-        protected long initCntr;
-
         /** Mvcc remove handler. */
         private final PageHandler<MvccVersion, Boolean> mvccUpdateMarker = new MvccMarkUpdatedHandler();
 
@@ -1514,35 +1504,37 @@ public class IgniteCacheOffheapManagerImpl implements IgniteCacheOffheapManager
 
         /** {@inheritDoc} */
         @Override public long nextUpdateCounter() {
-            return cntr.incrementAndGet();
+            return pCntr.next();
         }
 
         /** {@inheritDoc} */
-        @Override public long updateCounter() {
-            return cntr.get();
+        @Override public long initialUpdateCounter() {
+            return pCntr.initial();
         }
 
         /** {@inheritDoc} */
-        @Override public void updateCounter(long val) {
-            while (true) {
-                long val0 = cntr.get();
+        @Override public void updateInitialCounter(long cntr) {
+            pCntr.updateInitial(cntr);
+        }
 
-                if (val0 >= val)
-                    break;
+        /** {@inheritDoc} */
+        @Override public long getAndIncrementUpdateCounter(long delta) {
+            return pCntr.getAndAdd(delta);
+        }
 
-                if (cntr.compareAndSet(val0, val))
-                    break;
-            }
+        /** {@inheritDoc} */
+        @Override public long updateCounter() {
+            return pCntr.get();
         }
 
         /** {@inheritDoc} */
-        @Override public long nextMvccUpdateCounter() {
-            return mvccUpdCntr.incrementAndGet();
+        @Override public void updateCounter(long val) {
+            pCntr.update(val);
         }
 
         /** {@inheritDoc} */
-        @Override public long mvccUpdateCounter() {
-            return mvccUpdCntr.get();
+        @Override public void updateCounter(long start, long delta) {
+            pCntr.update(start, delta);
         }
 
         /** {@inheritDoc} */
@@ -2771,29 +2763,15 @@ public class IgniteCacheOffheapManagerImpl implements IgniteCacheOffheapManager
         }
 
         /** {@inheritDoc} */
-        @Override public long initialUpdateCounter() {
-            return initCntr;
-        }
-
-        /** {@inheritDoc} */
-        @Override public void updateInitialCounter(long cntr) {
-            if (updateCounter() < cntr)
-                updateCounter(cntr);
-
-            initCntr = cntr;
-        }
-
-        /** {@inheritDoc} */
         @Override public void setRowCacheCleaner(GridQueryRowCacheCleaner rowCacheCleaner) {
             rowStore().setRowCacheCleaner(rowCacheCleaner);
         }
 
         /** {@inheritDoc} */
         @Override public void init(long size, long updCntr, @Nullable Map<Integer, Long> cacheSizes) {
-            initCntr = updCntr;
-            storageSize.set(size);
+            pCntr.init(updCntr);
 
-            cntr.set(updCntr);
+            storageSize.set(size);
 
             if (cacheSizes != null) {
                 for (Map.Entry<Integer, Long> e : cacheSizes.entrySet())
@@ -3143,13 +3121,13 @@ public class IgniteCacheOffheapManagerImpl implements IgniteCacheOffheapManager
             long crd = iox.mvccCoordinator(pageAddr, offset);
             long cntr = iox.mvccCounter(pageAddr, offset);
             int opCntrAndHint = iox.mvccOperationCounter(pageAddr, offset);
-            int opCntr = opCntrAndHint & ~MVCC_HINTS_MASK;
+            int opCntr = opCntrAndHint & ~MVCC_OP_COUNTER_MASK;
             byte txState = (byte)(opCntrAndHint >>> MVCC_HINTS_BIT_OFF);
 
             long newCrd = iox.newMvccCoordinator(pageAddr, offset);
             long newCntr = iox.newMvccCounter(pageAddr, offset);
             int newOpCntrAndHint = iox.newMvccOperationCounter(pageAddr, offset);
-            int newOpCntr = newOpCntrAndHint & ~MVCC_HINTS_MASK;
+            int newOpCntr = newOpCntrAndHint & ~MVCC_OP_COUNTER_MASK;
             byte newTxState = (byte)(newOpCntrAndHint >>> MVCC_HINTS_BIT_OFF);
 
             assert crd == newRow.mvccCoordinatorVersion();

http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/PartitionUpdateCounter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/PartitionUpdateCounter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/PartitionUpdateCounter.java
new file mode 100644
index 0000000..b5960ab
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/PartitionUpdateCounter.java
@@ -0,0 +1,209 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.cache;
+
+import java.util.PriorityQueue;
+import java.util.Queue;
+import java.util.concurrent.atomic.AtomicLong;
+import org.apache.ignite.IgniteLogger;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Partition update counter with MVCC delta updates capabilities.
+ */
+public class PartitionUpdateCounter {
+    /** */
+    private IgniteLogger log;
+
+    /** Queue of counter update tasks*/
+    private final Queue<Item> queue = new PriorityQueue<>();
+
+    /** Counter. */
+    private final AtomicLong cntr = new AtomicLong();
+
+    /** Initial counter. */
+    private long initCntr;
+
+    /**
+     * @param log Logger.
+     */
+    PartitionUpdateCounter(IgniteLogger log) {
+        this.log = log;
+    }
+
+    /**
+     * Sets init counter.
+     *
+     * @param updateCntr Init counter valus.
+     */
+    public void init(long updateCntr) {
+        initCntr = updateCntr;
+
+        cntr.set(updateCntr);
+    }
+
+    /**
+     * @return Initial counter value.
+     */
+    public long initial() {
+        return initCntr;
+    }
+
+    /**
+     * @return Current update counter value.
+     */
+    public long get() {
+        return cntr.get();
+    }
+
+    /**
+     * Adds delta to current counter value.
+     *
+     * @param delta Delta.
+     * @return Value before add.
+     */
+    public long getAndAdd(long delta) {
+        return cntr.getAndAdd(delta);
+    }
+
+    /**
+     * @return Next update counter.
+     */
+    public long next() {
+        return cntr.incrementAndGet();
+    }
+
+    /**
+     * Sets value to update counter,
+     *
+     * @param val Values.
+     */
+    public void update(long val) {
+        while (true) {
+            long val0 = cntr.get();
+
+            if (val0 >= val)
+                break;
+
+            if (cntr.compareAndSet(val0, val))
+                break;
+        }
+    }
+
+    /**
+     * Updates counter by delta from start position.
+     *
+     * @param start Start.
+     * @param delta Delta.
+     */
+    public synchronized void update(long start, long delta) {
+        long cur = cntr.get(), next;
+
+        if (cur > start) {
+            log.warning("Stale update counter task [cur=" + cur + ", start=" + start + ", delta=" + delta + ']');
+
+            return;
+        }
+
+        if (cur < start) {
+            // backup node with gaps
+            offer(new Item(start, delta));
+
+            return;
+        }
+
+        while (true) {
+            boolean res = cntr.compareAndSet(cur, next = start + delta);
+
+            assert res;
+
+            Item peek = peek();
+
+            if (peek == null || peek.start != next)
+                return;
+
+            Item item = poll();
+
+            assert peek == item;
+
+            start = item.start;
+            delta = item.delta;
+            cur = next;
+        }
+    }
+
+    /**
+     * @param cntr Sets initial counter.
+     */
+    public void updateInitial(long cntr) {
+        if (get() < cntr)
+            update(cntr);
+
+        initCntr = cntr;
+    }
+
+    /**
+     * @return Retrieves the minimum update counter task from queue.
+     */
+    private Item poll() {
+        return queue.poll();
+    }
+
+    /**
+     * @return Checks the minimum update counter task from queue.
+     */
+    private Item peek() {
+        return queue.peek();
+    }
+
+    /**
+     * @param item Adds update task to priority queue.
+     */
+    private void offer(Item item) {
+        queue.offer(item);
+    }
+
+    /**
+     * Update counter task. Update from start value by delta value.
+     */
+    private static class Item implements Comparable<Item> {
+        /** */
+        private final long start;
+
+        /** */
+        private final long delta;
+
+        /**
+         * @param start Start value.
+         * @param delta Delta value.
+         */
+        private Item(long start, long delta) {
+            this.start = start;
+            this.delta = delta;
+        }
+
+        /** {@inheritDoc} */
+        @Override public int compareTo(@NotNull Item o) {
+            int cmp = Long.compare(this.start, o.start);
+
+            assert cmp != 0;
+
+            return cmp;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedTxRemoteAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedTxRemoteAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedTxRemoteAdapter.java
index 8e96ae2..1eccd6f 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedTxRemoteAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedTxRemoteAdapter.java
@@ -52,7 +52,7 @@ import org.apache.ignite.internal.processors.cache.GridCacheUpdateTxResult;
 import org.apache.ignite.internal.processors.cache.KeyCacheObject;
 import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtLocalPartition;
 import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtPartitionTopology;
-import org.apache.ignite.internal.processors.cache.distributed.dht.PartitionUpdateCounters;
+import org.apache.ignite.internal.processors.cache.distributed.dht.PartitionUpdateCountersMessage;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearCacheEntry;
 import org.apache.ignite.internal.processors.cache.persistence.StorageException;
 import org.apache.ignite.internal.processors.cache.transactions.IgniteInternalTx;
@@ -809,7 +809,14 @@ public abstract class GridDistributedTxRemoteAdapter extends IgniteTxAdapter
                                 }
                             }
 
-                            applyTxCounters();
+                            // Apply cache size deltas.
+                            applyTxSizes();
+
+                            TxCounters txCntrs = txCounters(false);
+
+                            // Apply update counters.
+                            if (txCntrs != null)
+                                applyPartitionsUpdatesCounters(txCntrs.updateCounters());
 
                             if (!near() && !F.isEmpty(dataEntries) && cctx.wal() != null) {
                                 // Set new update counters for data entries received from persisted tx entries.
@@ -848,38 +855,6 @@ public abstract class GridDistributedTxRemoteAdapter extends IgniteTxAdapter
     }
 
     /** {@inheritDoc} */
-    @Override protected void applyTxCounters() {
-        super.applyTxCounters();
-
-        TxCounters txCntrs = txCounters(false);
-
-        if (txCntrs == null)
-            return;
-
-        Map<Integer, PartitionUpdateCounters> updCntrs = txCntrs.updateCounters();
-
-        for (Map.Entry<Integer, PartitionUpdateCounters> entry : updCntrs.entrySet()) {
-            int cacheId = entry.getKey();
-
-            GridDhtPartitionTopology top = cctx.cacheContext(cacheId).topology();
-
-            Map<Integer, Long> cacheUpdCntrs = entry.getValue().updateCounters();
-
-            assert cacheUpdCntrs != null;
-
-            for (Map.Entry<Integer, Long> e : cacheUpdCntrs.entrySet()) {
-                long updCntr = e.getValue();
-
-                GridDhtLocalPartition dhtPart = top.localPartition(e.getKey());
-
-                assert dhtPart != null && updCntr > 0;
-
-                dhtPart.updateCounter(updCntr);
-            }
-        }
-    }
-
-    /** {@inheritDoc} */
     @Override public final void commitRemoteTx() throws IgniteCheckedException {
         if (optimistic())
             state(PREPARED);
@@ -965,6 +940,11 @@ public abstract class GridDistributedTxRemoteAdapter extends IgniteTxAdapter
             if (state(ROLLING_BACK) || state() == UNKNOWN) {
                 cctx.tm().rollbackTx(this, false, skipCompletedVers);
 
+                TxCounters counters = txCounters(false);
+
+                if (counters != null)
+                    applyPartitionsUpdatesCounters(counters.updateCounters());
+
                 state(ROLLED_BACK);
             }
         }
@@ -1029,6 +1009,39 @@ public abstract class GridDistributedTxRemoteAdapter extends IgniteTxAdapter
         }
     }
 
+    /**
+     * Applies partition counters updates for mvcc transactions.
+     *
+     * @param counters Counters values to be updated.
+     */
+    private void applyPartitionsUpdatesCounters(Iterable<PartitionUpdateCountersMessage> counters) {
+        if (counters == null)
+            return;
+
+        int cacheId = CU.UNDEFINED_CACHE_ID;
+        GridDhtPartitionTopology top = null;
+
+        for (PartitionUpdateCountersMessage counter : counters) {
+            if (counter.cacheId() != cacheId) {
+                GridCacheContext ctx0 = cctx.cacheContext(cacheId = counter.cacheId());
+
+                assert ctx0.mvccEnabled();
+
+                top = ctx0.topology();
+            }
+
+            assert top != null;
+
+            for (int i = 0; i < counter.size(); i++) {
+                GridDhtLocalPartition part = top.localPartition(counter.partition(i));
+
+                assert part != null;
+
+                part.updateCounter(counter.initialCounter(i), counter.updatesCount(i));
+            }
+        }
+    }
+
     /** {@inheritDoc} */
     @Override public String toString() {
         return GridToStringBuilder.toString(GridDistributedTxRemoteAdapter.class, this, "super", super.toString());

http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtCacheEntry.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtCacheEntry.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtCacheEntry.java
index 343e418..96f5c9b 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtCacheEntry.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtCacheEntry.java
@@ -102,11 +102,6 @@ public class GridDhtCacheEntry extends GridDistributedCacheEntry {
     }
 
     /** {@inheritDoc} */
-    @Override protected long nextMvccPartitionCounter() {
-        return locPart.nextMvccUpdateCounter();
-    }
-
-    /** {@inheritDoc} */
     @Override public int memorySize() throws IgniteCheckedException {
         int rdrsOverhead;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLocalPartition.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLocalPartition.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLocalPartition.java
index f56df00..a5a12a4 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLocalPartition.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLocalPartition.java
@@ -969,45 +969,51 @@ public class GridDhtLocalPartition extends GridCacheConcurrentMapImpl implements
     }
 
     /**
-     * @return Current update index.
+     * @return Current update counter.
      */
     public long updateCounter() {
         return store.updateCounter();
     }
 
     /**
-     * @return Current mvcc update counter value.
+     * @param val Update counter value.
      */
-    public long mvccUpdateCounter() {
-        return store.mvccUpdateCounter();
+    public void updateCounter(long val) {
+        store.updateCounter(val);
     }
 
     /**
-     * @return Next mvcc update counter.
+     * @return Initial update counter.
      */
-    public long nextMvccUpdateCounter() {
-        return store.nextMvccUpdateCounter();
+    public long initialUpdateCounter() {
+        return store.initialUpdateCounter();
     }
 
     /**
-     * @return Initial update counter.
+     * @param val Initial update counter value.
      */
-    public long initialUpdateCounter() {
-        return store.initialUpdateCounter();
+    public void initialUpdateCounter(long val) {
+        store.updateInitialCounter(val);
     }
 
     /**
-     * @param val Update index value.
+     * Updates MVCC cache update counter on primary node.
+     *
+     * @param delta Value to be added to update counter.
+     * @return Update counter value before update.
      */
-    public void updateCounter(long val) {
-        store.updateCounter(val);
+    public long getAndIncrementUpdateCounter(long delta) {
+        return store.getAndIncrementUpdateCounter(delta);
     }
 
     /**
-     * @param val Initial update index value.
+     * Updates MVCC cache update counter on backup node.
+     *
+     * @param start Start position
+     * @param delta Delta.
      */
-    public void initialUpdateCounter(long val) {
-        store.updateInitialCounter(val);
+    public void updateCounter(long start, long delta) {
+         store.updateCounter(start, delta);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTransactionalCacheAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTransactionalCacheAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTransactionalCacheAdapter.java
index be1c7e2..f6df80b 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTransactionalCacheAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTransactionalCacheAdapter.java
@@ -2205,7 +2205,7 @@ public abstract class GridDhtTransactionalCacheAdapter<K, V> extends GridDhtCach
             MvccSnapshot snapshot = new MvccSnapshotWithoutTxs(s0.coordinatorVersion(), s0.counter(),
                 req.operationCounter(), s0.cleanupVersion());
 
-            tx.mvccEnlistBatch(ctx, req.op(), req.keys(), req.values(), snapshot, req.updateCounters());
+            tx.mvccEnlistBatch(ctx, req.op(), req.keys(), req.values(), snapshot);
 
             GridDhtTxQueryEnlistResponse res = new GridDhtTxQueryEnlistResponse(req.cacheId(),
                 req.dhtFutureId(),

http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxAbstractEnlistFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxAbstractEnlistFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxAbstractEnlistFuture.java
index a3471c7..2b34a41 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxAbstractEnlistFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxAbstractEnlistFuture.java
@@ -61,7 +61,6 @@ import org.apache.ignite.internal.processors.query.IgniteSQLException;
 import org.apache.ignite.internal.processors.query.UpdateSourceIterator;
 import org.apache.ignite.internal.processors.timeout.GridTimeoutObjectAdapter;
 import org.apache.ignite.internal.transactions.IgniteTxTimeoutCheckedException;
-import org.apache.ignite.internal.util.GridLongList;
 import org.apache.ignite.internal.util.tostring.GridToStringExclude;
 import org.apache.ignite.internal.util.typedef.CI1;
 import org.apache.ignite.internal.util.typedef.F;
@@ -135,6 +134,9 @@ public abstract class GridDhtTxAbstractEnlistFuture extends GridCacheFutureAdapt
     /** Processed entries count. */
     protected long cnt;
 
+    /** New DHT nodes. */
+    protected Set<UUID> newDhtNodes = Collections.newSetFromMap(new ConcurrentHashMap<>());
+
     /** Near node ID. */
     protected final UUID nearNodeId;
 
@@ -186,9 +188,6 @@ public abstract class GridDhtTxAbstractEnlistFuture extends GridCacheFutureAdapt
     /** Moving partitions. */
     private Map<Integer, Boolean> movingParts;
 
-    /** Update counters to be sent to the near node in case it is a backup node also. */
-    protected GridLongList nearUpdCntrs;
-
     /**
      * @param nearNodeId Near node ID.
      * @param nearLockVer Near lock version.
@@ -388,7 +387,6 @@ public abstract class GridDhtTxAbstractEnlistFuture extends GridCacheFutureAdapt
                                         tx,
                                         cctx.localNodeId(),
                                         topVer,
-                                        null,
                                         mvccSnapshot,
                                         isMoving(key.partition()));
 
@@ -403,7 +401,6 @@ public abstract class GridDhtTxAbstractEnlistFuture extends GridCacheFutureAdapt
                                         val,
                                         0,
                                         topVer,
-                                        null,
                                         mvccSnapshot,
                                         op.cacheOperation(),
                                         isMoving(key.partition()),
@@ -575,7 +572,7 @@ public abstract class GridDhtTxAbstractEnlistFuture extends GridCacheFutureAdapt
         cnt++;
 
         if (op != EnlistOperation.LOCK)
-            addToBatch(entry.key(), val, updRes.mvccHistory(), updRes.updateCounter(), entry.context().cacheId());
+            addToBatch(entry.key(), val, updRes.mvccHistory(), entry.context().cacheId());
     }
 
     /**
@@ -585,9 +582,8 @@ public abstract class GridDhtTxAbstractEnlistFuture extends GridCacheFutureAdapt
      * @param key Key.
      * @param val Value.
      * @param hist History rows.
-     * @param updCntr Update counter.
      */
-    private void addToBatch(KeyCacheObject key, CacheObject val, List<MvccLinkAwareSearchRow> hist, long updCntr,
+    private void addToBatch(KeyCacheObject key, CacheObject val, List<MvccLinkAwareSearchRow> hist,
         int cacheId) throws IgniteCheckedException {
         List<ClusterNode> backups = backupNodes(key);
 
@@ -609,15 +605,10 @@ public abstract class GridDhtTxAbstractEnlistFuture extends GridCacheFutureAdapt
                 updateMappings(node);
 
                 if (newRemoteTx(node))
-                    tx.addLockTransactionNode(node);
+                    addNewRemoteTxNode(node);
 
                 hasNearNodeUpdates = true;
 
-                if (nearUpdCntrs == null)
-                    nearUpdCntrs = new GridLongList();
-
-                nearUpdCntrs.add(updCntr);
-
                 continue;
             }
 
@@ -637,7 +628,7 @@ public abstract class GridDhtTxAbstractEnlistFuture extends GridCacheFutureAdapt
                 hist0 = fetchHistoryInfo(key, hist);
             }
 
-            batch.add(key, moving ? hist0 : val, updCntr);
+            batch.add(key, moving ? hist0 : val);
 
             if (batch.size() == BATCH_SIZE) {
                 assert batches != null;
@@ -705,6 +696,17 @@ public abstract class GridDhtTxAbstractEnlistFuture extends GridCacheFutureAdapt
     }
 
     /**
+     * Add new involved DHT node.
+     *
+     * @param node Node.
+     */
+    private void addNewRemoteTxNode(ClusterNode node) {
+        tx.addLockTransactionNode(node);
+
+        newDhtNodes.add(node.id());
+    }
+
+    /**
      * Checks if there free space in batches or free slot in in-flight batches is available for the given key.
      *
      * @param key Key.
@@ -752,7 +754,7 @@ public abstract class GridDhtTxAbstractEnlistFuture extends GridCacheFutureAdapt
         GridDhtTxQueryEnlistRequest req;
 
         if (newRemoteTx(node)) {
-            tx.addLockTransactionNode(node);
+            addNewRemoteTxNode(node);
 
             // If this is a first request to this node, send full info.
             req = new GridDhtTxQueryFirstEnlistRequest(cctx.cacheId(),
@@ -768,8 +770,8 @@ public abstract class GridDhtTxAbstractEnlistFuture extends GridCacheFutureAdapt
                 it.operation(),
                 FIRST_BATCH_ID,
                 batch.keys(),
-                batch.values(),
-                batch.updateCounters());
+                batch.values()
+            );
         }
         else {
             // Send only keys, values, LockVersion and batchId if this is not a first request to this backup.
@@ -780,8 +782,8 @@ public abstract class GridDhtTxAbstractEnlistFuture extends GridCacheFutureAdapt
                 ++batchIdCntr,
                 mvccSnapshot.operationCounter(),
                 batch.keys(),
-                batch.values(),
-                batch.updateCounters());
+                batch.values()
+            );
         }
 
         ConcurrentMap<Integer, Batch> pending0 = null;
@@ -1036,9 +1038,6 @@ public abstract class GridDhtTxAbstractEnlistFuture extends GridCacheFutureAdapt
          */
         private List<Message> vals;
 
-        /** Update counters. */
-        private GridLongList updCntrs;
-
         /**
          * @param node Cluster node.
          */
@@ -1059,9 +1058,8 @@ public abstract class GridDhtTxAbstractEnlistFuture extends GridCacheFutureAdapt
          * @param key Key.
          * @param val Value or preload entries collection.
          */
-        public void add(KeyCacheObject key, Message val, long updCntr) {
+        public void add(KeyCacheObject key, Message val) {
             assert val == null || val instanceof CacheObject || val instanceof CacheEntryInfoCollection;
-            assert updCntr > 0;
 
             if (keys == null)
                 keys = new ArrayList<>();
@@ -1075,11 +1073,6 @@ public abstract class GridDhtTxAbstractEnlistFuture extends GridCacheFutureAdapt
                 vals.add(val);
             }
 
-            if (updCntrs == null)
-                updCntrs = new GridLongList();
-
-            updCntrs.add(updCntr);
-
             assert (vals == null) || keys.size() == vals.size();
         }
 
@@ -1103,13 +1096,6 @@ public abstract class GridDhtTxAbstractEnlistFuture extends GridCacheFutureAdapt
         public List<Message> values() {
             return vals;
         }
-
-        /**
-         * @return Update counters.
-         */
-        public GridLongList updateCounters() {
-            return updCntrs;
-        }
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxFinishFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxFinishFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxFinishFuture.java
index 4c72e6f..9283939 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxFinishFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxFinishFuture.java
@@ -371,7 +371,8 @@ public final class GridDhtTxFinishFuture<K, V> extends GridCacheCompoundIdentity
                 tx.activeCachesDeploymentEnabled(),
                 false,
                 false,
-                tx.mvccSnapshot());
+                tx.mvccSnapshot(),
+                tx.filterUpdateCountersForBackupNode(n));
 
             try {
                 cctx.io().send(n, req, tx.ioPolicy());
@@ -457,11 +458,6 @@ public final class GridDhtTxFinishFuture<K, V> extends GridCacheCompoundIdentity
             for (IgniteTxEntry e : dhtMapping.entries())
                 updCntrs.add(e.updateCounter());
 
-            Map<Integer, PartitionUpdateCounters> updCntrsForNode = null;
-
-            if (dhtMapping.queryUpdate() && commit)
-                updCntrsForNode = tx.filterUpdateCountersForBackupNode(n);
-
             GridDhtTxFinishRequest req = new GridDhtTxFinishRequest(
                 tx.nearNodeId(),
                 futId,
@@ -489,7 +485,7 @@ public final class GridDhtTxFinishFuture<K, V> extends GridCacheCompoundIdentity
                 false,
                 false,
                 mvccSnapshot,
-                updCntrsForNode);
+                commit ? null : tx.filterUpdateCountersForBackupNode(n));
 
             req.writeVersion(tx.writeVersion() != null ? tx.writeVersion() : tx.xidVersion());
 
@@ -559,7 +555,8 @@ public final class GridDhtTxFinishFuture<K, V> extends GridCacheCompoundIdentity
                     tx.activeCachesDeploymentEnabled(),
                     false,
                     false,
-                    mvccSnapshot);
+                    mvccSnapshot,
+                    null);
 
                 req.writeVersion(tx.writeVersion());
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxFinishRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxFinishRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxFinishRequest.java
index 8e9ece6..61896b5 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxFinishRequest.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxFinishRequest.java
@@ -20,11 +20,9 @@ package org.apache.ignite.internal.processors.cache.distributed.dht;
 import java.io.Externalizable;
 import java.nio.ByteBuffer;
 import java.util.Collection;
-import java.util.Map;
 import java.util.UUID;
 import org.apache.ignite.cache.CacheWriteSynchronizationMode;
 import org.apache.ignite.internal.GridDirectCollection;
-import org.apache.ignite.internal.GridDirectMap;
 import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
 import org.apache.ignite.internal.processors.cache.distributed.GridDistributedTxFinishRequest;
 import org.apache.ignite.internal.processors.cache.mvcc.MvccSnapshot;
@@ -74,8 +72,8 @@ public class GridDhtTxFinishRequest extends GridDistributedTxFinishRequest {
     private MvccSnapshot mvccSnapshot;
 
     /** */
-    @GridDirectMap(keyType = Integer.class, valueType = PartitionUpdateCounters.class)
-    private Map<Integer, PartitionUpdateCounters> updCntrs;
+    @GridDirectCollection(PartitionUpdateCountersMessage.class)
+    private Collection<PartitionUpdateCountersMessage> updCntrs;
 
     /**
      * Empty constructor required for {@link Externalizable}.
@@ -107,6 +105,10 @@ public class GridDhtTxFinishRequest extends GridDistributedTxFinishRequest {
      * @param subjId Subject ID.
      * @param taskNameHash Task name hash.
      * @param addDepInfo Deployment info flag.
+     * @param retVal Need return value
+     * @param waitRemoteTxs Wait remote transactions flag
+     * @param mvccSnapshot Mvcc snapshot.
+     * @param updCntrs Update counters for mvcc Tx.
      */
     public GridDhtTxFinishRequest(
         UUID nearNodeId,
@@ -133,7 +135,8 @@ public class GridDhtTxFinishRequest extends GridDistributedTxFinishRequest {
         boolean addDepInfo,
         boolean retVal,
         boolean waitRemoteTxs,
-        MvccSnapshot mvccSnapshot
+        MvccSnapshot mvccSnapshot,
+        Collection<PartitionUpdateCountersMessage> updCntrs
     ) {
         super(
             xidVer,
@@ -163,6 +166,7 @@ public class GridDhtTxFinishRequest extends GridDistributedTxFinishRequest {
         this.isolation = isolation;
         this.miniId = miniId;
         this.mvccSnapshot = mvccSnapshot;
+        this.updCntrs = updCntrs;
 
         needReturnValue(retVal);
         waitRemoteTransactions(waitRemoteTxs);
@@ -193,6 +197,10 @@ public class GridDhtTxFinishRequest extends GridDistributedTxFinishRequest {
      * @param taskNameHash Task name hash.
      * @param updateIdxs Partition update idxs.
      * @param addDepInfo Deployment info flag.
+     * @param retVal Need return value
+     * @param waitRemoteTxs Wait remote transactions flag
+     * @param mvccSnapshot Mvcc snapshot.
+     * @param updCntrs Update counters for mvcc Tx.
      */
     public GridDhtTxFinishRequest(
         UUID nearNodeId,
@@ -221,7 +229,7 @@ public class GridDhtTxFinishRequest extends GridDistributedTxFinishRequest {
         boolean retVal,
         boolean waitRemoteTxs,
         MvccSnapshot mvccSnapshot,
-        Map<Integer, PartitionUpdateCounters> updCntrs
+        Collection<PartitionUpdateCountersMessage> updCntrs
     ) {
         this(nearNodeId,
             futId,
@@ -247,7 +255,8 @@ public class GridDhtTxFinishRequest extends GridDistributedTxFinishRequest {
             addDepInfo,
             retVal,
             waitRemoteTxs,
-            mvccSnapshot);
+            mvccSnapshot,
+            updCntrs);
 
         if (updateIdxs != null && !updateIdxs.isEmpty()) {
             partUpdateCnt = new GridLongList(updateIdxs.size());
@@ -255,8 +264,6 @@ public class GridDhtTxFinishRequest extends GridDistributedTxFinishRequest {
             for (Long idx : updateIdxs)
                 partUpdateCnt.add(idx);
         }
-
-        this.updCntrs = updCntrs;
     }
 
     /**
@@ -367,7 +374,7 @@ public class GridDhtTxFinishRequest extends GridDistributedTxFinishRequest {
     /**
      * @return Partition counters update deferred until transaction commit.
      */
-    public Map<Integer, PartitionUpdateCounters> updateCounters() {
+    public Collection<PartitionUpdateCountersMessage> updateCounters() {
         return updCntrs;
     }
 
@@ -429,7 +436,7 @@ public class GridDhtTxFinishRequest extends GridDistributedTxFinishRequest {
                 writer.incrementState();
 
             case 28:
-                if (!writer.writeMap("updCntrs", updCntrs, MessageCollectionItemType.INT, MessageCollectionItemType.MSG))
+                if (!writer.writeCollection("updCntrs", updCntrs, MessageCollectionItemType.MSG))
                     return false;
 
                 writer.incrementState();
@@ -511,7 +518,7 @@ public class GridDhtTxFinishRequest extends GridDistributedTxFinishRequest {
                 reader.incrementState();
 
             case 28:
-                updCntrs = reader.readMap("updCntrs", MessageCollectionItemType.INT, MessageCollectionItemType.MSG, false);
+                updCntrs = reader.readCollection("updCntrs", MessageCollectionItemType.MSG);
 
                 if (!reader.isLastRead())
                     return false;

http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxLocalAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxLocalAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxLocalAdapter.java
index 613f160..a0c9d15 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxLocalAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxLocalAdapter.java
@@ -18,9 +18,9 @@
 package org.apache.ignite.internal.processors.cache.distributed.dht;
 
 import java.io.Externalizable;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -944,43 +944,32 @@ public abstract class GridDhtTxLocalAdapter extends IgniteTxLocalAdapter {
      * @param node Backup node.
      * @return Partition counters map for the given backup node.
      */
-    public Map<Integer, PartitionUpdateCounters> filterUpdateCountersForBackupNode(ClusterNode node) {
+    public List<PartitionUpdateCountersMessage> filterUpdateCountersForBackupNode(ClusterNode node) {
         TxCounters txCntrs = txCounters(false);
 
-        if (txCntrs == null)
+        if (txCntrs == null || F.isEmpty(txCntrs.updateCounters()))
             return null;
 
-        Map<Integer, PartitionUpdateCounters> updCntrs = txCntrs.updateCounters();
+        Collection<PartitionUpdateCountersMessage> updCntrs = txCntrs.updateCounters();
 
-        Map<Integer, PartitionUpdateCounters> res = new HashMap<>();
+        List<PartitionUpdateCountersMessage> res = new ArrayList<>(updCntrs.size());
 
         AffinityTopologyVersion top = topologyVersionSnapshot();
 
-        for (Map.Entry<Integer, PartitionUpdateCounters> entry : updCntrs.entrySet()) {
-            Integer cacheId = entry.getKey();
+        for (PartitionUpdateCountersMessage partCntrs : updCntrs) {
+            GridCacheAffinityManager affinity = cctx.cacheContext(partCntrs.cacheId()).affinity();
 
-            Map<Integer, Long> partsCntrs = entry.getValue().updateCounters();
+            PartitionUpdateCountersMessage resCntrs = new PartitionUpdateCountersMessage(partCntrs.cacheId(), partCntrs.size());
 
-            assert !F.isEmpty(partsCntrs);
+            for (int i = 0; i < partCntrs.size(); i++) {
+                int part = partCntrs.partition(i);
 
-            GridCacheAffinityManager affinity = cctx.cacheContext(cacheId).affinity();
-
-            Map<Integer, Long> resCntrs = new HashMap<>(partsCntrs.size());
-
-            for (Map.Entry<Integer, Long> e : partsCntrs.entrySet()) {
-                Integer p = e.getKey();
-
-                Long cntr = e.getValue();
-
-                if (affinity.backupByPartition(node, p, top)) {
-                    assert cntr != null && cntr > 0 : cntr;
-
-                    resCntrs.put(p, cntr);
-                }
+                if (affinity.backupByPartition(node, part, top))
+                    resCntrs.add(part, partCntrs.initialCounter(i), partCntrs.updatesCount(i));
             }
 
-            if (!resCntrs.isEmpty())
-                res.put(cacheId, new PartitionUpdateCounters(resCntrs));
+            if (resCntrs.size() > 0)
+                res.add(resCntrs);
         }
 
         return res;

http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareFuture.java
index 1974038..0edf63f 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareFuture.java
@@ -61,7 +61,6 @@ import org.apache.ignite.internal.processors.cache.distributed.GridDistributedTx
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearCacheAdapter;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxPrepareRequest;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxPrepareResponse;
-import org.apache.ignite.internal.processors.cache.mvcc.MvccCoordinator;
 import org.apache.ignite.internal.processors.cache.mvcc.MvccSnapshot;
 import org.apache.ignite.internal.processors.cache.mvcc.MvccUpdateVersionAware;
 import org.apache.ignite.internal.processors.cache.mvcc.MvccVersionAware;
@@ -69,6 +68,7 @@ import org.apache.ignite.internal.processors.cache.mvcc.txlog.TxState;
 import org.apache.ignite.internal.processors.cache.transactions.IgniteInternalTx;
 import org.apache.ignite.internal.processors.cache.transactions.IgniteTxEntry;
 import org.apache.ignite.internal.processors.cache.transactions.IgniteTxKey;
+import org.apache.ignite.internal.processors.cache.transactions.TxCounters;
 import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
 import org.apache.ignite.internal.processors.dr.GridDrType;
 import org.apache.ignite.internal.processors.timeout.GridTimeoutObjectAdapter;
@@ -1397,7 +1397,8 @@ public final class GridDhtTxPrepareFuture extends GridCacheCompoundFuture<Ignite
                 tx.activeCachesDeploymentEnabled(),
                 tx.storeWriteThrough(),
                 retVal,
-                mvccSnapshot);
+                mvccSnapshot,
+                tx.filterUpdateCountersForBackupNode(n));
 
             req.queryUpdate(dhtMapping.queryUpdate());
 
@@ -1503,7 +1504,8 @@ public final class GridDhtTxPrepareFuture extends GridCacheCompoundFuture<Ignite
                     tx.activeCachesDeploymentEnabled(),
                     tx.storeWriteThrough(),
                     retVal,
-                    mvccSnapshot);
+                    mvccSnapshot,
+                    null);
 
                 for (IgniteTxEntry entry : nearMapping.entries()) {
                     if (CU.writes().apply(entry)) {

http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareRequest.java
index 68c1f39..30e8ceb 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareRequest.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareRequest.java
@@ -88,6 +88,10 @@ public class GridDhtTxPrepareRequest extends GridDistributedTxPrepareRequest {
     @GridDirectCollection(GridCacheVersion.class)
     private Collection<GridCacheVersion> ownedVals;
 
+    /** */
+    @GridDirectCollection(PartitionUpdateCountersMessage.class)
+    private Collection<PartitionUpdateCountersMessage> counters;
+
     /** Near transaction ID. */
     private GridCacheVersion nearXidVer;
 
@@ -130,7 +134,9 @@ public class GridDhtTxPrepareRequest extends GridDistributedTxPrepareRequest {
      * @param last {@code True} if this is last prepare request for node.
      * @param addDepInfo Deployment info flag.
      * @param storeWriteThrough Cache store write through flag.
-     * @param retVal Need return value flag.
+     * @param retVal Need return value flag
+     * @param mvccSnapshot Mvcc snapshot.
+     * @param counters Update counters for mvcc Tx.
      */
     public GridDhtTxPrepareRequest(
         IgniteUuid futId,
@@ -149,7 +155,8 @@ public class GridDhtTxPrepareRequest extends GridDistributedTxPrepareRequest {
         boolean addDepInfo,
         boolean storeWriteThrough,
         boolean retVal,
-        MvccSnapshot mvccInfo) {
+        MvccSnapshot mvccSnapshot,
+        Collection<PartitionUpdateCountersMessage> counters) {
         super(tx,
             timeout,
             null,
@@ -170,7 +177,8 @@ public class GridDhtTxPrepareRequest extends GridDistributedTxPrepareRequest {
         this.nearXidVer = nearXidVer;
         this.subjId = subjId;
         this.taskNameHash = taskNameHash;
-        this.mvccSnapshot = mvccInfo;
+        this.mvccSnapshot = mvccSnapshot;
+        this.counters = counters;
 
         storeWriteThrough(storeWriteThrough);
         needReturnValue(retVal);
@@ -190,6 +198,13 @@ public class GridDhtTxPrepareRequest extends GridDistributedTxPrepareRequest {
     }
 
     /**
+     * @return Update counters list.
+     */
+    public Collection<PartitionUpdateCountersMessage> updateCounters() {
+        return counters;
+    }
+
+    /**
      * @return Near cache writes for which cache was not found (possible if client near cache was closed).
      */
     @Nullable public List<IgniteTxKey> nearWritesCacheMissed() {
@@ -492,6 +507,12 @@ public class GridDhtTxPrepareRequest extends GridDistributedTxPrepareRequest {
 
                 writer.incrementState();
 
+            case 34:
+                if (!writer.writeCollection("counters", counters, MessageCollectionItemType.MSG))
+                    return false;
+
+                writer.incrementState();
+
         }
 
         return true;
@@ -620,6 +641,14 @@ public class GridDhtTxPrepareRequest extends GridDistributedTxPrepareRequest {
 
                 reader.incrementState();
 
+            case 34:
+                counters = reader.readCollection("counters", MessageCollectionItemType.MSG);
+
+                if (!reader.isLastRead())
+                    return false;
+
+                reader.incrementState();
+
         }
 
         return reader.afterMessageRead(GridDhtTxPrepareRequest.class);
@@ -632,7 +661,7 @@ public class GridDhtTxPrepareRequest extends GridDistributedTxPrepareRequest {
 
     /** {@inheritDoc} */
     @Override public byte fieldsCount() {
-        return 34;
+        return 35;
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxQueryEnlistRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxQueryEnlistRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxQueryEnlistRequest.java
index 650e1dc..a1bc26b 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxQueryEnlistRequest.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxQueryEnlistRequest.java
@@ -30,7 +30,6 @@ import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
 import org.apache.ignite.internal.processors.cache.KeyCacheObject;
 import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
 import org.apache.ignite.internal.processors.query.EnlistOperation;
-import org.apache.ignite.internal.util.GridLongList;
 import org.apache.ignite.internal.util.typedef.internal.S;
 import org.apache.ignite.lang.IgniteUuid;
 import org.apache.ignite.plugin.extensions.communication.Message;
@@ -68,9 +67,6 @@ public class GridDhtTxQueryEnlistRequest extends GridCacheIdMessage {
     @GridDirectCollection(Message.class)
     private List<Message> vals;
 
-    /** */
-    private GridLongList updCntrs;
-
     /**
      *
      */
@@ -86,7 +82,6 @@ public class GridDhtTxQueryEnlistRequest extends GridCacheIdMessage {
      * @param mvccOpCnt Mvcc operation counter.
      * @param keys Keys.
      * @param vals Values.
-     * @param updCntrs Update counters.
      */
     GridDhtTxQueryEnlistRequest(int cacheId,
         IgniteUuid dhtFutId,
@@ -95,8 +90,7 @@ public class GridDhtTxQueryEnlistRequest extends GridCacheIdMessage {
         int batchId,
         int mvccOpCnt,
         List<KeyCacheObject> keys,
-        List<Message> vals,
-        GridLongList updCntrs) {
+        List<Message> vals) {
         this.cacheId = cacheId;
         this.dhtFutId = dhtFutId;
         this.lockVer = lockVer;
@@ -105,7 +99,6 @@ public class GridDhtTxQueryEnlistRequest extends GridCacheIdMessage {
         this.mvccOpCnt = mvccOpCnt;
         this.keys = keys;
         this.vals = vals;
-        this.updCntrs = updCntrs;
     }
 
     /**
@@ -160,13 +153,6 @@ public class GridDhtTxQueryEnlistRequest extends GridCacheIdMessage {
     }
 
     /**
-     * @return Update counters.
-     */
-    public GridLongList updateCounters() {
-        return updCntrs;
-    }
-
-    /**
      * @return Batch id.
      */
     public int batchId() {
@@ -292,12 +278,6 @@ public class GridDhtTxQueryEnlistRequest extends GridCacheIdMessage {
                 writer.incrementState();
 
             case 9:
-                if (!writer.writeMessage("updCntrs", updCntrs))
-                    return false;
-
-                writer.incrementState();
-
-            case 10:
                 if (!writer.writeCollection("vals", vals, MessageCollectionItemType.MSG))
                     return false;
 
@@ -372,14 +352,6 @@ public class GridDhtTxQueryEnlistRequest extends GridCacheIdMessage {
                 reader.incrementState();
 
             case 9:
-                updCntrs = reader.readMessage("updCntrs");
-
-                if (!reader.isLastRead())
-                    return false;
-
-                reader.incrementState();
-
-            case 10:
                 vals = reader.readCollection("vals", MessageCollectionItemType.MSG);
 
                 if (!reader.isLastRead())
@@ -394,7 +366,7 @@ public class GridDhtTxQueryEnlistRequest extends GridCacheIdMessage {
 
     /** {@inheritDoc} */
     @Override public byte fieldsCount() {
-        return 11;
+        return 10;
     }
 
     /** {@inheritDoc} */


[7/9] ignite git commit: Updated Ignite description

Posted by vo...@apache.org.
Updated Ignite description


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

Branch: refs/heads/ignite-2.7
Commit: 9089513d8f4543bc38e096ea19d82b1f955b30bb
Parents: e73137c
Author: Denis Magda <dm...@gridgain.com>
Authored: Tue Sep 25 23:10:39 2018 -0700
Committer: devozerov <vo...@gridgain.com>
Committed: Wed Sep 26 12:37:41 2018 +0300

----------------------------------------------------------------------
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/9089513d/README.md
----------------------------------------------------------------------
diff --git a/README.md b/README.md
index 80c8a92..89af2ca 100644
--- a/README.md
+++ b/README.md
@@ -22,7 +22,7 @@ You can find the full Apache Ignite documentation here: [Full documentation][doc
 
 <p align="center">
     <a href="https://ignite.apache.org/whatisignite.html">
-        <img src="https://ignite.apache.org/images/ignite_architecture.png" width="600px"/>
+        <img src="https://ignite.apache.org/images/ignite_architecture.png" width="400px"/>
     </a>
 </p>
 


[8/9] ignite git commit: IGNITE-4150: SQL: updated H2 version to 1.4.197. This closes #3956.

Posted by vo...@apache.org.
IGNITE-4150: SQL: updated H2 version to 1.4.197. This closes #3956.


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

Branch: refs/heads/ignite-2.7
Commit: 20f524680f6b316fcbf203355744ed2c528d4a47
Parents: 9089513
Author: tledkov-gridgain <tl...@gridgain.com>
Authored: Wed Sep 26 11:08:02 2018 +0300
Committer: devozerov <vo...@gridgain.com>
Committed: Wed Sep 26 12:37:49 2018 +0300

----------------------------------------------------------------------
 .../examples/datagrid/SpatialQueryExample.java  |   4 +-
 .../cache/query/annotations/QuerySqlField.java  |   2 +-
 .../processors/cache/query/CacheQuery.java      |  18 +--
 .../internal/processors/query/QueryUtils.java   |   2 +-
 modules/geospatial/pom.xml                      |   6 +-
 .../query/h2/opt/GridH2SpatialIndex.java        |  10 +-
 .../query/h2/H2IndexingAbstractGeoSelfTest.java |   6 +-
 .../processors/query/h2/H2DatabaseType.java     |   6 +-
 .../processors/query/h2/IgniteH2Indexing.java   |   2 +-
 .../processors/query/h2/dml/DmlUtils.java       |   6 +-
 .../query/h2/opt/GridH2CollocationModel.java    |   3 +
 .../query/h2/opt/GridH2ProxySpatialIndex.java   |   5 +-
 .../query/h2/opt/GridH2RowDescriptor.java       |   6 +-
 .../query/h2/opt/GridH2ValueCacheObject.java    |   3 +-
 .../query/h2/sql/GridSqlAggregateFunction.java  |  48 ++++++-
 .../query/h2/sql/GridSqlQueryParser.java        |  80 +++++++----
 .../query/h2/sql/GridSqlQuerySplitter.java      |   2 +-
 .../processors/query/h2/sql/GridSqlUnion.java   |  16 +--
 .../ignite/mesos/resource/IgniteProvider.java   |   6 +-
 .../src/sql_esc_convert_function_test.cpp       |   4 +-
 .../Cache/Query/Linq/CacheLinqTest.Misc.cs      |   2 +-
 .../frontend/app/data/pom-dependencies.json     |   3 +-
 .../benchmark-native-sql-select-join.properties |  89 ++++++++++++
 .../jdbc/NativeSqlJoinQueryRangeBenchmark.java  | 135 +++++++++++++++++++
 parent/pom.xml                                  |   2 +-
 25 files changed, 377 insertions(+), 89 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/20f52468/examples/src/main/java-lgpl/org/apache/ignite/examples/datagrid/SpatialQueryExample.java
----------------------------------------------------------------------
diff --git a/examples/src/main/java-lgpl/org/apache/ignite/examples/datagrid/SpatialQueryExample.java b/examples/src/main/java-lgpl/org/apache/ignite/examples/datagrid/SpatialQueryExample.java
index 7e13e34..f27dbac 100644
--- a/examples/src/main/java-lgpl/org/apache/ignite/examples/datagrid/SpatialQueryExample.java
+++ b/examples/src/main/java-lgpl/org/apache/ignite/examples/datagrid/SpatialQueryExample.java
@@ -17,8 +17,6 @@
 
 package org.apache.ignite.examples.datagrid;
 
-import com.vividsolutions.jts.geom.*;
-import com.vividsolutions.jts.io.*;
 import org.apache.ignite.*;
 import org.apache.ignite.cache.query.SqlQuery;
 import org.apache.ignite.cache.query.annotations.*;
@@ -27,6 +25,8 @@ import org.apache.ignite.configuration.*;
 import javax.cache.*;
 import java.util.*;
 import org.apache.ignite.examples.ExampleNodeStartup;
+import org.locationtech.jts.geom.Geometry;
+import org.locationtech.jts.io.WKTReader;
 
 /**
  * This examples shows the usage of geospatial queries and indexes in Apache Ignite.

http://git-wip-us.apache.org/repos/asf/ignite/blob/20f52468/modules/core/src/main/java/org/apache/ignite/cache/query/annotations/QuerySqlField.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/cache/query/annotations/QuerySqlField.java b/modules/core/src/main/java/org/apache/ignite/cache/query/annotations/QuerySqlField.java
index 35b7575..b05f6b6 100644
--- a/modules/core/src/main/java/org/apache/ignite/cache/query/annotations/QuerySqlField.java
+++ b/modules/core/src/main/java/org/apache/ignite/cache/query/annotations/QuerySqlField.java
@@ -41,7 +41,7 @@ public @interface QuerySqlField {
      * during updates, but makes select operations faster.
      * <p>
      * When indexing SPI and indexed field is
-     * of type {@code com.vividsolutions.jts.geom.Geometry} (or any subclass of this class) then Ignite will
+     * of type {@code org.locationtech.jts.geom.Geometry} (or any subclass of this class) then Ignite will
      * consider this index as spatial providing performance boost for spatial queries.
      *
      * @return {@code True} if index must be created for this field in database.

http://git-wip-us.apache.org/repos/asf/ignite/blob/20f52468/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/CacheQuery.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/CacheQuery.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/CacheQuery.java
index d8eb7ca..c8f392f 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/CacheQuery.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/CacheQuery.java
@@ -156,13 +156,13 @@ import org.jetbrains.annotations.Nullable;
  * private class MapPoint implements Serializable {
  *     // Geospatial index.
  *     &#64;QuerySqlField(index = true)
- *     private com.vividsolutions.jts.geom.Point location;
+ *     private org.locationtech.jts.geom.Point location;
  *
  *     // Not indexed field.
  *     &#64;QuerySqlField
  *     private String name;
  *
- *     public MapPoint(com.vividsolutions.jts.geom.Point location, String name) {
+ *     public MapPoint(org.locationtech.jts.geom.Point location, String name) {
  *         this.location = location;
  *         this.name = name;
  *     }
@@ -170,14 +170,14 @@ import org.jetbrains.annotations.Nullable;
  * </pre>
  * Example of spatial query on the geo-indexed field from above:
  * <pre name="code" class="java">
- * com.vividsolutions.jts.geom.GeometryFactory factory = new com.vividsolutions.jts.geom.GeometryFactory();
+ * org.locationtech.jts.geom.GeometryFactory factory = new org.locationtech.jts.geom.GeometryFactory();
  *
- * com.vividsolutions.jts.geom.Polygon square = factory.createPolygon(new Coordinate[] {
- *     new com.vividsolutions.jts.geom.Coordinate(0, 0),
- *     new com.vividsolutions.jts.geom.Coordinate(0, 100),
- *     new com.vividsolutions.jts.geom.Coordinate(100, 100),
- *     new com.vividsolutions.jts.geom.Coordinate(100, 0),
- *     new com.vividsolutions.jts.geom.Coordinate(0, 0)
+ * org.locationtech.jts.geom.Polygon square = factory.createPolygon(new Coordinate[] {
+ *     new org.locationtech.jts.geom.Coordinate(0, 0),
+ *     new org.locationtech.jts.geom.Coordinate(0, 100),
+ *     new org.locationtech.jts.geom.Coordinate(100, 100),
+ *     new org.locationtech.jts.geom.Coordinate(100, 0),
+ *     new org.locationtech.jts.geom.Coordinate(0, 0)
  * });
  *
  * Map.Entry<String, UserData> records = cache.queries().createSqlQuery(MapPoint.class, "select * from MapPoint where location && ?")

http://git-wip-us.apache.org/repos/asf/ignite/blob/20f52468/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryUtils.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryUtils.java
index 42de312..d977a49 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryUtils.java
@@ -97,7 +97,7 @@ public class QueryUtils {
     private static final int DISCO_HIST_SIZE = getInteger(IGNITE_INDEXING_DISCOVERY_HISTORY_SIZE, 1000);
 
     /** */
-    private static final Class<?> GEOMETRY_CLASS = U.classForName("com.vividsolutions.jts.geom.Geometry", null);
+    private static final Class<?> GEOMETRY_CLASS = U.classForName("org.locationtech.jts.geom.Geometry", null);
 
     /** */
     private static final Set<Class<?>> SQL_TYPES = createSqlTypes();

http://git-wip-us.apache.org/repos/asf/ignite/blob/20f52468/modules/geospatial/pom.xml
----------------------------------------------------------------------
diff --git a/modules/geospatial/pom.xml b/modules/geospatial/pom.xml
index 7133fad..a8fb899 100644
--- a/modules/geospatial/pom.xml
+++ b/modules/geospatial/pom.xml
@@ -42,9 +42,9 @@
         </dependency>
 
         <dependency>
-            <groupId>com.vividsolutions</groupId>
-            <artifactId>jts</artifactId>
-            <version>1.13</version>
+            <groupId>org.locationtech.jts</groupId>
+            <artifactId>jts-core</artifactId>
+            <version>1.15.0</version>
         </dependency>
 
         <dependency>

http://git-wip-us.apache.org/repos/asf/ignite/blob/20f52468/modules/geospatial/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2SpatialIndex.java
----------------------------------------------------------------------
diff --git a/modules/geospatial/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2SpatialIndex.java b/modules/geospatial/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2SpatialIndex.java
index 831e674..4d1577b 100644
--- a/modules/geospatial/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2SpatialIndex.java
+++ b/modules/geospatial/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2SpatialIndex.java
@@ -26,8 +26,6 @@ import java.util.Map;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReadWriteLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
-import com.vividsolutions.jts.geom.Envelope;
-import com.vividsolutions.jts.geom.Geometry;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.internal.processors.query.h2.H2Cursor;
 import org.apache.ignite.internal.util.GridCursorIteratorWrapper;
@@ -52,6 +50,8 @@ import org.h2.table.IndexColumn;
 import org.h2.table.TableFilter;
 import org.h2.value.Value;
 import org.h2.value.ValueGeometry;
+import org.locationtech.jts.geom.Envelope;
+import org.locationtech.jts.geom.Geometry;
 
 import static org.apache.ignite.internal.processors.query.h2.opt.GridH2KeyValueRowOnheap.KEY_COL;
 
@@ -286,8 +286,7 @@ public class GridH2SpatialIndex extends GridH2IndexBase implements SpatialIndex
     /** {@inheritDoc} */
     @Override public double getCost(Session ses, int[] masks, TableFilter[] filters, int filter,
         SortOrder sortOrder, HashSet<Column> cols) {
-        return SpatialTreeIndex.getCostRangeIndex(masks,
-            table.getRowCountApproximation(), columns) / 10;
+        return SpatialTreeIndex.getCostRangeIndex(masks, columns) / 10;
     }
 
     /** {@inheritDoc} */
@@ -343,9 +342,8 @@ public class GridH2SpatialIndex extends GridH2IndexBase implements SpatialIndex
         IndexingQueryFilter qryFilter = null;
         GridH2QueryContext qctx = GridH2QueryContext.get();
 
-        if (qctx != null) {
+        if (qctx != null)
             qryFilter = qctx.filter();
-        }
 
         IndexingQueryCacheFilter qryCacheFilter = qryFilter != null ? qryFilter.forCache(getTable().cacheName()) : null;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/20f52468/modules/geospatial/src/test/java/org/apache/ignite/internal/processors/query/h2/H2IndexingAbstractGeoSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/geospatial/src/test/java/org/apache/ignite/internal/processors/query/h2/H2IndexingAbstractGeoSelfTest.java b/modules/geospatial/src/test/java/org/apache/ignite/internal/processors/query/h2/H2IndexingAbstractGeoSelfTest.java
index e9f96e3..9c5038e 100644
--- a/modules/geospatial/src/test/java/org/apache/ignite/internal/processors/query/h2/H2IndexingAbstractGeoSelfTest.java
+++ b/modules/geospatial/src/test/java/org/apache/ignite/internal/processors/query/h2/H2IndexingAbstractGeoSelfTest.java
@@ -17,9 +17,6 @@
 
 package org.apache.ignite.internal.processors.query.h2;
 
-import com.vividsolutions.jts.geom.Geometry;
-import com.vividsolutions.jts.io.ParseException;
-import com.vividsolutions.jts.io.WKTReader;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.cache.CacheAtomicityMode;
 import org.apache.ignite.cache.CacheMode;
@@ -39,6 +36,9 @@ import org.apache.ignite.internal.util.typedef.internal.SB;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.testframework.GridTestUtils;
 import org.jetbrains.annotations.NotNull;
+import org.locationtech.jts.geom.Geometry;
+import org.locationtech.jts.io.ParseException;
+import org.locationtech.jts.io.WKTReader;
 
 import javax.cache.Cache;
 import java.io.Serializable;

http://git-wip-us.apache.org/repos/asf/ignite/blob/20f52468/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/H2DatabaseType.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/H2DatabaseType.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/H2DatabaseType.java
index 3b75239..3d7faca 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/H2DatabaseType.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/H2DatabaseType.java
@@ -144,11 +144,11 @@ public enum H2DatabaseType {
             return GEOMETRY;
 
         if (LocalDateTimeUtils.isJava8DateApiPresent()) {
-            if (LocalDateTimeUtils.isLocalDate(cls))
+            if (LocalDateTimeUtils.LOCAL_DATE == cls)
                 return DATE;
-            else if (LocalDateTimeUtils.isLocalTime(cls))
+            else if (LocalDateTimeUtils.LOCAL_TIME == cls)
                 return TIME;
-            else if (LocalDateTimeUtils.isLocalDateTime(cls))
+            else if (LocalDateTimeUtils.LOCAL_DATE_TIME == cls)
                 return TIMESTAMP;
         }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/20f52468/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
index 96d864d..4b855a7 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
@@ -250,7 +250,7 @@ public class IgniteH2Indexing implements GridQueryIndexing {
     /** Default DB options. */
     private static final String DB_OPTIONS = ";LOCK_MODE=3;MULTI_THREADED=1;DB_CLOSE_ON_EXIT=FALSE" +
         ";DEFAULT_LOCK_TIMEOUT=10000;FUNCTIONS_IN_SCHEMA=true;OPTIMIZE_REUSE_RESULTS=0;QUERY_CACHE_SIZE=0" +
-        ";RECOMPILE_ALWAYS=1;MAX_OPERATION_MEMORY=0;NESTED_JOINS=0;BATCH_JOINS=1" +
+        ";MAX_OPERATION_MEMORY=0;BATCH_JOINS=1" +
         ";ROW_FACTORY=\"" + GridH2PlainRowFactory.class.getName() + "\"" +
         ";DEFAULT_TABLE_ENGINE=" + GridH2DefaultTableEngine.class.getName();
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/20f52468/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/dml/DmlUtils.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/dml/DmlUtils.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/dml/DmlUtils.java
index 03b03d8..58fea4a 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/dml/DmlUtils.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/dml/DmlUtils.java
@@ -71,14 +71,14 @@ public class DmlUtils {
                     U.resolveClassLoader(desc.context().gridConfig()));
 
             if (LocalDateTimeUtils.isJava8DateApiPresent()) {
-                if (val instanceof Timestamp && LocalDateTimeUtils.isLocalDateTime(expCls))
+                if (val instanceof Timestamp && LocalDateTimeUtils.LOCAL_DATE_TIME ==expCls)
                     return LocalDateTimeUtils.valueToLocalDateTime(ValueTimestamp.get((Timestamp) val));
 
-                if (val instanceof Date && LocalDateTimeUtils.isLocalDate(expCls))
+                if (val instanceof Date && LocalDateTimeUtils.LOCAL_DATE == expCls)
                     return LocalDateTimeUtils.valueToLocalDate(ValueDate.fromDateValue(
                         DateTimeUtils.dateValueFromDate(((Date) val).getTime())));
 
-                if (val instanceof Time && LocalDateTimeUtils.isLocalTime(expCls))
+                if (val instanceof Time && LocalDateTimeUtils.LOCAL_TIME == expCls)
                     return LocalDateTimeUtils.valueToLocalTime(ValueTime.get((Time) val));
             }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/20f52468/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2CollocationModel.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2CollocationModel.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2CollocationModel.java
index 800a2aa..5e574e4 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2CollocationModel.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2CollocationModel.java
@@ -650,6 +650,9 @@ public final class GridH2CollocationModel {
             }
         }
 
+        if (filters == null)
+            return cm;
+
         assert cm.view;
 
         Select select = filters[0].getSelect();

http://git-wip-us.apache.org/repos/asf/ignite/blob/20f52468/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2ProxySpatialIndex.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2ProxySpatialIndex.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2ProxySpatialIndex.java
index 8af5099..9977128 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2ProxySpatialIndex.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2ProxySpatialIndex.java
@@ -53,9 +53,8 @@ public class GridH2ProxySpatialIndex extends GridH2ProxyIndex implements Spatial
 
     /** {@inheritDoc} */
     @Override public double getCost(Session ses, int[] masks, TableFilter[] filters, int filter,
-                                    SortOrder sortOrder, HashSet<Column> cols) {
-        return SpatialTreeIndex.getCostRangeIndex(masks,
-                table.getRowCountApproximation(), columns) / 10;
+        SortOrder sortOrder, HashSet<Column> cols) {
+        return SpatialTreeIndex.getCostRangeIndex(masks, columns) / 10;
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/20f52468/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2RowDescriptor.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2RowDescriptor.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2RowDescriptor.java
index 23f3ba4..d20496a 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2RowDescriptor.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2RowDescriptor.java
@@ -223,13 +223,13 @@ public class GridH2RowDescriptor {
                 UUID uuid = (UUID)obj;
                 return ValueUuid.get(uuid.getMostSignificantBits(), uuid.getLeastSignificantBits());
             case Value.DATE:
-                if (LocalDateTimeUtils.isLocalDate(obj.getClass()))
+                if (LocalDateTimeUtils.LOCAL_DATE == obj.getClass())
                     return LocalDateTimeUtils.localDateToDateValue(obj);
 
                 return ValueDate.get((Date)obj);
 
             case Value.TIME:
-                if (LocalDateTimeUtils.isLocalTime(obj.getClass()))
+                if (LocalDateTimeUtils.LOCAL_TIME == obj.getClass())
                     return LocalDateTimeUtils.localTimeToTimeValue(obj);
 
                 return ValueTime.get((Time)obj);
@@ -238,7 +238,7 @@ public class GridH2RowDescriptor {
                 if (obj instanceof java.util.Date && !(obj instanceof Timestamp))
                     obj = new Timestamp(((java.util.Date)obj).getTime());
 
-                if (LocalDateTimeUtils.isLocalDateTime(obj.getClass()))
+                if (LocalDateTimeUtils.LOCAL_DATE_TIME == obj.getClass())
                     return LocalDateTimeUtils.localDateTimeToValue(obj);
 
                 return ValueTimestamp.get((Timestamp)obj);

http://git-wip-us.apache.org/repos/asf/ignite/blob/20f52468/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2ValueCacheObject.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2ValueCacheObject.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2ValueCacheObject.java
index 9b5f0d5..5b1dfcd 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2ValueCacheObject.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2ValueCacheObject.java
@@ -25,6 +25,7 @@ import org.apache.ignite.internal.binary.BinaryObjectImpl;
 import org.apache.ignite.internal.processors.cache.CacheObject;
 import org.apache.ignite.internal.processors.cache.CacheObjectValueContext;
 import org.h2.message.DbException;
+import org.h2.util.Bits;
 import org.h2.util.JdbcUtils;
 import org.h2.util.Utils;
 import org.h2.value.CompareMode;
@@ -169,7 +170,7 @@ public class GridH2ValueCacheObject extends Value {
             if (o1.equals(o2))
                 return 0;
 
-            return Utils.compareNotNullSigned(getBytesNoCopy(), v.getBytesNoCopy());
+            return Bits.compareNotNullSigned(getBytesNoCopy(), v.getBytesNoCopy());
         }
 
         return h1 > h2 ? 1 : -1;

http://git-wip-us.apache.org/repos/asf/ignite/blob/20f52468/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlAggregateFunction.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlAggregateFunction.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlAggregateFunction.java
index 2978b15..cfe0155 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlAggregateFunction.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlAggregateFunction.java
@@ -18,7 +18,10 @@
 package org.apache.ignite.internal.processors.query.h2.sql;
 
 import org.apache.ignite.internal.util.typedef.F;
+import org.h2.expression.Aggregate;
 import org.h2.util.StatementBuilder;
+import org.h2.util.StringUtils;
+import org.jetbrains.annotations.Nullable;
 
 import static org.apache.ignite.internal.processors.query.h2.sql.GridSqlFunctionType.AVG;
 import static org.apache.ignite.internal.processors.query.h2.sql.GridSqlFunctionType.COUNT;
@@ -38,6 +41,39 @@ public class GridSqlAggregateFunction extends GridSqlFunction {
 //        STDDEV_POP, STDDEV_SAMP, VAR_POP, VAR_SAMP, BOOL_OR, BOOL_AND, SELECTIVITY, HISTOGRAM,
     };
 
+    /**
+     * Map type.
+     *
+     * @param type H2 type.
+     * @return Ignite type, {@code null} if not supported.
+     */
+    @Nullable private static GridSqlFunctionType mapType(Aggregate.AggregateType type) {
+        switch (type) {
+            case COUNT_ALL:
+                return COUNT_ALL;
+
+            case COUNT:
+                return COUNT;
+
+            case GROUP_CONCAT:
+                return GROUP_CONCAT;
+
+            case SUM:
+                return SUM;
+
+            case MIN:
+                return MIN;
+
+            case MAX:
+                return MAX;
+
+            case AVG:
+                return AVG;
+        }
+
+        return null;
+    }
+
     /** */
     private final boolean distinct;
 
@@ -62,20 +98,20 @@ public class GridSqlAggregateFunction extends GridSqlFunction {
 
     /**
      * @param distinct Distinct.
-     * @param typeId Type.
+     * @param type Type.
      */
-    public GridSqlAggregateFunction(boolean distinct, int typeId) {
-        this(distinct, TYPE_INDEX[typeId]);
+    public GridSqlAggregateFunction(boolean distinct, Aggregate.AggregateType type) {
+        this(distinct, mapType(type));
     }
 
     /**
      * Checks if the aggregate type is valid.
      *
-     * @param typeId Aggregate type id.
+     * @param type Aggregate type.
      * @return True is valid, otherwise false.
      */
-    protected static boolean isValidType(int typeId) {
-        return (typeId >= 0) && (typeId < TYPE_INDEX.length);
+    protected static boolean isValidType(Aggregate.AggregateType type) {
+        return mapType(type) != null;
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/20f52468/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java
index cca1dfc..a653e7f 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java
@@ -50,6 +50,7 @@ import org.h2.command.CommandInterface;
 import org.h2.command.Prepared;
 import org.h2.command.ddl.AlterTableAddConstraint;
 import org.h2.command.ddl.AlterTableAlterColumn;
+import org.h2.command.ddl.CommandWithColumns;
 import org.h2.command.ddl.CreateIndex;
 import org.h2.command.ddl.CreateTable;
 import org.h2.command.ddl.CreateTableData;
@@ -108,8 +109,6 @@ import org.jetbrains.annotations.Nullable;
 import static org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperationType.AND;
 import static org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperationType.BIGGER;
 import static org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperationType.BIGGER_EQUAL;
-import static org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperationType.CONCAT;
-import static org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperationType.DIVIDE;
 import static org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperationType.EQUAL;
 import static org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperationType.EQUAL_NULL_SAFE;
 import static org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperationType.EXISTS;
@@ -117,14 +116,10 @@ import static org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperatio
 import static org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperationType.IS_NOT_NULL;
 import static org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperationType.IS_NULL;
 import static org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperationType.LIKE;
-import static org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperationType.MINUS;
-import static org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperationType.MODULUS;
-import static org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperationType.MULTIPLY;
 import static org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperationType.NOT;
 import static org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperationType.NOT_EQUAL;
 import static org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperationType.NOT_EQUAL_NULL_SAFE;
 import static org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperationType.OR;
-import static org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperationType.PLUS;
 import static org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperationType.REGEXP;
 import static org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperationType.SMALLER;
 import static org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperationType.SMALLER_EQUAL;
@@ -138,10 +133,6 @@ import static org.apache.ignite.internal.processors.query.h2.sql.GridSqlType.fro
 @SuppressWarnings("TypeMayBeWeakened")
 public class GridSqlQueryParser {
     /** */
-    private static final GridSqlOperationType[] OPERATION_OP_TYPES =
-        {CONCAT, PLUS, MINUS, MULTIPLY, DIVIDE, null, MODULUS};
-
-    /** */
     private static final GridSqlOperationType[] COMPARISON_TYPES =
         {EQUAL, BIGGER_EQUAL, BIGGER, SMALLER_EQUAL,
         SMALLER, NOT_EQUAL, IS_NULL, IS_NOT_NULL,
@@ -165,7 +156,7 @@ public class GridSqlQueryParser {
     private static final Getter<SelectUnion, Boolean> UNION_IS_FOR_UPDATE = getter(SelectUnion.class, "isForUpdate");
 
     /** */
-    private static final Getter<Operation, Integer> OPERATION_TYPE = getter(Operation.class, "opType");
+    private static final Getter<Operation, Operation.OpType> OPERATION_TYPE = getter(Operation.class, "opType");
 
     /** */
     private static final Getter<Operation, Expression> OPERATION_LEFT = getter(Operation.class, "left");
@@ -249,7 +240,7 @@ public class GridSqlQueryParser {
     private static final Getter<Aggregate, Boolean> DISTINCT = getter(Aggregate.class, "distinct");
 
     /** */
-    private static final Getter<Aggregate, Integer> TYPE = getter(Aggregate.class, "type");
+    private static final Getter<Aggregate, Aggregate.AggregateType> TYPE = getter(Aggregate.class, "type");
 
     /** */
     private static final Getter<Aggregate, Expression> ON = getter(Aggregate.class, "on");
@@ -290,7 +281,7 @@ public class GridSqlQueryParser {
     private static final Getter<Explain, Prepared> EXPLAIN_COMMAND = getter(Explain.class, "command");
 
     /** */
-    private static final Getter<Merge, Table> MERGE_TABLE = getter(Merge.class, "table");
+    private static final Getter<Merge, Table> MERGE_TABLE = getter(Merge.class, "targetTable");
 
     /** */
     private static final Getter<Merge, Column[]> MERGE_COLUMNS = getter(Merge.class, "columns");
@@ -299,7 +290,7 @@ public class GridSqlQueryParser {
     private static final Getter<Merge, Column[]> MERGE_KEYS = getter(Merge.class, "keys");
 
     /** */
-    private static final Getter<Merge, List<Expression[]>> MERGE_ROWS = getter(Merge.class, "list");
+    private static final Getter<Merge, List<Expression[]>> MERGE_ROWS = getter(Merge.class, "valuesExpressionList");
 
     /** */
     private static final Getter<Merge, Query> MERGE_QUERY = getter(Merge.class, "query");
@@ -323,7 +314,7 @@ public class GridSqlQueryParser {
     private static final Getter<Insert, Boolean> INSERT_SORTED = getter(Insert.class, "sortedInsertMode");
 
     /** */
-    private static final Getter<Delete, TableFilter> DELETE_FROM = getter(Delete.class, "tableFilter");
+    private static final Getter<Delete, TableFilter> DELETE_FROM = getter(Delete.class, "targetTableFilter");
 
     /** */
     private static final Getter<Delete, Expression> DELETE_WHERE = getter(Delete.class, "condition");
@@ -332,7 +323,7 @@ public class GridSqlQueryParser {
     private static final Getter<Delete, Expression> DELETE_LIMIT = getter(Delete.class, "limitExpr");
 
     /** */
-    private static final Getter<Update, TableFilter> UPDATE_TARGET = getter(Update.class, "tableFilter");
+    private static final Getter<Update, TableFilter> UPDATE_TARGET = getter(Update.class, "targetTableFilter");
 
     /** */
     private static final Getter<Update, ArrayList<Column>> UPDATE_COLUMNS = getter(Update.class, "columns");
@@ -397,12 +388,12 @@ public class GridSqlQueryParser {
     private static final Getter<CreateTable, CreateTableData> CREATE_TABLE_DATA = getter(CreateTable.class, "data");
 
     /** */
-    private static final Getter<CreateTable, ArrayList<DefineCommand>> CREATE_TABLE_CONSTRAINTS =
-        getter(CreateTable.class, "constraintCommands");
+    private static final Getter<CommandWithColumns, ArrayList<DefineCommand>> CREATE_TABLE_CONSTRAINTS =
+        getter(CommandWithColumns.class, "constraintCommands");
 
     /** */
-    private static final Getter<CreateTable, IndexColumn[]> CREATE_TABLE_PK = getter(CreateTable.class,
-        "pkColumns");
+    private static final Getter<CommandWithColumns, IndexColumn[]> CREATE_TABLE_PK =
+        getter(CommandWithColumns.class, "pkColumns");
 
     /** */
     private static final Getter<CreateTable, Boolean> CREATE_TABLE_IF_NOT_EXISTS = getter(CreateTable.class,
@@ -1122,7 +1113,7 @@ public class GridSqlQueryParser {
 
         List<DefineCommand> constraints = CREATE_TABLE_CONSTRAINTS.get(createTbl);
 
-        if (constraints.size() == 0)
+        if (F.isEmpty(constraints))
             throw new IgniteSQLException("No PRIMARY KEY defined for CREATE TABLE",
                 IgniteQueryErrorCode.PARSING);
 
@@ -1923,6 +1914,41 @@ public class GridSqlQueryParser {
     }
 
     /**
+     * Map operation type.
+     *
+     * @param opType H2 operation type.
+     * @return Ignite operation type.
+     */
+    private static GridSqlOperationType mapOperationType(Operation.OpType opType) {
+        switch (opType) {
+            case CONCAT:
+                return GridSqlOperationType.CONCAT;
+
+            case PLUS:
+                return GridSqlOperationType.PLUS;
+
+            case MINUS:
+                return GridSqlOperationType.MINUS;
+
+            case MULTIPLY:
+                return GridSqlOperationType.MULTIPLY;
+
+            case DIVIDE:
+                return GridSqlOperationType.DIVIDE;
+
+            case NEGATE:
+                // NB: Was set to null in original code for some reason; left unchanged during 1.4.197 migration.
+                return null;
+
+            case MODULUS:
+                return GridSqlOperationType.MODULUS;
+
+            default:
+                throw new IllegalStateException("Unsupported operation type: " + opType);
+        }
+    }
+
+    /**
      * @param expression Expression.
      * @param calcTypes Calculate types for all the expressions.
      * @return Parsed expression.
@@ -1950,16 +1976,16 @@ public class GridSqlQueryParser {
         if (expression instanceof Operation) {
             Operation operation = (Operation)expression;
 
-            Integer type = OPERATION_TYPE.get(operation);
+            Operation.OpType type = OPERATION_TYPE.get(operation);
 
-            if (type == Operation.NEGATE) {
+            if (type == Operation.OpType.NEGATE) {
                 assert OPERATION_RIGHT.get(operation) == null;
 
                 return new GridSqlOperation(GridSqlOperationType.NEGATE,
                     parseExpression(OPERATION_LEFT.get(operation), calcTypes));
             }
 
-            return new GridSqlOperation(OPERATION_OP_TYPES[type],
+            return new GridSqlOperation(mapOperationType(type),
                 parseExpression(OPERATION_LEFT.get(operation), calcTypes),
                 parseExpression(OPERATION_RIGHT.get(operation), calcTypes));
         }
@@ -2118,11 +2144,11 @@ public class GridSqlQueryParser {
             return new GridSqlParameter(((Parameter)expression).getIndex());
 
         if (expression instanceof Aggregate) {
-            int typeId = TYPE.get((Aggregate)expression);
+            Aggregate.AggregateType type = TYPE.get((Aggregate)expression);
 
-            if (GridSqlAggregateFunction.isValidType(typeId)) {
+            if (GridSqlAggregateFunction.isValidType(type)) {
                 GridSqlAggregateFunction res = new GridSqlAggregateFunction(
-                    DISTINCT.get((Aggregate)expression), typeId);
+                    DISTINCT.get((Aggregate)expression), type);
 
                 Expression on = ON.get((Aggregate)expression);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/20f52468/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQuerySplitter.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQuerySplitter.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQuerySplitter.java
index c26be27..ca9c5bb 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQuerySplitter.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQuerySplitter.java
@@ -1338,7 +1338,7 @@ public class GridSqlQuerySplitter {
                 prntModel.add(model);
             }
 
-            if (((GridSqlUnion)child).unionType() != SelectUnion.UNION_ALL)
+            if (((GridSqlUnion)child).unionType() != SelectUnion.UnionType.UNION_ALL)
                 model.unionAll = false;
 
             buildQueryModel(model, child, LEFT_CHILD, null);

http://git-wip-us.apache.org/repos/asf/ignite/blob/20f52468/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlUnion.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlUnion.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlUnion.java
index 09f0e24..8d2ba42 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlUnion.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlUnion.java
@@ -32,7 +32,7 @@ public class GridSqlUnion extends GridSqlQuery {
     public static final int RIGHT_CHILD = 3;
 
     /** */
-    private int unionType;
+    private SelectUnion.UnionType unionType;
 
     /** */
     private GridSqlQuery right;
@@ -108,19 +108,19 @@ public class GridSqlUnion extends GridSqlQuery {
         buff.append('(').append(left.getSQL()).append(')');
 
         switch (unionType()) {
-            case SelectUnion.UNION_ALL:
+            case UNION_ALL:
                 buff.append("\nUNION ALL\n");
                 break;
 
-            case SelectUnion.UNION:
+            case UNION:
                 buff.append("\nUNION\n");
                 break;
 
-            case SelectUnion.INTERSECT:
+            case INTERSECT:
                 buff.append("\nINTERSECT\n");
                 break;
 
-            case SelectUnion.EXCEPT:
+            case EXCEPT:
                 buff.append("\nEXCEPT\n");
                 break;
 
@@ -137,7 +137,7 @@ public class GridSqlUnion extends GridSqlQuery {
 
     /** {@inheritDoc} */
     @Override public boolean simpleQuery() {
-        return unionType() == SelectUnion.UNION_ALL && sort().isEmpty() &&
+        return unionType() == SelectUnion.UnionType.UNION_ALL && sort().isEmpty() &&
             offset() == null && limit() == null &&
             left().simpleQuery() && right().simpleQuery();
     }
@@ -145,14 +145,14 @@ public class GridSqlUnion extends GridSqlQuery {
     /**
      * @return Union type.
      */
-    public int unionType() {
+    public SelectUnion.UnionType unionType() {
         return unionType;
     }
 
     /**
      * @param unionType New union type.
      */
-    public void unionType(int unionType) {
+    public void unionType(SelectUnion.UnionType unionType) {
         this.unionType = unionType;
     }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/20f52468/modules/mesos/src/main/java/org/apache/ignite/mesos/resource/IgniteProvider.java
----------------------------------------------------------------------
diff --git a/modules/mesos/src/main/java/org/apache/ignite/mesos/resource/IgniteProvider.java b/modules/mesos/src/main/java/org/apache/ignite/mesos/resource/IgniteProvider.java
index 5735051..4cd0c0a 100644
--- a/modules/mesos/src/main/java/org/apache/ignite/mesos/resource/IgniteProvider.java
+++ b/modules/mesos/src/main/java/org/apache/ignite/mesos/resource/IgniteProvider.java
@@ -52,13 +52,13 @@ public class IgniteProvider {
     private static final String DOWNLOAD_URL_PATTERN = "https://archive.apache.org/dist/ignite/%s/apache-ignite-fabric-%s-bin.zip";
 
     /** URL for request Ignite latest version. */
-    private final static String IGNITE_LATEST_VERSION_URL = "";
+    private final static String IGNITE_LATEST_VERSION_URL = "https://ignite.apache.org/latest";
 
     /** Mirrors. */
-    private static final String APACHE_MIRROR_URL = "";
+    private static final String APACHE_MIRROR_URL = "https://www.apache.org/dyn/closer.cgi?as_json=1";
 
     /** Ignite on Apache URL path. */
-    private static final String IGNITE_PATH = "";
+    private static final String IGNITE_PATH = "/ignite/%s/apache-ignite-fabric-%s-bin.zip";
 
     /** Version pattern. */
     private static final Pattern VERSION_PATTERN = Pattern.compile("(?<=version=).*\\S+");

http://git-wip-us.apache.org/repos/asf/ignite/blob/20f52468/modules/platforms/cpp/odbc-test/src/sql_esc_convert_function_test.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/src/sql_esc_convert_function_test.cpp b/modules/platforms/cpp/odbc-test/src/sql_esc_convert_function_test.cpp
index f583d02..a71d924 100644
--- a/modules/platforms/cpp/odbc-test/src/sql_esc_convert_function_test.cpp
+++ b/modules/platforms/cpp/odbc-test/src/sql_esc_convert_function_test.cpp
@@ -151,8 +151,8 @@ BOOST_AUTO_TEST_CASE(TestEscConvertFunctionTime)
 BOOST_AUTO_TEST_CASE(TestEscConvertFunctionTimestamp)
 {
     using ignite::impl::binary::BinaryUtils;
-    Timestamp ts = common::MakeTimestampGmt(1983, 3, 14, 13, 20, 15, 999999999);
-    CheckSingleResult<Timestamp>("SELECT {fn CONVERT('1983-03-14 13:20:15.999999999', SQL_TIMESTAMP)}", ts);
+    Timestamp ts = common::MakeTimestampGmt(1983, 3, 14, 13, 20, 15, 999999000);
+    CheckSingleResult<Timestamp>("SELECT {fn CONVERT('1983-03-14 13:20:15.999999', SQL_TIMESTAMP)}", ts);
 }
 
 BOOST_AUTO_TEST_SUITE_END()

http://git-wip-us.apache.org/repos/asf/ignite/blob/20f52468/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Misc.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Misc.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Misc.cs
index d9c57d0..8aaa7b8 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Misc.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Misc.cs
@@ -149,7 +149,7 @@ namespace Apache.Ignite.Core.Tests.Cache.Query.Linq
             TestConditionalWithNullableStructs<double>();
             TestConditionalWithNullableStructs<float>();
             TestConditionalWithNullableStructs<decimal>();
-            TestConditionalWithNullableStructs<DateTime>(DateTime.UtcNow);
+            TestConditionalWithNullableStructs<DateTime>(DateTime.Parse("1983-03-14 13:20:15.999999").ToUniversalTime());
 
             var charException = Assert.Throws<NotSupportedException>(() => TestConditionalWithNullableStructs<char>());
             Assert.AreEqual("Type is not supported for SQL mapping: System.Char", charException.Message);

http://git-wip-us.apache.org/repos/asf/ignite/blob/20f52468/modules/web-console/frontend/app/data/pom-dependencies.json
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/data/pom-dependencies.json b/modules/web-console/frontend/app/data/pom-dependencies.json
index 8d3fa81..d13bf14 100644
--- a/modules/web-console/frontend/app/data/pom-dependencies.json
+++ b/modules/web-console/frontend/app/data/pom-dependencies.json
@@ -19,7 +19,8 @@
     "PostgreSQL": {"groupId": "org.postgresql", "artifactId": "postgresql", "version": "9.4.1212.jre7"},
     "H2": {"groupId": "com.h2database", "artifactId": "h2", "version": [
         {"range": ["1.0.0", "2.0.0"], "version": "1.4.191"},
-        {"range": "2.0.0", "version": "1.4.195"}
+        {"range": ["2.0.0", "2.7.0"], "version": "1.4.195"},
+        {"range": "2.7.0", "version": "1.4.197"}
     ]},
     "Oracle": {"groupId": "com.oracle.jdbc", "artifactId": "ojdbc7", "version": "12.1.0.2", "jar": "ojdbc7.jar"},
     "DB2": {"groupId": "ibm", "artifactId": "jdbc", "version": "4.21.29", "jar": "db2jcc4.jar"},

http://git-wip-us.apache.org/repos/asf/ignite/blob/20f52468/modules/yardstick/config/benchmark-native-sql-select-join.properties
----------------------------------------------------------------------
diff --git a/modules/yardstick/config/benchmark-native-sql-select-join.properties b/modules/yardstick/config/benchmark-native-sql-select-join.properties
new file mode 100644
index 0000000..f32622a
--- /dev/null
+++ b/modules/yardstick/config/benchmark-native-sql-select-join.properties
@@ -0,0 +1,89 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#
+# Contains benchmarks for select queries
+#
+
+now0=`date +'%H%M%S'`
+
+# JVM options.
+JVM_OPTS=${JVM_OPTS}" -DIGNITE_QUIET=false"
+
+# Uncomment to enable concurrent garbage collection (GC) if you encounter long GC pauses.
+JVM_OPTS=${JVM_OPTS}" \
+-Xms8g \
+-Xmx8g \
+-Xloggc:./gc${now0}.log \
+-XX:+PrintGCDetails \
+-verbose:gc \
+-XX:+UseParNewGC \
+-XX:+UseConcMarkSweepGC \
+-XX:+PrintGCDateStamps \
+"
+
+#Ignite version
+ver="RELEASE-"
+
+# List of default probes.
+# Add DStatProbe or VmStatProbe if your OS supports it (e.g. if running on Linux).
+BENCHMARK_DEFAULT_PROBES=ThroughputLatencyProbe,PercentileProbe,DStatProbe
+
+# Packages where the specified benchmark is searched by reflection mechanism.
+BENCHMARK_PACKAGES=org.yardstickframework,org.apache.ignite.yardstick
+
+# Flag which indicates to restart the servers before every benchmark execution.
+RESTART_SERVERS=true
+
+# Probe point writer class name.
+# BENCHMARK_WRITER=
+
+# The benchmark is applicable only for 1 server and 1 driver
+SERVER_HOSTS=""
+DRIVER_HOSTS=127.0.0.1
+
+# Remote username.
+# REMOTE_USER=
+
+# Number of nodes, used to wait for the specified number of nodes to start.
+nodesNum=$((`echo ${SERVER_HOSTS} | tr ',' '\n' | wc -l` + `echo ${DRIVER_HOSTS} | tr ',' '\n' | wc -l`))
+
+# Backups count.
+b=1
+
+# Warmup.
+w=30
+
+# Duration.
+d=300
+
+# Threads count.
+t=4
+
+# Sync mode.
+sm=PRIMARY_SYNC
+
+# Jobs.
+j=10
+
+DATA_RANGE=100000
+
+# Run configuration which contains all benchmarks.
+# Note that each benchmark is set to run for 300 seconds (5 min) with warm-up set to 60 seconds (1 minute).
+CONFIGS="\
+-cfg ${SCRIPT_DIR}/../config/ignite-localhost-config.xml -pc 2 -nn 1 -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -r ${DATA_RANGE} --sqlRange 1 -dn NativeSqlJoinQueryRangeBenchmark -sn IgniteNode -ds ${ver}sql-select-native-r1-${b}-backup,\
+-cfg ${SCRIPT_DIR}/../config/ignite-localhost-config.xml -pc 2 -nn 1 -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -r ${DATA_RANGE} --sqlRange 1000 -dn NativeSqlJoinQueryRangeBenchmark -sn IgniteNode -ds ${ver}sql-select-native-r1k-${b}-backup ,\
+-cfg ${SCRIPT_DIR}/../config/ignite-localhost-config.xml -pc 2 -nn 1 -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -r ${DATA_RANGE} --sqlRange -1 -dn NativeSqlJoinQueryRangeBenchmark -sn IgniteNode -ds ${ver}sql-select-native-r100k-${b}-backup,\
+"

http://git-wip-us.apache.org/repos/asf/ignite/blob/20f52468/modules/yardstick/src/main/java/org/apache/ignite/yardstick/jdbc/NativeSqlJoinQueryRangeBenchmark.java
----------------------------------------------------------------------
diff --git a/modules/yardstick/src/main/java/org/apache/ignite/yardstick/jdbc/NativeSqlJoinQueryRangeBenchmark.java b/modules/yardstick/src/main/java/org/apache/ignite/yardstick/jdbc/NativeSqlJoinQueryRangeBenchmark.java
new file mode 100644
index 0000000..f660b8c
--- /dev/null
+++ b/modules/yardstick/src/main/java/org/apache/ignite/yardstick/jdbc/NativeSqlJoinQueryRangeBenchmark.java
@@ -0,0 +1,135 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.yardstick.jdbc;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ThreadLocalRandom;
+import org.apache.ignite.cache.query.FieldsQueryCursor;
+import org.apache.ignite.cache.query.SqlFieldsQuery;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.processors.query.GridQueryProcessor;
+import org.apache.ignite.yardstick.IgniteAbstractBenchmark;
+import org.yardstickframework.BenchmarkConfiguration;
+
+import static org.yardstickframework.BenchmarkUtils.println;
+
+/**
+ * Native sql benchmark that performs select operations.
+ */
+public class NativeSqlJoinQueryRangeBenchmark extends IgniteAbstractBenchmark {
+    /** Ignite query processor. */
+    GridQueryProcessor qry;
+
+    /**
+     * Benchmarked action that performs selects and validates results.
+     *
+     * {@inheritDoc}
+     */
+    @Override public boolean test(Map<Object, Object> ctx) throws Exception {
+        long expRsSize;
+
+        SqlFieldsQuery qry;
+
+        if (args.sqlRange() == 1) {
+            qry = new SqlFieldsQuery("SELECT * FROM person p join organization o on p.orgId=o.id WHERE p.id = ? " +
+                "order by p.id");
+
+            qry.setArgs(ThreadLocalRandom.current().nextLong(args.range()) + 1);
+
+            expRsSize = 1;
+        }
+        else if (args.sqlRange() <= 0) {
+            qry = new SqlFieldsQuery("SELECT * FROM person p join organization o on p.orgId=o.id order by p.id LIMIT 1000");
+
+            expRsSize = 1000;
+        }
+        else {
+            qry = new SqlFieldsQuery("SELECT * FROM person p join organization o on p.orgId=o.id WHERE p.id BETWEEN ? AND ?" +
+                "order by p.id");
+
+            long id = ThreadLocalRandom.current().nextLong(args.range() - args.sqlRange()) + 1;
+            long maxId = id + args.sqlRange() - 1;
+
+            qry.setArgs(id, maxId);
+
+            expRsSize = args.sqlRange();
+        }
+
+        long rsSize = 0;
+
+        try (FieldsQueryCursor<List<?>> cursor = ((IgniteEx)ignite()).context().query()
+                .querySqlFields(qry, false)) {
+
+            for (List<?> r : cursor)
+                rsSize++;
+        }
+
+        if (rsSize != expRsSize)
+            throw new Exception("Invalid result set size [actual=" + rsSize + ", expected=" + expRsSize + ']');
+
+        return true;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setUp(BenchmarkConfiguration cfg) throws Exception {
+        super.setUp(cfg);
+
+        qry = ((IgniteEx)ignite()).context().query();
+
+        StringBuilder withExpr = new StringBuilder(" WITH \"AFFINITY_KEY=orgId,");
+
+        if (args.atomicMode() != null)
+            withExpr.append("atomicity=").append(args.atomicMode().name()).append(",");
+
+        if (args.partitionedCachesNumber() == 1)
+            withExpr.append("template=replicated");
+        else
+            withExpr.append("template=partitioned");
+
+        withExpr.append("\"");
+
+        qry.querySqlFields(
+            new SqlFieldsQuery("CREATE TABLE person (id long, orgId long, name varchar, PRIMARY KEY (id, orgId))" + withExpr), true);
+
+        withExpr = new StringBuilder(" WITH \"");
+
+        if (args.atomicMode() != null)
+            withExpr.append("atomicity=").append(args.atomicMode().name()).append(",");
+
+        withExpr.append("template=partitioned");
+
+        withExpr.append("\"");
+
+        qry.querySqlFields(
+            new SqlFieldsQuery("CREATE TABLE organization (id long primary key, name varchar)" + withExpr), true);
+
+        for (long k = 1; k <= args.range(); ++k) {
+            qry.querySqlFields(new SqlFieldsQuery("insert into person (id, orgId, name) values (?, ?, ?)")
+                .setArgs(k, k / 10, "person " + k), true).getAll();
+
+            if (k % 10 == 0) {
+                qry.querySqlFields(new SqlFieldsQuery("insert into organization (id, name) values (?, ?)")
+                    .setArgs(k / 10, "organization " + k / 10), true).getAll();
+            }
+
+            if (k % 10000 == 0)
+                println(cfg, "Populate " + k);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/20f52468/parent/pom.xml
----------------------------------------------------------------------
diff --git a/parent/pom.xml b/parent/pom.xml
index cc92ca8..cc04175 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -69,7 +69,7 @@
         <guava.version>25.1-jre</guava.version>
         <guava14.version>14.0.1</guava14.version>
         <guava16.version>16.0.1</guava16.version>
-        <h2.version>1.4.195</h2.version>
+        <h2.version>1.4.197</h2.version>
         <hadoop.version>2.9.1</hadoop.version>
         <hamcrest.version>1.2</hamcrest.version>
         <httpclient.version>4.5.1</httpclient.version>


[5/9] ignite git commit: Updated Ignite description

Posted by vo...@apache.org.
Updated Ignite description


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

Branch: refs/heads/ignite-2.7
Commit: 32165dbb0202a994fcf679774bf38993adc7647d
Parents: 8f771ba
Author: Denis Magda <dm...@gridgain.com>
Authored: Tue Sep 25 23:08:05 2018 -0700
Committer: devozerov <vo...@gridgain.com>
Committed: Wed Sep 26 12:37:24 2018 +0300

----------------------------------------------------------------------
 README.md  | 38 +++++++++++++++++++++++++++-----------
 README.txt | 12 ++++++------
 2 files changed, 33 insertions(+), 17 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/32165dbb/README.md
----------------------------------------------------------------------
diff --git a/README.md b/README.md
index b4a9b23..e6f5abf 100644
--- a/README.md
+++ b/README.md
@@ -16,26 +16,42 @@ You can find the full Apache Ignite documentation here: [Full documentation][doc
 
 ## What is Apache Ignite?
 
-[Apache Ignite][apache-ignite-homepage] is a memory-centric multi-model distributed
- <strong>database</strong>, <strong>caching</strong>, and <strong>processing</strong> platform for
- transactional, analytical, and streaming workloads, delivering in-memory speeds at petabyte scale.
+[Apache Ignite][apache-ignite-homepage] is a memory-centric distributed <strong>database</strong>, <strong>caching</strong>,
+ and <strong>processing</strong> platform for transactional, analytical, and streaming workloads delivering in-memory
+ speeds at petabyte scale.
 
 <p align="center">
-    <a href="https://apacheignite.readme.io/docs">
-        <img src="https://ignite.apache.org/images/durable-memory.png" width="900px"/>
+    <a href="https://ignite.apache.org/whatisignite.html">
+        <img src="https://ignite.apache.org/images/ignite_architecture.png" width="900px"/>
     </a>
 </p>
 
-## Durable Memory
-Ignite's durable memory component treats RAM not just as a caching layer but as a complete fully functional storage layer. This means that users can turn the persistence on and off as needed. If the persistence is off, then Ignite can act as a distributed **in-memory database** or **in-memory data grid**, depending on whether you prefer to use SQL or key-value APIs. If the persistence is turned on, then Ignite becomes a distributed, **horizontally scalable database** that guarantees full data consistency and is resilient to full cluster failures.
+## Memory-Centric Storage
+Apache Ignite is based on distributed memory-centric architecture that combines the performance and scale of in-memory
+computing together with the disk durability and strong consistency in one system.
 
-[Read More](https://apacheignite.readme.io/docs/durable-memory)
+The main difference between the memory-centric approach and the traditional disk-centric approach is that the memory
+is treated as a fully functional storage, not just as a caching layer, like most databases do.
+For example, Apache Ignite can function in a pure in-memory mode, in which case it can be treated as an
+In-Memory Database (IMDB) and In-Memory Data Grid (IMDG) in one.
+
+On the other hand, when persistence is turned on, Ignite begins to function as a memory-centric system where most of
+the processing happens in memory, but the data and indexes get persisted to disk. The main difference here
+from the traditional disk-centric RDBMS or NoSQL system is that Ignite is strongly consistent, horizontally
+scalable, and supports both SQL and key-value processing APIs.
+
+[Read More](https://ignite.apache.org/arch/memorycentric.html)
 
 ## Ignite Persistence
 
-Ignite Native Persistence is a distributed, ACID, and SQL-compliant **disk store** that transparently integrates with Ignite's Durable Memory as an optional disk layer storing data and indexes on SSD, Flash, 3D XPoint, and other types of non-volatile storages.
+Ignite Native Persistence is a distributed, ACID, and SQL-compliant **disk store** that transparently integrates with
+Ignite memory-centric storage as an optional disk layer storing data and indexes on SSD,
+ Flash, 3D XPoint, and other types of non-volatile storages.
 
-With the Ignite Persistence enabled, you no longer need to keep all the data and indexes in memory or warm it up after a node or cluster restart because the Durable Memory is tightly coupled with persistence and treats it as a secondary memory tier. This implies that if a subset of data or an index is missing in RAM, the Durable Memory will take it from the disk.
+With the Ignite Persistence enabled, you no longer need to keep all the data and indexes in memory or warm it
+up after a node or cluster restart because the Durable Memory is tightly coupled with persistence and treats
+it as a secondary memory tier. This implies that if a subset of data or an index is missing in RAM,
+the Durable Memory will take it from the disk.
 
 <p align="center">
     <a href="https://apacheignite.readme.io/docs/distributed-persistent-store">
@@ -43,7 +59,7 @@ With the Ignite Persistence enabled, you no longer need to keep all the data and
     </a>
 </p>
 
-[Read More](https://apacheignite.readme.io/docs/distributed-persistent-store)
+[Read More](https://ignite.apache.org/arch/persistence.html)
 
 ## ACID Compliance
 Data stored in Ignite is ACID-compliant both in memory and on disk, making Ignite a **strongly consistent** system. Ignite transactions work across the network and can span multiple servers.

http://git-wip-us.apache.org/repos/asf/ignite/blob/32165dbb/README.txt
----------------------------------------------------------------------
diff --git a/README.txt b/README.txt
index 013f290..7cfdaad 100644
--- a/README.txt
+++ b/README.txt
@@ -1,16 +1,16 @@
 Apache Ignite In-Memory Data Fabric
 ===================================
 
-Ignite In-Memory Data Fabric is designed to deliver high performance for the widest
-array of in-memory computing use cases.
+Ignite is a memory-centric distributed database, caching, and processing platform for transactional, analytical,
+and streaming workloads delivering in-memory speeds at petabyte scale.
 
-The main feature set of Ignite In-Memory Data Fabric includes:
+The main feature set of Ignite includes:
+* Memory-Centric Storage
 * Advanced Clustering
+* Distributed Key-Value
+* Distributed SQL
 * Compute Grid
-* Data Grid
-* SQL Database
 * Service Grid
-* IGFS - Ignite File System
 * Distributed Data Structures
 * Distributed Messaging
 * Distributed Events


[2/9] ignite git commit: IGNITE-9538: MVCC: update partition counters on prepare phase. This closes #4795.

Posted by vo...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxQueryFirstEnlistRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxQueryFirstEnlistRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxQueryFirstEnlistRequest.java
index 5df1d58..5c1bf6c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxQueryFirstEnlistRequest.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxQueryFirstEnlistRequest.java
@@ -26,7 +26,6 @@ import org.apache.ignite.internal.processors.cache.mvcc.MvccSnapshot;
 import org.apache.ignite.internal.processors.cache.mvcc.MvccSnapshotWithoutTxs;
 import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
 import org.apache.ignite.internal.processors.query.EnlistOperation;
-import org.apache.ignite.internal.util.GridLongList;
 import org.apache.ignite.internal.util.typedef.internal.S;
 import org.apache.ignite.lang.IgniteUuid;
 import org.apache.ignite.plugin.extensions.communication.Message;
@@ -88,7 +87,6 @@ public class GridDhtTxQueryFirstEnlistRequest extends GridDhtTxQueryEnlistReques
      * @param batchId Batch id.
      * @param keys Keys.
      * @param vals Values.
-     * @param updCntrs Update counters.
      */
     GridDhtTxQueryFirstEnlistRequest(int cacheId,
         IgniteUuid dhtFutId,
@@ -103,9 +101,8 @@ public class GridDhtTxQueryFirstEnlistRequest extends GridDhtTxQueryEnlistReques
         EnlistOperation op,
         int batchId,
         List<KeyCacheObject> keys,
-        List<Message> vals,
-        GridLongList updCntrs) {
-        super(cacheId, dhtFutId, lockVer, op, batchId, snapshot.operationCounter(), keys, vals, updCntrs);
+        List<Message> vals) {
+        super(cacheId, dhtFutId, lockVer, op, batchId, snapshot.operationCounter(), keys, vals);
         this.cacheId = cacheId;
         this.subjId = subjId;
         this.topVer = topVer;
@@ -211,55 +208,55 @@ public class GridDhtTxQueryFirstEnlistRequest extends GridDhtTxQueryEnlistReques
         }
 
         switch (writer.state()) {
-            case 11:
+            case 10:
                 if (!writer.writeLong("cleanupVer", cleanupVer))
                     return false;
 
                 writer.incrementState();
 
-            case 12:
+            case 11:
                 if (!writer.writeLong("cntr", cntr))
                     return false;
 
                 writer.incrementState();
 
-            case 13:
+            case 12:
                 if (!writer.writeLong("crdVer", crdVer))
                     return false;
 
                 writer.incrementState();
 
-            case 14:
+            case 13:
                 if (!writer.writeUuid("nearNodeId", nearNodeId))
                     return false;
 
                 writer.incrementState();
 
-            case 15:
+            case 14:
                 if (!writer.writeMessage("nearXidVer", nearXidVer))
                     return false;
 
                 writer.incrementState();
 
-            case 16:
+            case 15:
                 if (!writer.writeUuid("subjId", subjId))
                     return false;
 
                 writer.incrementState();
 
-            case 17:
+            case 16:
                 if (!writer.writeInt("taskNameHash", taskNameHash))
                     return false;
 
                 writer.incrementState();
 
-            case 18:
+            case 17:
                 if (!writer.writeLong("timeout", timeout))
                     return false;
 
                 writer.incrementState();
 
-            case 19:
+            case 18:
                 if (!writer.writeMessage("topVer", topVer))
                     return false;
 
@@ -281,7 +278,7 @@ public class GridDhtTxQueryFirstEnlistRequest extends GridDhtTxQueryEnlistReques
             return false;
 
         switch (reader.state()) {
-            case 11:
+            case 10:
                 cleanupVer = reader.readLong("cleanupVer");
 
                 if (!reader.isLastRead())
@@ -289,7 +286,7 @@ public class GridDhtTxQueryFirstEnlistRequest extends GridDhtTxQueryEnlistReques
 
                 reader.incrementState();
 
-            case 12:
+            case 11:
                 cntr = reader.readLong("cntr");
 
                 if (!reader.isLastRead())
@@ -297,7 +294,7 @@ public class GridDhtTxQueryFirstEnlistRequest extends GridDhtTxQueryEnlistReques
 
                 reader.incrementState();
 
-            case 13:
+            case 12:
                 crdVer = reader.readLong("crdVer");
 
                 if (!reader.isLastRead())
@@ -305,7 +302,7 @@ public class GridDhtTxQueryFirstEnlistRequest extends GridDhtTxQueryEnlistReques
 
                 reader.incrementState();
 
-            case 14:
+            case 13:
                 nearNodeId = reader.readUuid("nearNodeId");
 
                 if (!reader.isLastRead())
@@ -313,7 +310,7 @@ public class GridDhtTxQueryFirstEnlistRequest extends GridDhtTxQueryEnlistReques
 
                 reader.incrementState();
 
-            case 15:
+            case 14:
                 nearXidVer = reader.readMessage("nearXidVer");
 
                 if (!reader.isLastRead())
@@ -321,7 +318,7 @@ public class GridDhtTxQueryFirstEnlistRequest extends GridDhtTxQueryEnlistReques
 
                 reader.incrementState();
 
-            case 16:
+            case 15:
                 subjId = reader.readUuid("subjId");
 
                 if (!reader.isLastRead())
@@ -329,7 +326,7 @@ public class GridDhtTxQueryFirstEnlistRequest extends GridDhtTxQueryEnlistReques
 
                 reader.incrementState();
 
-            case 17:
+            case 16:
                 taskNameHash = reader.readInt("taskNameHash");
 
                 if (!reader.isLastRead())
@@ -337,7 +334,7 @@ public class GridDhtTxQueryFirstEnlistRequest extends GridDhtTxQueryEnlistReques
 
                 reader.incrementState();
 
-            case 18:
+            case 17:
                 timeout = reader.readLong("timeout");
 
                 if (!reader.isLastRead())
@@ -345,7 +342,7 @@ public class GridDhtTxQueryFirstEnlistRequest extends GridDhtTxQueryEnlistReques
 
                 reader.incrementState();
 
-            case 19:
+            case 18:
                 topVer = reader.readMessage("topVer");
 
                 if (!reader.isLastRead())
@@ -360,7 +357,7 @@ public class GridDhtTxQueryFirstEnlistRequest extends GridDhtTxQueryEnlistReques
 
     /** {@inheritDoc} */
     @Override public byte fieldsCount() {
-        return 20;
+        return 19;
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxRemote.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxRemote.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxRemote.java
index 2fdb6ac..609bc4a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxRemote.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxRemote.java
@@ -387,12 +387,11 @@ public class GridDhtTxRemote extends GridDistributedTxRemoteAdapter {
      * @param keys Keys.
      * @param vals Values.
      * @param snapshot Mvcc snapshot.
-     * @param updCntrs Update counters.
      * @throws IgniteCheckedException If failed.
      */
     public void mvccEnlistBatch(GridCacheContext ctx, EnlistOperation op, List<KeyCacheObject> keys,
-        List<Message> vals, MvccSnapshot snapshot, GridLongList updCntrs) throws IgniteCheckedException {
-        assert keys != null && updCntrs != null && keys.size() == updCntrs.size();
+        List<Message> vals, MvccSnapshot snapshot) throws IgniteCheckedException {
+        assert keys != null && (vals == null || vals.size() == keys.size());
 
         WALPointer ptr = null;
 
@@ -438,7 +437,6 @@ public class GridDhtTxRemote extends GridDistributedTxRemoteAdapter {
                                         this,
                                         ctx.localNodeId(),
                                         topologyVersion(),
-                                        updCntrs.get(i),
                                         snapshot,
                                         false);
 
@@ -453,7 +451,6 @@ public class GridDhtTxRemote extends GridDistributedTxRemoteAdapter {
                                         val,
                                         0,
                                         topologyVersion(),
-                                        updCntrs.get(i),
                                         snapshot,
                                         op.cacheOperation(),
                                         false,
@@ -471,7 +468,6 @@ public class GridDhtTxRemote extends GridDistributedTxRemoteAdapter {
                             updRes = entry.mvccUpdateRowsWithPreloadInfo(this,
                                 ctx.localNodeId(),
                                 topologyVersion(),
-                                updCntrs.get(i),
                                 entries.infos(),
                                 op.cacheOperation(),
                                 snapshot);

http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/NearTxQueryEnlistResultHandler.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/NearTxQueryEnlistResultHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/NearTxQueryEnlistResultHandler.java
index bb863fb..8043def 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/NearTxQueryEnlistResultHandler.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/NearTxQueryEnlistResultHandler.java
@@ -82,7 +82,7 @@ public final class NearTxQueryEnlistResultHandler implements CI1<IgniteInternalF
             assert future.tx.queryEnlisted() || future.cnt == 0;
 
             return new GridNearTxQueryEnlistResponse(future.cctx.cacheId(), future.nearFutId, future.nearMiniId,
-                future.nearLockVer, future.cnt, future.tx.empty() && !future.tx.queryEnlisted());
+                future.nearLockVer, future.cnt, future.tx.empty() && !future.tx.queryEnlisted(), future.newDhtNodes);
         }
         catch (IgniteCheckedException e) {
             return new GridNearTxQueryEnlistResponse(future.cctx.cacheId(), future.nearFutId, future.nearMiniId, future.nearLockVer, e);
@@ -90,29 +90,28 @@ public final class NearTxQueryEnlistResultHandler implements CI1<IgniteInternalF
     }
 
     /**
-     * @param future Enlist future.
+     * @param fut Enlist future.
      * @return Enlist response.
      */
-    @NotNull private static GridNearTxQueryResultsEnlistResponse createResponse(GridDhtTxQueryResultsEnlistFuture future) {
+    @NotNull private static GridNearTxQueryResultsEnlistResponse createResponse(GridDhtTxQueryResultsEnlistFuture fut) {
         try {
-            future.get();
+            fut.get();
 
             GridCacheVersion ver = null;
             IgniteUuid id = null;
-            GridLongList updCntrs = null;
 
-            if (future.hasNearNodeUpdates) {
-                ver = future.cctx.tm().mappedVersion(future.nearLockVer);
-                id = future.futId;
-                updCntrs = future.nearUpdCntrs;
+            if (fut.hasNearNodeUpdates) {
+                ver = fut.cctx.tm().mappedVersion(fut.nearLockVer);
+
+                id = fut.futId;
             }
 
-            return new GridNearTxQueryResultsEnlistResponse(future.cctx.cacheId(), future.nearFutId, future.nearMiniId,
-                future.nearLockVer, future.cnt, ver, id, updCntrs);
+            return new GridNearTxQueryResultsEnlistResponse(fut.cctx.cacheId(), fut.nearFutId, fut.nearMiniId,
+                fut.nearLockVer, fut.cnt, ver, id, fut.newDhtNodes);
         }
         catch (IgniteCheckedException e) {
-            return new GridNearTxQueryResultsEnlistResponse(future.cctx.cacheId(), future.nearFutId, future.nearMiniId,
-                future.nearLockVer, e);
+            return new GridNearTxQueryResultsEnlistResponse(fut.cctx.cacheId(), fut.nearFutId, fut.nearMiniId,
+                fut.nearLockVer, e);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/PartitionUpdateCounters.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/PartitionUpdateCounters.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/PartitionUpdateCounters.java
deleted file mode 100644
index 5b1eccd..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/PartitionUpdateCounters.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.processors.cache.distributed.dht;
-
-import java.nio.ByteBuffer;
-import java.util.Map;
-import org.apache.ignite.internal.GridDirectMap;
-import org.apache.ignite.plugin.extensions.communication.Message;
-import org.apache.ignite.plugin.extensions.communication.MessageCollectionItemType;
-import org.apache.ignite.plugin.extensions.communication.MessageReader;
-import org.apache.ignite.plugin.extensions.communication.MessageWriter;
-
-/**
- * Partition update counters message.
- */
-public class PartitionUpdateCounters implements Message {
-    /** */
-    private static final long serialVersionUID = 193442457510062844L;
-
-    /** Map of update counters made by this tx. Mapping: partId -> updCntr. */
-    @GridDirectMap(keyType = Integer.class, valueType = Long.class)
-    private Map<Integer, Long> updCntrs;
-
-    /** */
-    public PartitionUpdateCounters() {
-        // No-op.
-    }
-
-    /**
-     * @param updCntrs Update counters map.
-     */
-    public PartitionUpdateCounters(Map<Integer, Long> updCntrs) {
-        this.updCntrs = updCntrs;
-    }
-
-    /**
-     * @return Update counters.
-     */
-    public Map<Integer, Long> updateCounters() {
-        return updCntrs;
-    }
-
-    /**
-     * @param updCntrs Update counters.
-     */
-    public void updateCounters(Map<Integer, Long> updCntrs) {
-        this.updCntrs = updCntrs;
-    }
-
-    /** {@inheritDoc} */
-    @Override public boolean writeTo(ByteBuffer buf, MessageWriter writer) {
-        writer.setBuffer(buf);
-
-        if (!writer.isHeaderWritten()) {
-            if (!writer.writeHeader(directType(), fieldsCount()))
-                return false;
-
-            writer.onHeaderWritten();
-        }
-
-        switch (writer.state()) {
-            case 0:
-                if (!writer.writeMap("updCntrs", updCntrs, MessageCollectionItemType.INT, MessageCollectionItemType.LONG))
-                    return false;
-
-                writer.incrementState();
-
-        }
-
-        return true;
-    }
-
-    /** {@inheritDoc} */
-    @Override public boolean readFrom(ByteBuffer buf, MessageReader reader) {
-        reader.setBuffer(buf);
-
-        if (!reader.beforeMessageRead())
-            return false;
-
-        switch (reader.state()) {
-            case 0:
-                updCntrs = reader.readMap("updCntrs", MessageCollectionItemType.INT, MessageCollectionItemType.LONG, false);
-
-                if (!reader.isLastRead())
-                    return false;
-
-                reader.incrementState();
-
-        }
-
-        return reader.afterMessageRead(PartitionUpdateCounters.class);
-    }
-
-    /** {@inheritDoc} */
-    @Override public short directType() {
-        return 157;
-    }
-
-    /** {@inheritDoc} */
-    @Override public byte fieldsCount() {
-        return 1;
-    }
-
-    /** {@inheritDoc} */
-    @Override public void onAckReceived() {
-        // No-op.
-    }
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/PartitionUpdateCountersMessage.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/PartitionUpdateCountersMessage.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/PartitionUpdateCountersMessage.java
new file mode 100644
index 0000000..6ee0294
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/PartitionUpdateCountersMessage.java
@@ -0,0 +1,259 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.cache.distributed.dht;
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import org.apache.ignite.internal.GridDirectTransient;
+import org.apache.ignite.internal.util.GridUnsafe;
+import org.apache.ignite.plugin.extensions.communication.Message;
+import org.apache.ignite.plugin.extensions.communication.MessageReader;
+import org.apache.ignite.plugin.extensions.communication.MessageWriter;
+
+/**
+ * Partition update counters message.
+ */
+public class PartitionUpdateCountersMessage implements Message {
+    /** */
+    private static final int ITEM_SIZE = 4 /* partition */ + 8 /* initial counter */ + 8 /* updates count */;
+
+    /** */
+    private static final long serialVersionUID = 193442457510062844L;
+
+    /** */
+    private byte data[];
+
+    /** */
+    private int cacheId;
+
+    /** */
+    @GridDirectTransient
+    private int size;
+
+    /** */
+    public PartitionUpdateCountersMessage() {
+        // No-op.
+    }
+
+    /**
+     * @param cacheId Cache id.
+     * @param initSize Initial size.
+     */
+    public PartitionUpdateCountersMessage(int cacheId, int initSize) {
+        assert initSize >= 1;
+
+        this.cacheId = cacheId;
+        data = new byte[initSize * ITEM_SIZE];
+    }
+
+    /**
+     * @return Cache id.
+     */
+    public int cacheId() {
+        return cacheId;
+    }
+
+    /**
+     * @return Size.
+     */
+    public int size() {
+        return size;
+    }
+
+    /**
+     * @param idx Item number.
+     * @return Partition number.
+     */
+    public int partition(int idx) {
+        if (idx >= size)
+            throw new ArrayIndexOutOfBoundsException();
+
+        long off = GridUnsafe.BYTE_ARR_OFF + idx * ITEM_SIZE;
+
+        return GridUnsafe.getInt(data, off);
+    }
+
+    /**
+     * @param idx Item number.
+     * @return Partition number.
+     */
+    public long initialCounter(int idx){
+        if (idx >= size)
+            throw new ArrayIndexOutOfBoundsException();
+
+        long off = GridUnsafe.BYTE_ARR_OFF + idx * ITEM_SIZE + 4;
+
+        return GridUnsafe.getLong(data, off);
+    }
+
+    /**
+     * @param idx Item number.
+     * @param value Initial partition counter.
+     */
+    public void initialCounter(int idx, long value){
+        if (idx >= size)
+            throw new ArrayIndexOutOfBoundsException();
+
+        long off = GridUnsafe.BYTE_ARR_OFF + idx * ITEM_SIZE + 4;
+
+        GridUnsafe.putLong(data, off, value);
+    }
+
+    /**
+     * @param idx Item number.
+     * @return Update counter delta.
+     */
+    public long updatesCount(int idx){
+        if (idx >= size)
+            throw new ArrayIndexOutOfBoundsException();
+
+        long off = GridUnsafe.BYTE_ARR_OFF + idx * ITEM_SIZE + 12;
+
+        return GridUnsafe.getLong(data, off);
+    }
+
+    /**
+     * @param part Partition number.
+     * @param init Init partition counter.
+     * @param updatesCnt Update counter delta.
+     */
+    public void add(int part, long init, long updatesCnt) {
+        ensureSpace(size + 1);
+
+        long off = GridUnsafe.BYTE_ARR_OFF + size++ * ITEM_SIZE;
+
+        GridUnsafe.putInt(data, off, part); off += 4;
+        GridUnsafe.putLong(data, off, init); off += 8;
+        GridUnsafe.putLong(data, off, updatesCnt);
+    }
+
+    /**
+     * Clears message.
+     */
+    public void clear() {
+        size = 0;
+    }
+
+    /**
+     * Check if there is enough space is allocated.
+     *
+     * @param newSize Size to ensure.
+     */
+    private void ensureSpace(int newSize) {
+        int req = newSize * ITEM_SIZE;
+
+        if (data.length < req)
+            data = Arrays.copyOf(data, data.length << 1);
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean writeTo(ByteBuffer buf, MessageWriter writer) {
+        writer.setBuffer(buf);
+
+        if (!writer.isHeaderWritten()) {
+            if (!writer.writeHeader(directType(), fieldsCount()))
+                return false;
+
+            writer.onHeaderWritten();
+        }
+
+        switch (writer.state()) {
+            case 0:
+                if (!writer.writeInt("cacheId", cacheId))
+                    return false;
+
+                writer.incrementState();
+
+            case 1:
+                if (!writer.writeByteArray("data", data, 0, size * ITEM_SIZE))
+                    return false;
+
+                writer.incrementState();
+
+        }
+
+        return true;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean readFrom(ByteBuffer buf, MessageReader reader) {
+        reader.setBuffer(buf);
+
+        if (!reader.beforeMessageRead())
+            return false;
+
+        switch (reader.state()) {
+            case 0:
+                cacheId = reader.readInt("cacheId");
+
+                if (!reader.isLastRead())
+                    return false;
+
+                reader.incrementState();
+
+            case 1:
+                data = reader.readByteArray("data");
+
+                if (!reader.isLastRead())
+                    return false;
+
+                size = data.length / ITEM_SIZE;
+
+                reader.incrementState();
+
+        }
+
+        return reader.afterMessageRead(PartitionUpdateCountersMessage.class);
+    }
+
+    /** {@inheritDoc} */
+    @Override public short directType() {
+        return 157;
+    }
+
+    /** {@inheritDoc} */
+    @Override public byte fieldsCount() {
+        return 1;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void onAckReceived() {
+        // No-op.
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        StringBuilder sb = new StringBuilder();
+
+        for (int i = 0; i < size; i++) {
+            sb.append("[part=")
+                .append(partition(i))
+                .append(", initCntr=")
+                .append(initialCounter(i))
+                .append(", cntr=")
+                .append(updatesCount(i))
+                .append(']');
+        }
+
+        return "PartitionUpdateCountersMessage{" +
+            "cacheId=" + cacheId +
+            ", size=" + size +
+            ", cntrs=" + sb +
+            '}';
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxFinishFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxFinishFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxFinishFuture.java
index cea3030..4a4d8e3 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxFinishFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxFinishFuture.java
@@ -947,6 +947,7 @@ public final class GridNearTxFinishFuture<K, V> extends GridCacheCompoundIdentit
             tx.activeCachesDeploymentEnabled(),
             !waitRemoteTxs && (tx.needReturnValue() && tx.implicit()),
             waitRemoteTxs,
+            null,
             null);
 
         finishReq.checkCommitted(true);

http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxLocal.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxLocal.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxLocal.java
index d03d0d3..b8c78bd 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxLocal.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxLocal.java
@@ -64,6 +64,7 @@ import org.apache.ignite.internal.processors.cache.dr.GridCacheDrInfo;
 import org.apache.ignite.internal.processors.cache.mvcc.MvccQueryTracker;
 import org.apache.ignite.internal.processors.cache.mvcc.MvccQueryTrackerImpl;
 import org.apache.ignite.internal.processors.cache.mvcc.MvccSnapshot;
+import org.apache.ignite.internal.processors.cache.mvcc.MvccUtils;
 import org.apache.ignite.internal.processors.cache.transactions.IgniteInternalTx;
 import org.apache.ignite.internal.processors.cache.transactions.IgniteTxEntry;
 import org.apache.ignite.internal.processors.cache.transactions.IgniteTxKey;
@@ -1862,8 +1863,14 @@ public class GridNearTxLocal extends GridDhtTxLocalAdapter implements GridTimeou
                 assert mvccSnapshot != null;
                 assert res != null;
 
-                if (res > 0)
+                if (res > 0) {
+                    if (mvccSnapshot.operationCounter() == ~MvccUtils.MVCC_OP_COUNTER_MASK) {
+                        throw new IgniteCheckedException("The maximum limit of the number of statements allowed in" +
+                            " one transaction is reached. [max=" + mvccSnapshot.operationCounter() + ']');
+                    }
+
                     mvccSnapshot.incrementOperationCounter();
+                }
 
                 return res;
             }

http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxQueryEnlistResponse.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxQueryEnlistResponse.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxQueryEnlistResponse.java
index 39e33c4..dae1e81 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxQueryEnlistResponse.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxQueryEnlistResponse.java
@@ -18,7 +18,12 @@
 package org.apache.ignite.internal.processors.cache.distributed.near;
 
 import java.nio.ByteBuffer;
+import java.util.Collection;
+import java.util.Set;
+import java.util.UUID;
+
 import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.internal.GridDirectCollection;
 import org.apache.ignite.internal.GridDirectTransient;
 import org.apache.ignite.internal.processors.cache.GridCacheIdMessage;
 import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
@@ -27,6 +32,7 @@ import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
 import org.apache.ignite.internal.util.typedef.internal.S;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.lang.IgniteUuid;
+import org.apache.ignite.plugin.extensions.communication.MessageCollectionItemType;
 import org.apache.ignite.plugin.extensions.communication.MessageReader;
 import org.apache.ignite.plugin.extensions.communication.MessageWriter;
 import org.jetbrains.annotations.Nullable;
@@ -60,6 +66,10 @@ public class GridNearTxQueryEnlistResponse extends GridCacheIdMessage implements
     /** */
     private GridCacheVersion lockVer;
 
+    /** New DHT nodes involved into transaction. */
+    @GridDirectCollection(UUID.class)
+    private Collection<UUID> newDhtNodes;
+
     /**
      * Default constructor.
      */
@@ -90,13 +100,15 @@ public class GridNearTxQueryEnlistResponse extends GridCacheIdMessage implements
      * @param res Result.
      * @param removeMapping Remove mapping flag.
      */
-    public GridNearTxQueryEnlistResponse(int cacheId, IgniteUuid futId, int miniId, GridCacheVersion lockVer, long res, boolean removeMapping) {
+    public GridNearTxQueryEnlistResponse(int cacheId, IgniteUuid futId, int miniId, GridCacheVersion lockVer, long res,
+        boolean removeMapping, Set<UUID> newDhtNodes) {
         this.cacheId = cacheId;
         this.futId = futId;
         this.miniId = miniId;
         this.lockVer = lockVer;
         this.res = res;
         this.removeMapping = removeMapping;
+        this.newDhtNodes = newDhtNodes;
     }
 
     /**
@@ -128,6 +140,13 @@ public class GridNearTxQueryEnlistResponse extends GridCacheIdMessage implements
     }
 
     /**
+     * @return New DHT nodes involved into transaction.
+     */
+    public Collection<UUID> newDhtNodes() {
+        return newDhtNodes;
+    }
+
+    /**
      * @return Remove mapping flag.
      */
     public boolean removeMapping() {
@@ -146,7 +165,7 @@ public class GridNearTxQueryEnlistResponse extends GridCacheIdMessage implements
 
     /** {@inheritDoc} */
     @Override public byte fieldsCount() {
-        return 9;
+        return 10;
     }
 
     /** {@inheritDoc} */
@@ -200,6 +219,11 @@ public class GridNearTxQueryEnlistResponse extends GridCacheIdMessage implements
 
                 writer.incrementState();
 
+            case 9:
+                if (!writer.writeCollection("newDhtNodes", newDhtNodes, MessageCollectionItemType.UUID))
+                    return false;
+
+                writer.incrementState();
         }
 
         return true;
@@ -264,6 +288,13 @@ public class GridNearTxQueryEnlistResponse extends GridCacheIdMessage implements
 
                 reader.incrementState();
 
+            case 9:
+                newDhtNodes = reader.readCollection("newDhtNodes", MessageCollectionItemType.UUID);
+
+                if (!reader.isLastRead())
+                    return false;
+
+                reader.incrementState();
         }
 
         return reader.afterMessageRead(GridNearTxQueryEnlistResponse.class);

http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxQueryResultsEnlistFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxQueryResultsEnlistFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxQueryResultsEnlistFuture.java
index 910deb9..2452b92 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxQueryResultsEnlistFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxQueryResultsEnlistFuture.java
@@ -42,7 +42,6 @@ import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
 import org.apache.ignite.internal.processors.query.EnlistOperation;
 import org.apache.ignite.internal.processors.query.UpdateSourceIterator;
 import org.apache.ignite.internal.transactions.IgniteTxRollbackCheckedException;
-import org.apache.ignite.internal.util.GridLongList;
 import org.apache.ignite.internal.util.tostring.GridToStringExclude;
 import org.apache.ignite.internal.util.typedef.CI1;
 import org.apache.ignite.internal.util.typedef.F;
@@ -302,15 +301,13 @@ public class GridNearTxQueryResultsEnlistFuture extends GridNearTxAbstractEnlist
     }
 
     /**
-     *
      * @param primaryId Primary node id.
      * @param rows Rows.
      * @param dhtVer Dht version assigned at primary node.
      * @param dhtFutId Dht future id assigned at primary node.
-     * @param updCntrs Update counters.
      */
     private void processBatchLocalBackupKeys(UUID primaryId, List<Object> rows, GridCacheVersion dhtVer,
-        IgniteUuid dhtFutId, GridLongList updCntrs) {
+        IgniteUuid dhtFutId) {
         assert dhtVer != null;
         assert dhtFutId != null;
 
@@ -366,7 +363,7 @@ public class GridNearTxQueryResultsEnlistFuture extends GridNearTxAbstractEnlist
                 }
             }
 
-            dhtTx.mvccEnlistBatch(cctx, it.operation(), keys, vals, mvccSnapshot.withoutActiveTransactions(), updCntrs);
+            dhtTx.mvccEnlistBatch(cctx, it.operation(), keys, vals, mvccSnapshot.withoutActiveTransactions());
         }
         catch (IgniteCheckedException e) {
             onDone(e);
@@ -507,8 +504,7 @@ public class GridNearTxQueryResultsEnlistFuture extends GridNearTxAbstractEnlist
             Batch batch = batches.get(nodeId);
 
             if (batch != null && !F.isEmpty(batch.localBackupRows()) && res.dhtFutureId() != null)
-                processBatchLocalBackupKeys(nodeId, batch.localBackupRows(), res.dhtVersion(), res.dhtFutureId(),
-                    res.updateCounters());
+                processBatchLocalBackupKeys(nodeId, batch.localBackupRows(), res.dhtVersion(), res.dhtFutureId());
             else
                 sendNextBatches(nodeId);
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxQueryResultsEnlistResponse.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxQueryResultsEnlistResponse.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxQueryResultsEnlistResponse.java
index 749afd3..94cacfa 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxQueryResultsEnlistResponse.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxQueryResultsEnlistResponse.java
@@ -18,8 +18,9 @@
 package org.apache.ignite.internal.processors.cache.distributed.near;
 
 import java.nio.ByteBuffer;
+import java.util.Set;
+import java.util.UUID;
 import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
-import org.apache.ignite.internal.util.GridLongList;
 import org.apache.ignite.internal.util.typedef.internal.S;
 import org.apache.ignite.lang.IgniteUuid;
 import org.apache.ignite.plugin.extensions.communication.MessageReader;
@@ -38,9 +39,6 @@ public class GridNearTxQueryResultsEnlistResponse extends GridNearTxQueryEnlistR
     /** */
     private IgniteUuid dhtFutId;
 
-    /** */
-    private GridLongList updCntrs;
-
     /**
      * Default-constructor.
      */
@@ -56,7 +54,7 @@ public class GridNearTxQueryResultsEnlistResponse extends GridNearTxQueryEnlistR
      * @param res Result.
      * @param dhtFutId Dht future id.
      * @param dhtVer Dht version.
-     * @param updCntrs Update counters.
+     * @param newDhtNodes New
      */
     public GridNearTxQueryResultsEnlistResponse(int cacheId,
         IgniteUuid futId,
@@ -65,12 +63,11 @@ public class GridNearTxQueryResultsEnlistResponse extends GridNearTxQueryEnlistR
         long res,
         GridCacheVersion dhtVer,
         IgniteUuid dhtFutId,
-        GridLongList updCntrs) {
-        super(cacheId, futId, miniId, lockVer, res, false);
+        Set<UUID> newDhtNodes) {
+        super(cacheId, futId, miniId, lockVer, res, false, newDhtNodes);
 
         this.dhtVer = dhtVer;
         this.dhtFutId = dhtFutId;
-        this.updCntrs = updCntrs;
     }
 
     /**
@@ -102,12 +99,6 @@ public class GridNearTxQueryResultsEnlistResponse extends GridNearTxQueryEnlistR
         return dhtFutId;
     }
 
-    /**
-     * @return Update counters.
-     */
-    public GridLongList updateCounters() {
-        return updCntrs;
-    }
 
     /** {@inheritDoc} */
     @Override public byte fieldsCount() {
@@ -129,20 +120,14 @@ public class GridNearTxQueryResultsEnlistResponse extends GridNearTxQueryEnlistR
         }
 
         switch (writer.state()) {
-            case 9:
-                if (!writer.writeIgniteUuid("dhtFutId", dhtFutId))
-                    return false;
-
-                writer.incrementState();
-
             case 10:
-                if (!writer.writeMessage("dhtVer", dhtVer))
+                if (!writer.writeIgniteUuid("dhtFutId", dhtFutId))
                     return false;
 
                 writer.incrementState();
 
             case 11:
-                if (!writer.writeMessage("updCntrs", updCntrs))
+                if (!writer.writeMessage("dhtVer", dhtVer))
                     return false;
 
                 writer.incrementState();
@@ -162,16 +147,8 @@ public class GridNearTxQueryResultsEnlistResponse extends GridNearTxQueryEnlistR
             return false;
 
         switch (reader.state()) {
-            case 9:
-                dhtFutId = reader.readIgniteUuid("dhtFutId");
-
-                if (!reader.isLastRead())
-                    return false;
-
-                reader.incrementState();
-
             case 10:
-                dhtVer = reader.readMessage("dhtVer");
+                dhtFutId = reader.readIgniteUuid("dhtFutId");
 
                 if (!reader.isLastRead())
                     return false;
@@ -179,7 +156,7 @@ public class GridNearTxQueryResultsEnlistResponse extends GridNearTxQueryEnlistR
                 reader.incrementState();
 
             case 11:
-                updCntrs = reader.readMessage("updCntrs");
+                dhtVer = reader.readMessage("dhtVer");
 
                 if (!reader.isLastRead())
                     return false;

http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/mvcc/MvccProcessorImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/mvcc/MvccProcessorImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/mvcc/MvccProcessorImpl.java
index 5df9bb1..f59220b 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/mvcc/MvccProcessorImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/mvcc/MvccProcessorImpl.java
@@ -118,6 +118,7 @@ import static org.apache.ignite.internal.processors.cache.distributed.dht.GridDh
 import static org.apache.ignite.internal.processors.cache.mvcc.MvccQueryTracker.MVCC_TRACKER_ID_NA;
 import static org.apache.ignite.internal.processors.cache.mvcc.MvccUtils.MVCC_COUNTER_NA;
 import static org.apache.ignite.internal.processors.cache.mvcc.MvccUtils.MVCC_CRD_COUNTER_NA;
+import static org.apache.ignite.internal.processors.cache.mvcc.MvccUtils.MVCC_HINTS_BIT_OFF;
 import static org.apache.ignite.internal.processors.cache.mvcc.MvccUtils.MVCC_INITIAL_CNTR;
 import static org.apache.ignite.internal.processors.cache.mvcc.MvccUtils.MVCC_READ_OP_CNTR;
 import static org.apache.ignite.internal.processors.cache.mvcc.MvccUtils.MVCC_START_CNTR;
@@ -1084,7 +1085,8 @@ public class MvccProcessorImpl extends GridProcessorAdapter implements MvccProce
             }
 
             if (workers == null) {
-                U.warn(log, "Attempting to stop inactive vacuum.");
+                if (log.isInfoEnabled())
+                    log.info("Attempting to stop inactive vacuum.");
 
                 return;
             }
@@ -2223,9 +2225,9 @@ public class MvccProcessorImpl extends GridProcessorAdapter implements MvccProce
             return compare(row, snapshot.coordinatorVersion(), snapshot.cleanupVersion()) <= 0
                 && hasNewVersion(row) && MvccUtils.compareNewVersion(row, snapshot.coordinatorVersion(), snapshot.cleanupVersion()) <= 0
                 && MvccUtils.state(cctx, row.newMvccCoordinatorVersion(), row.newMvccCounter(),
-                row.newMvccOperationCounter() | (row.newMvccTxState() << PageIO.MVCC_HINTS_BIT_OFF)) == TxState.COMMITTED
+                row.newMvccOperationCounter() | (row.newMvccTxState() << MVCC_HINTS_BIT_OFF)) == TxState.COMMITTED
                 || MvccUtils.state(cctx, row.mvccCoordinatorVersion(), row.mvccCounter(),
-                row.mvccOperationCounter() | (row.mvccTxState() << PageIO.MVCC_HINTS_BIT_OFF)) == TxState.ABORTED;
+                row.mvccOperationCounter() | (row.mvccTxState() << MVCC_HINTS_BIT_OFF)) == TxState.ABORTED;
         }
 
         /** */

http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/mvcc/MvccUpdateVersionAware.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/mvcc/MvccUpdateVersionAware.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/mvcc/MvccUpdateVersionAware.java
index 17804c4..fee928e 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/mvcc/MvccUpdateVersionAware.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/mvcc/MvccUpdateVersionAware.java
@@ -73,4 +73,9 @@ public interface MvccUpdateVersionAware {
     public default MvccVersion newMvccVersion() {
         return new MvccVersionImpl(newMvccCoordinatorVersion(), newMvccCounter(), newMvccOperationCounter());
     }
+
+    /**
+     * @return {@code True} if this key was inserted in the cache with this row in the same transaction.
+     */
+    public boolean isKeyAbsentBefore();
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/mvcc/MvccUtils.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/mvcc/MvccUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/mvcc/MvccUtils.java
index c3f9a6d..896c9aa 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/mvcc/MvccUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/mvcc/MvccUtils.java
@@ -44,8 +44,6 @@ import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
 import static org.apache.ignite.internal.pagemem.PageIdUtils.itemId;
 import static org.apache.ignite.internal.pagemem.PageIdUtils.pageId;
 import static org.apache.ignite.internal.processors.cache.persistence.tree.io.DataPageIO.MVCC_INFO_SIZE;
-import static org.apache.ignite.internal.processors.cache.persistence.tree.io.PageIO.MVCC_HINTS_BIT_OFF;
-import static org.apache.ignite.internal.processors.cache.persistence.tree.io.PageIO.MVCC_HINTS_MASK;
 import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.TRANSACTION_COMPLETED;
 import static org.apache.ignite.transactions.TransactionConcurrency.PESSIMISTIC;
 import static org.apache.ignite.transactions.TransactionIsolation.REPEATABLE_READ;
@@ -55,26 +53,50 @@ import static org.apache.ignite.transactions.TransactionIsolation.REPEATABLE_REA
  */
 public class MvccUtils {
     /** */
+    public static final int MVCC_KEY_ABSENT_BEFORE_OFF = 29;
+
+    /** */
+    public static final int MVCC_KEY_ABSENT_BEFORE_MASK = 0b0001 << MVCC_KEY_ABSENT_BEFORE_OFF;
+
+    /** */
+    public static final int MVCC_HINTS_BIT_OFF = MVCC_KEY_ABSENT_BEFORE_OFF + 1;
+
+    /** */
+    public static final int MVCC_HINTS_MASK = 0b0011 << MVCC_HINTS_BIT_OFF;
+
+    /** Mask for all masked high bits in operation counter field. */
+    public static final int MVCC_OP_COUNTER_MASK = 0b0111 << MVCC_KEY_ABSENT_BEFORE_OFF;
+
+    /** */
     public static final long MVCC_CRD_COUNTER_NA = 0L;
+
     /** */
     public static final long MVCC_CRD_START_CNTR = 1L;
+
     /** */
     public static final long MVCC_COUNTER_NA = 0L;
+
     /** */
     public static final long MVCC_INITIAL_CNTR = 1L;
+
     /** */
     public static final long MVCC_START_CNTR = 3L;
+
     /** */
     public static final int MVCC_OP_COUNTER_NA = 0;
+
     /** */
     public static final int MVCC_START_OP_CNTR = 1;
+
     /** */
     public static final int MVCC_READ_OP_CNTR = ~MVCC_HINTS_MASK;
 
     /** */
     public static final int MVCC_INVISIBLE = 0;
+
     /** */
     public static final int MVCC_VISIBLE_REMOVED = 1;
+
     /** */
     public static final int MVCC_VISIBLE = 2;
 
@@ -559,13 +581,13 @@ public class MvccUtils {
 
                 long mvccCrd = dataIo.mvccCoordinator(pageAddr, offset);
                 long mvccCntr = dataIo.mvccCounter(pageAddr, offset);
-                int mvccOpCntr = dataIo.mvccOperationCounter(pageAddr, offset);
+                int mvccOpCntr = dataIo.mvccOperationCounter(pageAddr, offset) & ~MVCC_KEY_ABSENT_BEFORE_MASK;
 
                 assert mvccVersionIsValid(mvccCrd, mvccCntr, mvccOpCntr) : mvccVersion(mvccCrd, mvccCntr, mvccOpCntr);
 
                 long newMvccCrd = dataIo.newMvccCoordinator(pageAddr, offset);
                 long newMvccCntr = dataIo.newMvccCounter(pageAddr, offset);
-                int newMvccOpCntr = dataIo.newMvccOperationCounter(pageAddr, offset);
+                int newMvccOpCntr = dataIo.newMvccOperationCounter(pageAddr, offset) & ~MVCC_KEY_ABSENT_BEFORE_MASK;
 
                 assert newMvccCrd == MVCC_CRD_COUNTER_NA || mvccVersionIsValid(newMvccCrd, newMvccCntr, newMvccOpCntr)
                     : mvccVersion(newMvccCrd, newMvccCntr, newMvccOpCntr);

http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/CacheDataRowAdapter.java
----------------------------------------------------------------------
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 b8245df..574e6d5 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
@@ -661,6 +661,11 @@ public class CacheDataRowAdapter implements CacheDataRow {
         return TxState.NA;
     }
 
+    /** {@inheritDoc} */
+    @Override public boolean isKeyAbsentBefore() {
+        return false;
+    }
+
     /**
      *
      */

http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheOffheapManager.java
----------------------------------------------------------------------
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 04476ad..90099cf 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
@@ -1181,6 +1181,11 @@ public class GridCacheOffheapManager extends IgniteCacheOffheapManagerImpl imple
         @Override public byte newMvccTxState() {
             return 0; // TODO IGNITE-7384
         }
+
+        /** {@inheritDoc} */
+        @Override public boolean isKeyAbsentBefore() {
+            return false;
+        }
     }
 
     /**
@@ -1588,11 +1593,11 @@ public class GridCacheOffheapManager extends IgniteCacheOffheapManagerImpl imple
         }
 
         /** {@inheritDoc} */
-        @Override public long nextMvccUpdateCounter() {
+        @Override public long getAndIncrementUpdateCounter(long delta) {
             try {
                 CacheDataStore delegate0 = init0(true);
 
-                return delegate0 == null ? 0 : delegate0.nextMvccUpdateCounter();
+                return delegate0 == null ? 0 : delegate0.getAndIncrementUpdateCounter(delta);
             }
             catch (IgniteCheckedException e) {
                 throw new IgniteException(e);
@@ -1600,11 +1605,17 @@ public class GridCacheOffheapManager extends IgniteCacheOffheapManagerImpl imple
         }
 
         /** {@inheritDoc} */
-        @Override public long mvccUpdateCounter() {
+        @Override public void init(long size, long updCntr, @Nullable Map<Integer, Long> cacheSizes) {
+            throw new IllegalStateException("Should be never called.");
+        }
+
+        /** {@inheritDoc} */
+        @Override public void updateCounter(long val) {
             try {
-                CacheDataStore delegate0 = init0(true);
+                CacheDataStore delegate0 = init0(false);
 
-                return delegate0 == null ? 0 : delegate0.mvccUpdateCounter();
+                if (delegate0 != null)
+                    delegate0.updateCounter(val);
             }
             catch (IgniteCheckedException e) {
                 throw new IgniteException(e);
@@ -1612,17 +1623,12 @@ public class GridCacheOffheapManager extends IgniteCacheOffheapManagerImpl imple
         }
 
         /** {@inheritDoc} */
-        @Override public void init(long size, long updCntr, @Nullable Map<Integer, Long> cacheSizes) {
-            throw new IllegalStateException("Should be never called.");
-        }
-
-        /** {@inheritDoc} */
-        @Override public void updateCounter(long val) {
+        @Override public void updateCounter(long start, long delta) {
             try {
                 CacheDataStore delegate0 = init0(false);
 
                 if (delegate0 != null)
-                    delegate0.updateCounter(val);
+                    delegate0.updateCounter(start, delta);
             }
             catch (IgniteCheckedException e) {
                 throw new IgniteException(e);

http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/io/DataPageIO.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/io/DataPageIO.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/io/DataPageIO.java
index 87e37f6..95a46eb 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/io/DataPageIO.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/io/DataPageIO.java
@@ -27,6 +27,9 @@ import org.apache.ignite.internal.processors.cache.persistence.CacheDataRow;
 import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
 import org.apache.ignite.internal.util.GridStringBuilder;
 
+import static org.apache.ignite.internal.processors.cache.mvcc.MvccUtils.MVCC_HINTS_BIT_OFF;
+import static org.apache.ignite.internal.processors.cache.mvcc.MvccUtils.MVCC_HINTS_MASK;
+import static org.apache.ignite.internal.processors.cache.mvcc.MvccUtils.MVCC_KEY_ABSENT_BEFORE_OFF;
 import static org.apache.ignite.internal.processors.cache.persistence.tree.io.DataPageIO.EntryPart.CACHE_ID;
 import static org.apache.ignite.internal.processors.cache.persistence.tree.io.DataPageIO.EntryPart.EXPIRE_TIME;
 import static org.apache.ignite.internal.processors.cache.persistence.tree.io.DataPageIO.EntryPart.KEY;
@@ -71,7 +74,8 @@ public class DataPageIO extends AbstractDataPageIO<CacheDataRow> {
                 // xid_min.
                 PageUtils.putLong(addr, 0, row.mvccCoordinatorVersion());
                 PageUtils.putLong(addr, 8, row.mvccCounter());
-                PageUtils.putInt(addr, 16, row.mvccOperationCounter() | (row.mvccTxState() << MVCC_HINTS_BIT_OFF));
+                PageUtils.putInt(addr, 16, row.mvccOperationCounter() | (row.mvccTxState() << MVCC_HINTS_BIT_OFF) |
+                    ((row.isKeyAbsentBefore() ? 1 : 0) << MVCC_KEY_ABSENT_BEFORE_OFF));
 
                 assert row.newMvccCoordinatorVersion() == 0
                     || MvccUtils.mvccVersionIsValid(row.newMvccCoordinatorVersion(), row.newMvccCounter(), row.newMvccOperationCounter());
@@ -79,7 +83,8 @@ public class DataPageIO extends AbstractDataPageIO<CacheDataRow> {
                 // xid_max.
                 PageUtils.putLong(addr, 20, row.newMvccCoordinatorVersion());
                 PageUtils.putLong(addr, 28, row.newMvccCounter());
-                PageUtils.putInt(addr, 36, row.newMvccOperationCounter() | (row.newMvccTxState() << MVCC_HINTS_BIT_OFF));
+                PageUtils.putInt(addr, 36, row.newMvccOperationCounter() | (row.newMvccTxState() << MVCC_HINTS_BIT_OFF) |
+                    ((row.isKeyAbsentBefore() ? 1 : 0) << MVCC_KEY_ABSENT_BEFORE_OFF));
 
                 addr += mvccInfoSize;
             }
@@ -211,10 +216,12 @@ public class DataPageIO extends AbstractDataPageIO<CacheDataRow> {
             writeMvccInfoFragment(buf,
                 row.mvccCoordinatorVersion(),
                 row.mvccCounter(),
-                row.mvccOperationCounter() | (row.mvccTxState() << MVCC_HINTS_BIT_OFF),
+                row.mvccOperationCounter() | (row.mvccTxState() << MVCC_HINTS_BIT_OFF) |
+                    ((row.isKeyAbsentBefore() ? 1 : 0) << MVCC_KEY_ABSENT_BEFORE_OFF),
                 row.newMvccCoordinatorVersion(),
                 row.newMvccCounter(),
-                row.newMvccOperationCounter() | (row.newMvccTxState() << MVCC_HINTS_BIT_OFF),
+                row.newMvccOperationCounter() | (row.newMvccTxState() << MVCC_HINTS_BIT_OFF) |
+                    ((row.isKeyAbsentBefore() ? 1 : 0) << MVCC_KEY_ABSENT_BEFORE_OFF),
                 len);
         else if (type != VERSION) {
             // Write key or value.

http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/io/PageIO.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/io/PageIO.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/io/PageIO.java
index f167d0c..22d2420 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/io/PageIO.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/io/PageIO.java
@@ -147,12 +147,6 @@ public abstract class PageIO {
     /** */
     public static final int COMMON_HEADER_END = RESERVED_3_OFF + 8; // 40=type(2)+ver(2)+crc(4)+pageId(8)+rotatedIdPart(1)+reserved(1+2+4+2*8)
 
-    /** */
-    public static final int MVCC_HINTS_MASK = 0xC0000000;
-
-    /** */
-    public static final int MVCC_HINTS_BIT_OFF = 30;
-
     /* All the page types. */
 
     /** */

http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxAdapter.java
index c6d1991..357b992 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxAdapter.java
@@ -2033,9 +2033,9 @@ public abstract class IgniteTxAdapter extends GridMetadataAwareAdapter implement
     }
 
     /**
-     * Make counters accumulated during transaction visible outside of transaciton.
+     * Makes cache sizes changes accumulated during transaction visible outside of transaction.
      */
-    protected void applyTxCounters() {
+    protected void applyTxSizes() {
         TxCounters txCntrs = txCounters(false);
 
         if (txCntrs == null)

http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxHandler.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxHandler.java
index 32f4dd4..8655caa 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
@@ -1129,6 +1129,9 @@ public class IgniteTxHandler {
             nearTx = !F.isEmpty(req.nearWrites()) ? startNearRemoteTx(ctx.deploy().globalLoader(), nodeId, req) : null;
             dhtTx = startRemoteTx(nodeId, req, res);
 
+            if (dhtTx != null && req.updateCounters() != null) // Remember update counters on prepare state.
+                dhtTx.txCounters(true).updateCounters(req.updateCounters());
+
             // Set evicted keys from near transaction.
             if (nearTx != null)
                 res.nearEvicted(nearTx.evicted());
@@ -1372,9 +1375,14 @@ public class IgniteTxHandler {
 
             return;
         }
-        else if (log.isDebugEnabled())
-            log.debug("Received finish request for transaction [senderNodeId=" + nodeId + ", req=" + req +
-                ", tx=" + tx + ']');
+        else {
+            if (req.updateCounters() != null)
+                tx.txCounters(true).updateCounters(req.updateCounters());
+
+            if (log.isDebugEnabled())
+                log.debug("Received finish request for transaction [senderNodeId=" + nodeId + ", req=" + req +
+                    ", tx=" + tx + ']');
+        }
 
         req.txState(tx.txState());
 
@@ -1391,8 +1399,6 @@ public class IgniteTxHandler {
                 tx.setPartitionUpdateCounters(
                     req.partUpdateCounters() != null ? req.partUpdateCounters().array() : null);
 
-                tx.txCounters(true).updateCounters(req.updateCounters());
-
                 tx.commitRemoteTx();
             }
             else {

http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java
index bfe67ee..8354c8b 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java
@@ -18,13 +18,15 @@
 package org.apache.ignite.internal.processors.cache.transactions;
 
 import java.io.Externalizable;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
 import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
+import java.util.concurrent.atomic.AtomicLong;
 import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
 import javax.cache.expiry.Duration;
 import javax.cache.expiry.ExpiryPolicy;
@@ -57,7 +59,9 @@ import org.apache.ignite.internal.processors.cache.GridCacheUpdateTxResult;
 import org.apache.ignite.internal.processors.cache.IgniteCacheExpiryPolicy;
 import org.apache.ignite.internal.processors.cache.KeyCacheObject;
 import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtLocalPartition;
-import org.apache.ignite.internal.processors.cache.distributed.dht.PartitionUpdateCounters;
+import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtPartitionState;
+import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtPartitionTopology;
+import org.apache.ignite.internal.processors.cache.distributed.dht.PartitionUpdateCountersMessage;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxLocal;
 import org.apache.ignite.internal.processors.cache.mvcc.MvccSnapshot;
 import org.apache.ignite.internal.processors.cache.persistence.StorageException;
@@ -442,6 +446,8 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter implements Ig
 
         try {
             cctx.tm().prepareTx(this, entries);
+
+            calculatePartitionUpdateCounters();
         }
         catch (IgniteCheckedException e) {
             throw e;
@@ -457,6 +463,64 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter implements Ig
     }
 
     /**
+     * Calculates partition update counters for current transaction. Each partition will be supplied with
+     * pair (init, delta) values, where init - initial update counter, and delta - updates count made
+     * by current transaction for a given partition.
+     */
+    private void calculatePartitionUpdateCounters() {
+        TxCounters counters = txCounters(false);
+
+        if (counters != null && F.isEmpty(counters.updateCounters())) {
+            List<PartitionUpdateCountersMessage> cntrMsgs = new ArrayList<>();
+
+            for (Map.Entry<Integer, Map<Integer, AtomicLong>> record : counters.accumulatedUpdateCounters().entrySet()) {
+                int cacheId = record.getKey();
+
+                Map<Integer, AtomicLong> partToCntrs = record.getValue();
+
+                assert partToCntrs != null;
+
+                if (F.isEmpty(partToCntrs))
+                    continue;
+
+                PartitionUpdateCountersMessage msg = new PartitionUpdateCountersMessage(cacheId, partToCntrs.size());
+                GridCacheContext ctx0 = cctx.cacheContext(cacheId);
+
+                assert ctx0 != null && ctx0.mvccEnabled();
+
+                GridDhtPartitionTopology top = ctx0.topology();
+
+                assert top != null;
+
+                for (Map.Entry<Integer, AtomicLong> e : partToCntrs.entrySet()) {
+                    AtomicLong acc = e.getValue();
+
+                    assert acc != null;
+
+                    long cntr = acc.get();
+
+                    assert cntr >= 0;
+
+                    if (cntr != 0) {
+                        int p = e.getKey();
+
+                        GridDhtLocalPartition part = top.localPartition(p);
+
+                        assert part != null && part.state() == GridDhtPartitionState.OWNING;
+
+                        msg.add(p, part.getAndIncrementUpdateCounter(cntr), cntr);
+                    }
+                }
+
+                if (msg.size() > 0)
+                    cntrMsgs.add(msg);
+            }
+
+            counters.updateCounters(cntrMsgs);
+        }
+    }
+
+    /**
      * Checks that locks are in proper state for commit.
      *
      * @param entry Cache entry to check.
@@ -913,7 +977,8 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter implements Ig
                     }
                 }
 
-                applyTxCounters();
+                // Apply cache sizes only for primary nodes. Update counters were applied on prepare state.
+                applyTxSizes();
 
                 if (ptr != null && !cctx.tm().logTxRecords())
                     cctx.wal().flush(ptr, false);
@@ -1644,45 +1709,6 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter implements Ig
     }
 
     /**
-     * Merges mvcc update counters to the partition update counters. For mvcc transactions we update partitions
-     * counters only on commit phase.
-     */
-    private Map<Integer, PartitionUpdateCounters> applyAndCollectLocalUpdateCounters() {
-        if (F.isEmpty(txState.touchedPartitions()))
-            return null;
-
-        HashMap<Integer, PartitionUpdateCounters> updCntrs = new HashMap<>();
-
-        for (Map.Entry<Integer, Set<Integer>> entry : txState.touchedPartitions().entrySet()) {
-            Integer cacheId = entry.getKey();
-
-            Set<Integer> parts = entry.getValue();
-
-            assert !F.isEmpty(parts);
-
-            GridCacheContext ctx0 = cctx.cacheContext(cacheId);
-
-            Map<Integer, Long> partCntrs = new HashMap<>(parts.size());
-
-            for (Integer p : parts) {
-                GridDhtLocalPartition dhtPart = ctx0.topology().localPartition(p);
-
-                assert dhtPart != null;
-
-                long cntr = dhtPart.mvccUpdateCounter();
-
-                dhtPart.updateCounter(cntr);
-
-                partCntrs.put(p, cntr);
-            }
-
-            updCntrs.put(cacheId, new PartitionUpdateCounters(partCntrs));
-        }
-
-        return updCntrs;
-    }
-
-    /**
      * @return {@code True} if there are entries, enlisted by query.
      */
     public boolean queryEnlisted() {
@@ -1703,16 +1729,6 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter implements Ig
         }
     }
 
-    /** {@inheritDoc} */
-    @Override protected void applyTxCounters() {
-        super.applyTxCounters();
-
-        Map<Integer, PartitionUpdateCounters> updCntrs = applyAndCollectLocalUpdateCounters();
-
-        // remember counters for subsequent sending to backups
-        txCounters(true).updateCounters(updCntrs);
-    }
-
     /**
      * Post-lock closure alias.
      *

http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/TxCounters.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/TxCounters.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/TxCounters.java
index 2ad4f94..e1a0bd6 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/TxCounters.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/TxCounters.java
@@ -17,21 +17,25 @@
 
 package org.apache.ignite.internal.processors.cache.transactions;
 
-import java.util.Collections;
+import java.util.Collection;
+import java.util.HashMap;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.atomic.AtomicLong;
-import org.apache.ignite.internal.processors.cache.distributed.dht.PartitionUpdateCounters;
+import org.apache.ignite.internal.processors.cache.distributed.dht.PartitionUpdateCountersMessage;
 
 /**
  * Values which should be tracked during transaction execution and applied on commit.
  */
 public class TxCounters {
     /** Size changes for cache partitions made by transaction */
-    private final ConcurrentMap<Integer, ConcurrentMap<Integer, AtomicLong>> sizeDeltas = new ConcurrentHashMap<>();
-    /** Update counters for cache partitions in the end of transaction */
-    private Map<Integer, PartitionUpdateCounters> updCntrs;
+    private final Map<Integer, Map<Integer, AtomicLong>> sizeDeltas = new ConcurrentHashMap<>();
+
+    /** Per-partition update counter accumulator. */
+    private final Map<Integer, Map<Integer, AtomicLong>> updCntrsAcc = new HashMap<>();
+
+    /** Final update counters for cache partitions in the end of transaction */
+    private Collection<PartitionUpdateCountersMessage> updCntrs;
 
     /**
      * Accumulates size change for cache partition.
@@ -41,42 +45,85 @@ public class TxCounters {
      * @param delta Size delta.
      */
     public void accumulateSizeDelta(int cacheId, int part, long delta) {
-        ConcurrentMap<Integer, AtomicLong> partDeltas = sizeDeltas.get(cacheId);
-
-        if (partDeltas == null) {
-            ConcurrentMap<Integer, AtomicLong> partDeltas0 =
-                sizeDeltas.putIfAbsent(cacheId, partDeltas = new ConcurrentHashMap<>());
-
-            if (partDeltas0 != null)
-                partDeltas = partDeltas0;
-        }
-
-        AtomicLong accDelta = partDeltas.get(part);
-
-        if (accDelta == null) {
-            AtomicLong accDelta0 = partDeltas.putIfAbsent(part, accDelta = new AtomicLong());
-
-            if (accDelta0 != null)
-                accDelta = accDelta0;
-        }
+        AtomicLong accDelta = accumulator(sizeDeltas, cacheId, part);
 
         // here AtomicLong is used more as a container,
         // every instance is assumed to be accessed in thread-confined manner
         accDelta.set(accDelta.get() + delta);
     }
 
-    /** */
-    public void updateCounters(Map<Integer, PartitionUpdateCounters> updCntrs) {
+    /**
+     * @return Map of size changes for cache partitions made by transaction.
+     */
+    public Map<Integer, Map<Integer, AtomicLong>> sizeDeltas() {
+        return sizeDeltas;
+    }
+
+    /**
+     * @param updCntrs Final update counters.
+     */
+    public void updateCounters(Collection<PartitionUpdateCountersMessage> updCntrs) {
         this.updCntrs = updCntrs;
     }
 
-    /** */
-    public Map<Integer, PartitionUpdateCounters> updateCounters() {
-        return updCntrs != null ? Collections.unmodifiableMap(updCntrs) : Collections.emptyMap();
+    /**
+     * @return Final update counters.
+     */
+    public Collection<PartitionUpdateCountersMessage> updateCounters() {
+        return updCntrs;
     }
 
-    /** */
-    public Map<Integer, ? extends Map<Integer, AtomicLong>> sizeDeltas() {
-        return Collections.unmodifiableMap(sizeDeltas);
+    /**
+     * @return Accumulated update counters.
+     */
+    public Map<Integer, Map<Integer, AtomicLong>> accumulatedUpdateCounters() {
+        return updCntrsAcc;
+    }
+
+    /**
+     * @param cacheId Cache id.
+     * @param part Partition number.
+     */
+    public void incrementUpdateCounter(int cacheId, int part) {
+        accumulator(updCntrsAcc, cacheId, part).incrementAndGet();
+    }
+
+    /**
+     * @param cacheId Cache id.
+     * @param part Partition number.
+     */
+    public void decrementUpdateCounter(int cacheId, int part) {
+        long acc = accumulator(updCntrsAcc, cacheId, part).decrementAndGet();
+
+        assert acc >= 0;
+    }
+
+    /**
+     * @param accMap Map to obtain accumulator from.
+     * @param cacheId Cache id.
+     * @param part Partition number.
+     * @return Accumulator.
+     */
+    private AtomicLong accumulator(Map<Integer, Map<Integer, AtomicLong>> accMap, int cacheId, int part) {
+        Map<Integer, AtomicLong> cacheAccs = accMap.get(cacheId);
+
+        if (cacheAccs == null) {
+            Map<Integer, AtomicLong> cacheAccs0 =
+                accMap.putIfAbsent(cacheId, cacheAccs = new ConcurrentHashMap<>());
+
+            if (cacheAccs0 != null)
+                cacheAccs = cacheAccs0;
+        }
+
+        AtomicLong acc = cacheAccs.get(part);
+
+        if (acc == null) {
+            AtomicLong accDelta0 = cacheAccs.putIfAbsent(part, acc = new AtomicLong());
+
+            if (accDelta0 != null)
+                acc = accDelta0;
+        }
+
+        return acc;
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/tree/mvcc/data/MvccDataRow.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/tree/mvcc/data/MvccDataRow.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/tree/mvcc/data/MvccDataRow.java
index fc98452..9ded71f 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/tree/mvcc/data/MvccDataRow.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/tree/mvcc/data/MvccDataRow.java
@@ -33,10 +33,12 @@ import org.apache.ignite.internal.util.typedef.internal.S;
 
 import static org.apache.ignite.internal.processors.cache.mvcc.MvccUtils.MVCC_COUNTER_NA;
 import static org.apache.ignite.internal.processors.cache.mvcc.MvccUtils.MVCC_CRD_COUNTER_NA;
+import static org.apache.ignite.internal.processors.cache.mvcc.MvccUtils.MVCC_HINTS_BIT_OFF;
+import static org.apache.ignite.internal.processors.cache.mvcc.MvccUtils.MVCC_KEY_ABSENT_BEFORE_MASK;
+import static org.apache.ignite.internal.processors.cache.mvcc.MvccUtils.MVCC_KEY_ABSENT_BEFORE_OFF;
+import static org.apache.ignite.internal.processors.cache.mvcc.MvccUtils.MVCC_OP_COUNTER_MASK;
 import static org.apache.ignite.internal.processors.cache.mvcc.MvccUtils.MVCC_OP_COUNTER_NA;
 import static org.apache.ignite.internal.processors.cache.persistence.tree.io.DataPageIO.MVCC_INFO_SIZE;
-import static org.apache.ignite.internal.processors.cache.persistence.tree.io.PageIO.MVCC_HINTS_BIT_OFF;
-import static org.apache.ignite.internal.processors.cache.persistence.tree.io.PageIO.MVCC_HINTS_MASK;
 
 /**
  *
@@ -74,6 +76,9 @@ public class MvccDataRow extends DataRow {
     @GridToStringInclude
     protected byte newMvccTxState;
 
+    /** Flag, whether this key was absent in cache before this transaction. */
+    protected boolean keyAbsentBefore;
+
     /**
      * @param link Link.
      */
@@ -153,8 +158,9 @@ public class MvccDataRow extends DataRow {
 
         int withHint = PageUtils.getInt(addr, off + 16);
 
-        mvccOpCntr = withHint & ~MVCC_HINTS_MASK;
+        mvccOpCntr = withHint & ~MVCC_OP_COUNTER_MASK;
         mvccTxState = (byte)(withHint >>> MVCC_HINTS_BIT_OFF);
+        keyAbsentBefore = ((withHint & MVCC_KEY_ABSENT_BEFORE_MASK) >>> MVCC_KEY_ABSENT_BEFORE_OFF) == 1;
 
         assert MvccUtils.mvccVersionIsValid(mvccCrd, mvccCntr, mvccOpCntr);
 
@@ -164,9 +170,12 @@ public class MvccDataRow extends DataRow {
 
         withHint = PageUtils.getInt(addr, off + 36);
 
-        newMvccOpCntr = withHint & ~MVCC_HINTS_MASK;
+        newMvccOpCntr = withHint & ~MVCC_OP_COUNTER_MASK;
         newMvccTxState = (byte)(withHint >>> MVCC_HINTS_BIT_OFF);
 
+        if (newMvccCrd != MVCC_CRD_COUNTER_NA)
+            keyAbsentBefore = ((withHint & MVCC_KEY_ABSENT_BEFORE_MASK) >>> MVCC_KEY_ABSENT_BEFORE_OFF) == 1;
+
         assert newMvccCrd == MVCC_CRD_COUNTER_NA || MvccUtils.mvccVersionIsValid(newMvccCrd, newMvccCntr, newMvccOpCntr);
 
         return MVCC_INFO_SIZE;
@@ -247,6 +256,11 @@ public class MvccDataRow extends DataRow {
     }
 
     /** {@inheritDoc} */
+    @Override public boolean isKeyAbsentBefore() {
+        return keyAbsentBefore;
+    }
+
+    /** {@inheritDoc} */
     @Override public int size() throws IgniteCheckedException {
         return super.size() + MVCC_INFO_SIZE;
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/tree/mvcc/data/MvccUpdateDataRow.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/tree/mvcc/data/MvccUpdateDataRow.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/tree/mvcc/data/MvccUpdateDataRow.java
index 81b1b58..716094e 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/tree/mvcc/data/MvccUpdateDataRow.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/tree/mvcc/data/MvccUpdateDataRow.java
@@ -41,14 +41,14 @@ import org.apache.ignite.internal.util.typedef.internal.S;
 
 import static org.apache.ignite.internal.processors.cache.mvcc.MvccUtils.MVCC_COUNTER_NA;
 import static org.apache.ignite.internal.processors.cache.mvcc.MvccUtils.MVCC_CRD_COUNTER_NA;
+import static org.apache.ignite.internal.processors.cache.mvcc.MvccUtils.MVCC_HINTS_BIT_OFF;
+import static org.apache.ignite.internal.processors.cache.mvcc.MvccUtils.MVCC_OP_COUNTER_MASK;
 import static org.apache.ignite.internal.processors.cache.mvcc.MvccUtils.MVCC_OP_COUNTER_NA;
 import static org.apache.ignite.internal.processors.cache.mvcc.MvccUtils.compare;
 import static org.apache.ignite.internal.processors.cache.mvcc.MvccUtils.isActive;
 import static org.apache.ignite.internal.processors.cache.mvcc.MvccUtils.isVisible;
 import static org.apache.ignite.internal.processors.cache.mvcc.MvccUtils.mvccVersionIsValid;
 import static org.apache.ignite.internal.processors.cache.mvcc.MvccUtils.unexpectedStateException;
-import static org.apache.ignite.internal.processors.cache.persistence.tree.io.PageIO.MVCC_HINTS_BIT_OFF;
-import static org.apache.ignite.internal.processors.cache.persistence.tree.io.PageIO.MVCC_HINTS_MASK;
 
 /**
  *
@@ -56,16 +56,22 @@ import static org.apache.ignite.internal.processors.cache.persistence.tree.io.Pa
 public class MvccUpdateDataRow extends MvccDataRow implements MvccUpdateResult, BPlusTree.TreeVisitorClosure<CacheSearchRow, CacheDataRow> {
     /** */
     private static final int FIRST = DIRTY << 1;
+
     /** */
     private static final int CHECK_VERSION = FIRST << 1;
+
     /** */
     private static final int LAST_COMMITTED_FOUND = CHECK_VERSION << 1;
+
     /** */
     private static final int CAN_CLEANUP = LAST_COMMITTED_FOUND << 1;
+
     /** */
     private static final int PRIMARY = CAN_CLEANUP << 1;
+
     /** */
     private static final int REMOVE_OR_LOCK = PRIMARY << 1;
+
     /** */
     private static final int NEED_HISTORY = REMOVE_OR_LOCK << 1;
     /**
@@ -78,11 +84,16 @@ public class MvccUpdateDataRow extends MvccDataRow implements MvccUpdateResult,
      * but more versions should be checked.
      */
     private static final int FAST_UPDATE = NEED_HISTORY << 1;
+
     /** */
     private static final int FAST_MISMATCH = FAST_UPDATE << 1;
+
     /** */
     private static final int DELETED = FAST_MISMATCH << 1;
 
+    /** Whether tx has overridden it's own update. */
+    private static final int OWN_VALUE_OVERRIDDEN = DELETED << 1;
+
     /** */
     @GridToStringExclude
     private final GridCacheContext cctx;
@@ -152,6 +163,7 @@ public class MvccUpdateDataRow extends MvccDataRow implements MvccUpdateResult,
 
         this.mvccSnapshot = mvccSnapshot;
         this.cctx = cctx;
+        this.keyAbsentBefore = primary; // True for primary and false for backup (backups do not use this flag).
 
         assert !lockOnly || val == null;
 
@@ -228,7 +240,11 @@ public class MvccUpdateDataRow extends MvccDataRow implements MvccUpdateResult,
                 else
                     oldRow = row;
 
-                setFlags(LAST_COMMITTED_FOUND);
+                setFlags(LAST_COMMITTED_FOUND | OWN_VALUE_OVERRIDDEN);
+
+                // Copy new key flag from the previous row version if it was created by the current tx.
+                if (isFlagsSet(PRIMARY))
+                    keyAbsentBefore = row.isKeyAbsentBefore();
             }
         }
 
@@ -238,13 +254,13 @@ public class MvccUpdateDataRow extends MvccDataRow implements MvccUpdateResult,
         long rowCntr = row.mvccCounter();
 
         // with hint bits
-        int rowOpCntr = (row.mvccTxState() << MVCC_HINTS_BIT_OFF) | (row.mvccOperationCounter() & ~MVCC_HINTS_MASK);
+        int rowOpCntr = (row.mvccTxState() << MVCC_HINTS_BIT_OFF) | (row.mvccOperationCounter() & ~MVCC_OP_COUNTER_MASK);
 
         long rowNewCrd = row.newMvccCoordinatorVersion();
         long rowNewCntr = row.newMvccCounter();
 
         // with hint bits
-        int rowNewOpCntr = (row.newMvccTxState() << MVCC_HINTS_BIT_OFF) | (row.newMvccOperationCounter() & ~MVCC_HINTS_MASK);
+        int rowNewOpCntr = (row.newMvccTxState() << MVCC_HINTS_BIT_OFF) | (row.newMvccOperationCounter() & ~MVCC_OP_COUNTER_MASK);
 
         // Search for youngest committed by another transaction row.
         if (!isFlagsSet(LAST_COMMITTED_FOUND)) {
@@ -278,6 +294,8 @@ public class MvccUpdateDataRow extends MvccDataRow implements MvccUpdateResult,
                         res = ResultType.PREV_NOT_NULL;
 
                         oldRow = row;
+
+                        keyAbsentBefore = false;
                     }
 
                     if (isFlagsSet(CHECK_VERSION)) {
@@ -380,7 +398,7 @@ public class MvccUpdateDataRow extends MvccDataRow implements MvccUpdateResult,
             if (cleanupRows == null)
                 cleanupRows = new ArrayList<>();
 
-            cleanupRows.add(new MvccLinkAwareSearchRow(cacheId, key, rowCrd, rowCntr, rowOpCntr & ~MVCC_HINTS_MASK, rowLink));
+            cleanupRows.add(new MvccLinkAwareSearchRow(cacheId, key, rowCrd, rowCntr, rowOpCntr & ~MVCC_OP_COUNTER_MASK, rowLink));
         }
         else {
             // Row obsoleted by current operation, all rows created or updated with current tx.
@@ -391,7 +409,7 @@ public class MvccUpdateDataRow extends MvccDataRow implements MvccUpdateResult,
                 if (historyRows == null)
                     historyRows = new ArrayList<>();
 
-                historyRows.add(new MvccLinkAwareSearchRow(cacheId, key, rowCrd, rowCntr, rowOpCntr & ~MVCC_HINTS_MASK, rowLink));
+                historyRows.add(new MvccLinkAwareSearchRow(cacheId, key, rowCrd, rowCntr, rowOpCntr & ~MVCC_OP_COUNTER_MASK, rowLink));
             }
 
             if (cleanupVer > MVCC_OP_COUNTER_NA // Do not clean if cleanup version is not assigned.
@@ -463,6 +481,11 @@ public class MvccUpdateDataRow extends MvccDataRow implements MvccUpdateResult,
         return historyRows;
     }
 
+    /** {@inheritDoc} */
+    @Override public boolean isOwnValueOverridden() {
+        return isFlagsSet(OWN_VALUE_OVERRIDDEN);
+    }
+
     /** */
     private boolean isFlagsSet(int flags) {
         return (state & flags) == flags;

http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/tree/mvcc/data/MvccUpdateResult.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/tree/mvcc/data/MvccUpdateResult.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/tree/mvcc/data/MvccUpdateResult.java
index 086a30d..d76a6e8 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/tree/mvcc/data/MvccUpdateResult.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/tree/mvcc/data/MvccUpdateResult.java
@@ -40,4 +40,14 @@ public interface MvccUpdateResult {
      * @return Collection of row created or affected by the current tx.
      */
     public List<MvccLinkAwareSearchRow> history();
+
+    /**
+     * @return {@code True} if this key was inserted in the cache with this row in the same transaction.
+     */
+    public boolean isKeyAbsentBefore();
+
+    /**
+     * @return Flag whether tx has overridden it's own update.
+     */
+    public boolean isOwnValueOverridden();
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheTestEntryEx.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheTestEntryEx.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheTestEntryEx.java
index 8bc620f..9bbf03d 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
@@ -482,7 +482,7 @@ public class GridCacheTestEntryEx extends GridMetadataAwareAdapter implements Gr
 
     /** {@inheritDoc} */
     @Override public GridCacheUpdateTxResult mvccSet(@Nullable IgniteInternalTx tx, UUID affNodeId, CacheObject val,
-        long ttl0, AffinityTopologyVersion topVer, @Nullable Long updateCntr, MvccSnapshot mvccVer,
+        long ttl0, AffinityTopologyVersion topVer, MvccSnapshot mvccVer,
         GridCacheOperation op, boolean needHistory,
         boolean noCreate) throws IgniteCheckedException, GridCacheEntryRemovedException {
         rawPut(val, ttl);
@@ -492,7 +492,7 @@ public class GridCacheTestEntryEx extends GridMetadataAwareAdapter implements Gr
 
     /** {@inheritDoc} */
     @Override public GridCacheUpdateTxResult mvccRemove(@Nullable IgniteInternalTx tx, UUID affNodeId,
-        AffinityTopologyVersion topVer, @Nullable Long updateCntr, MvccSnapshot mvccVer, boolean needHistory)
+        AffinityTopologyVersion topVer, MvccSnapshot mvccVer, boolean needHistory)
         throws IgniteCheckedException, GridCacheEntryRemovedException {
         obsoleteVer = ver;
 
@@ -943,7 +943,6 @@ public class GridCacheTestEntryEx extends GridMetadataAwareAdapter implements Gr
     @Override public GridCacheUpdateTxResult mvccUpdateRowsWithPreloadInfo(IgniteInternalTx tx,
         UUID affNodeId,
         AffinityTopologyVersion topVer,
-        @Nullable Long updateCntr,
         List<GridCacheEntryInfo> entries,
         GridCacheOperation op,
         MvccSnapshot mvccVer) throws IgniteCheckedException, GridCacheEntryRemovedException {

http://git-wip-us.apache.org/repos/asf/ignite/blob/cc9db58e/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/CacheMvccConfigurationValidationTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/CacheMvccConfigurationValidationTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/CacheMvccConfigurationValidationTest.java
index a10c6c7..8b70468 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/CacheMvccConfigurationValidationTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/CacheMvccConfigurationValidationTest.java
@@ -286,7 +286,7 @@ public class CacheMvccConfigurationValidationTest extends GridCommonAbstractTest
 
                 return null;
             }
-        }, IgniteCheckedException.class, "Failed to start processor");
+        }, IgniteCheckedException.class, "Cannot start cache. Statically configured atomicity mode differs from");
     }
 
     /**
@@ -332,7 +332,7 @@ public class CacheMvccConfigurationValidationTest extends GridCommonAbstractTest
 
                 return null;
             }
-        }, IgniteCheckedException.class, "Failed to start processor");
+        }, IgniteCheckedException.class, "Cannot start cache. Statically configured atomicity mode");
     }
 
     /**


[4/9] ignite git commit: IGNITE-9573 Fix ZooKeeper SASL authentication tests. - Fixes #4755.

Posted by vo...@apache.org.
IGNITE-9573 Fix ZooKeeper SASL authentication tests. - Fixes #4755.

Signed-off-by: Dmitriy Pavlov <dp...@apache.org>


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

Branch: refs/heads/ignite-2.7
Commit: 8f771ba442c74368122d208548d573f6e86b3468
Parents: cc9db58
Author: Ilya Kasnacheev <il...@gmail.com>
Authored: Tue Sep 25 20:28:48 2018 +0300
Committer: devozerov <vo...@gridgain.com>
Committed: Wed Sep 26 12:37:12 2018 +0300

----------------------------------------------------------------------
 .../apache/ignite/IgniteSystemProperties.java   | 10 ++++++++++
 .../discovery/zk/internal/ZookeeperClient.java  | 21 +++++++++++++-------
 ...okeeperDiscoverySpiSaslAuthAbstractTest.java | 14 +++++++++++++
 ...ZookeeperDiscoverySpiSaslFailedAuthTest.java | 11 ++++++----
 4 files changed, 45 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/8f771ba4/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java b/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java
index 71a633f..5932de0 100644
--- a/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java
+++ b/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java
@@ -979,6 +979,16 @@ public final class IgniteSystemProperties {
     public static final String IGNITE_EVICTION_PERMITS = "IGNITE_EVICTION_PERMITS";
 
     /**
+     * Timeout between ZooKeeper client retries, default 2s.
+     */
+    public static final String IGNITE_ZOOKEEPER_DISCOVERY_RETRY_TIMEOUT = "IGNITE_ZOOKEEPER_DISCOVERY_RETRY_TIMEOUT";
+
+    /**
+     * Number of attempts to reconnect to ZooKeeper.
+     */
+    public static final String IGNITE_ZOOKEEPER_DISCOVERY_MAX_RETRY_COUNT = "IGNITE_ZOOKEEPER_DISCOVERY_MAX_RETRY_COUNT";
+
+    /**
      * Enforces singleton.
      */
     private IgniteSystemProperties() {

http://git-wip-us.apache.org/repos/asf/ignite/blob/8f771ba4/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperClient.java
----------------------------------------------------------------------
diff --git a/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperClient.java b/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperClient.java
index 39417c2..a2788a1 100644
--- a/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperClient.java
+++ b/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperClient.java
@@ -40,17 +40,18 @@ import org.apache.zookeeper.data.ACL;
 import org.apache.zookeeper.data.Stat;
 import org.jetbrains.annotations.Nullable;
 
+import static org.apache.ignite.IgniteSystemProperties.IGNITE_ZOOKEEPER_DISCOVERY_MAX_RETRY_COUNT;
+import static org.apache.ignite.IgniteSystemProperties.IGNITE_ZOOKEEPER_DISCOVERY_RETRY_TIMEOUT;
+
 /**
  * Zookeeper Client.
  */
 public class ZookeeperClient implements Watcher {
     /** */
-    private static final long RETRY_TIMEOUT =
-        IgniteSystemProperties.getLong("IGNITE_ZOOKEEPER_DISCOVERY_RETRY_TIMEOUT", 2000);
+    private static final int DFLT_RETRY_TIMEOUT = 2000;
 
     /** */
-    private static final int MAX_RETRY_COUNT =
-        IgniteSystemProperties.getInteger("IGNITE_ZOOKEEPER_DISCOVERY_MAX_RETRY_COUNT", 10);
+    private static final int DFLT_MAX_RETRY_COUNT = 10;
 
     /** */
     private final AtomicInteger retryCount = new AtomicInteger();
@@ -866,13 +867,16 @@ public class ZookeeperClient implements Watcher {
                 }
 
                 if (err == null) {
+                    long retryTimeout = IgniteSystemProperties.getLong(IGNITE_ZOOKEEPER_DISCOVERY_RETRY_TIMEOUT,
+                        DFLT_RETRY_TIMEOUT);
+
                     U.warn(log, "ZooKeeper operation failed, will retry [err=" + e +
-                        ", retryTimeout=" + RETRY_TIMEOUT +
+                        ", retryTimeout=" + retryTimeout +
                         ", connLossTimeout=" + connLossTimeout +
                         ", path=" + ((KeeperException)e).getPath() +
                         ", remainingWaitTime=" + remainingTime + ']');
 
-                    stateMux.wait(RETRY_TIMEOUT);
+                    stateMux.wait(retryTimeout);
 
                     if (closing)
                         throw new ZookeeperClientFailedException("ZooKeeper client is closed.");
@@ -906,7 +910,10 @@ public class ZookeeperClient implements Watcher {
             code == KeeperException.Code.OPERATIONTIMEOUT.intValue();
 
         if (retryByErrorCode) {
-            if (MAX_RETRY_COUNT <= 0 || retryCount.incrementAndGet() < MAX_RETRY_COUNT)
+            int maxRetryCount = IgniteSystemProperties.getInteger(IGNITE_ZOOKEEPER_DISCOVERY_MAX_RETRY_COUNT,
+                DFLT_MAX_RETRY_COUNT);
+
+            if (maxRetryCount <= 0 || retryCount.incrementAndGet() < maxRetryCount)
                 return true;
             else
                 return false;

http://git-wip-us.apache.org/repos/asf/ignite/blob/8f771ba4/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoverySpiSaslAuthAbstractTest.java
----------------------------------------------------------------------
diff --git a/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoverySpiSaslAuthAbstractTest.java b/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoverySpiSaslAuthAbstractTest.java
index ac94bf2..14d02f4 100644
--- a/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoverySpiSaslAuthAbstractTest.java
+++ b/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoverySpiSaslAuthAbstractTest.java
@@ -20,10 +20,12 @@ import java.io.File;
 import java.io.FileWriter;
 import java.io.IOException;
 import java.nio.file.Paths;
+import javax.security.auth.login.Configuration;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.spi.discovery.zk.ZookeeperDiscoverySpi;
+import org.apache.ignite.testframework.GridTestUtils;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
 import org.apache.zookeeper.client.ZooKeeperSaslClient;
 import org.apache.zookeeper.server.ServerCnxnFactory;
@@ -109,6 +111,8 @@ public abstract class ZookeeperDiscoverySpiSaslAuthAbstractTest extends GridComm
 
     /** */
     protected void clearSaslSystemProperties() {
+        resetSaslStaticFields();
+
         System.clearProperty(AUTH_PROVIDER);
 
         System.clearProperty(SASL_CONFIG);
@@ -137,12 +141,22 @@ public abstract class ZookeeperDiscoverySpiSaslAuthAbstractTest extends GridComm
 
     /** */
     private void prepareSaslSystemProperties() {
+        resetSaslStaticFields();
+
         System.setProperty(SASL_CONFIG, Paths.get(tmpDir.getPath().toString(), JAAS_CONF_FILE).toString());
 
         System.setProperty(AUTH_PROVIDER, "org.apache.zookeeper.server.auth.SASLAuthenticationProvider");
     }
 
     /** */
+    private void resetSaslStaticFields() {
+        Configuration.setConfiguration(null);
+
+        GridTestUtils.setFieldValue(ZooKeeperSaslClient.class, "initializedLogin", false);
+        GridTestUtils.setFieldValue(ZooKeeperSaslClient.class, "login", null);
+    }
+
+    /** */
     private void writeClientConfigSection(FileWriter fwriter, String clientName, String pass) throws IOException {
         fwriter.write(clientName + "{\n" +
             "       org.apache.zookeeper.server.auth.DigestLoginModule required\n" +

http://git-wip-us.apache.org/repos/asf/ignite/blob/8f771ba4/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoverySpiSaslFailedAuthTest.java
----------------------------------------------------------------------
diff --git a/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoverySpiSaslFailedAuthTest.java b/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoverySpiSaslFailedAuthTest.java
index 097b7c5..c90f6d4 100644
--- a/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoverySpiSaslFailedAuthTest.java
+++ b/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoverySpiSaslFailedAuthTest.java
@@ -19,6 +19,8 @@ package org.apache.ignite.spi.discovery.zk.internal;
 import org.apache.zookeeper.client.ZooKeeperSaslClient;
 import org.junit.Assert;
 
+import static org.apache.ignite.IgniteSystemProperties.IGNITE_ZOOKEEPER_DISCOVERY_MAX_RETRY_COUNT;
+
 /**
  *
  */
@@ -27,20 +29,21 @@ public class ZookeeperDiscoverySpiSaslFailedAuthTest extends ZookeeperDiscoveryS
      * @throws Exception If failed.
      */
     public void testIgniteNodeWithInvalidPasswordFailsToJoin() throws Exception {
-        fail("https://issues.apache.org/jira/browse/IGNITE-9573");
-
         System.setProperty(ZooKeeperSaslClient.LOGIN_CONTEXT_NAME_KEY,
             "InvalidZookeeperClient");
 
-        System.setProperty("IGNITE_ZOOKEEPER_DISCOVERY_MAX_RETRY_COUNT", Integer.toString(1));
+        System.setProperty(IGNITE_ZOOKEEPER_DISCOVERY_MAX_RETRY_COUNT, "1");
 
         try {
             startGrid(0);
 
             Assert.fail("Ignite node with invalid password should fail on join.");
         }
-        catch (Exception e) {
+        catch (Exception ignored) {
             //ignored
         }
+        finally {
+            System.clearProperty(IGNITE_ZOOKEEPER_DISCOVERY_MAX_RETRY_COUNT);
+        }
     }
 }