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

[02/24] ignite git commit: GG-11414: Remove snapshotableIndex flag from CacheConfiguration, Get rid of all usages of GridH2TreeIndex

GG-11414: Remove snapshotableIndex flag from CacheConfiguration, Get rid of all usages of GridH2TreeIndex


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

Branch: refs/heads/ignite-gg-11810
Commit: b2999f2e4d490fdb140483e4283f0fe2d8004a67
Parents: ef015d3
Author: Sergey Sidorov <ss...@gridgain.com>
Authored: Tue Nov 15 18:50:24 2016 +0300
Committer: Sergey Sidorov <ss...@gridgain.com>
Committed: Wed Nov 16 16:49:52 2016 +0300

----------------------------------------------------------------------
 .../configuration/CacheConfiguration.java       |  30 ----
 .../cache/IgniteCacheOffheapManagerImpl.java    |   6 +-
 .../cache/database/tree/BPlusTree.java          |  30 +++-
 .../util/GridCursorIteratorWrapper.java         |  28 +++
 .../apache/ignite/internal/util/IgniteTree.java |  79 ++++----
 .../ignite/internal/util/lang/GridCursor.java   |   1 +
 .../offheap/unsafe/GridOffHeapSnapTreeMap.java  |  85 ++++++---
 .../internal/util/snaptree/SnapTreeMap.java     |  92 +++++++---
 .../internal/processors/query/h2/H2Cursor.java  |  84 +++++++++
 .../processors/query/h2/IgniteH2Indexing.java   |  36 +---
 .../query/h2/database/H2TreeIndex.java          |  92 +++-------
 .../query/h2/opt/GridH2IndexBase.java           | 178 ++++++++-----------
 .../processors/query/h2/opt/GridH2Table.java    |   4 +-
 .../query/h2/opt/GridH2TreeIndex.java           | 154 +++++++++++-----
 .../cache/IgniteCacheAbstractQuerySelfTest.java |   2 +-
 .../query/h2/opt/GridH2TableSelfTest.java       |  29 +--
 16 files changed, 536 insertions(+), 394 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/b2999f2e/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java b/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java
index e15c989..44c23c0 100644
--- a/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java
+++ b/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java
@@ -371,9 +371,6 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> {
     /** */
     private transient Class<?>[] indexedTypes;
 
-    /** */
-    private boolean snapshotableIdx;
-
     /** Copy on read flag. */
     private boolean cpOnRead = DFLT_COPY_ON_READ;
 
@@ -466,7 +463,6 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> {
         rebalancePoolSize = cc.getRebalanceThreadPoolSize();
         rebalanceTimeout = cc.getRebalanceTimeout();
         rebalanceThrottle = cc.getRebalanceThrottle();
-        snapshotableIdx = cc.isSnapshotableIndex();
         sqlSchema = cc.getSqlSchema();
         sqlEscapeAll = cc.isSqlEscapeAll();
         sqlFuncCls = cc.getSqlFunctionClasses();
@@ -1930,32 +1926,6 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> {
     }
 
     /**
-     * Gets flag indicating whether SQL indexes should support snapshots.
-     *
-     * @return {@code True} if SQL indexes should support snapshots.
-     */
-    public boolean isSnapshotableIndex() {
-        return snapshotableIdx;
-    }
-
-    /**
-     * Sets flag indicating whether SQL indexes should support snapshots.
-     * <p>
-     * Default value is {@code false}.
-     * <p>
-     * <b>Note</b> that this flag is ignored if indexes are stored in offheap memory,
-     * for offheap indexes snapshots are always enabled.
-     *
-     * @param snapshotableIdx {@code True} if SQL indexes should support snapshots.
-     * @return {@code this} for chaining.
-     */
-    public CacheConfiguration<K, V> setSnapshotableIndex(boolean snapshotableIdx) {
-        this.snapshotableIdx = snapshotableIdx;
-
-        return this;
-    }
-
-    /**
      * Gets array of cache plugin configurations.
      *
      * @return Cache plugin configurations.

http://git-wip-us.apache.org/repos/asf/ignite/blob/b2999f2e/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 e431f58..66896d2 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
@@ -570,9 +570,11 @@ public class IgniteCacheOffheapManagerImpl extends GridCacheManagerAdapter imple
      * @throws IgniteCheckedException If failed.
      */
     private long allocateForTree() throws IgniteCheckedException {
-        long pageId = cctx.shared().database().globalReuseList().takeRecycledPage();
+        ReuseList reuseList = cctx.shared().database().globalReuseList();
 
-        if (pageId == 0L)
+        long pageId;
+
+        if (reuseList == null || (pageId = reuseList.takeRecycledPage()) == 0L)
             pageId = cctx.shared().database().pageMemory().allocatePage(cctx.cacheId(), INDEX_PARTITION, FLAG_IDX);
 
         return pageId;

http://git-wip-us.apache.org/repos/asf/ignite/blob/b2999f2e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/BPlusTree.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/BPlusTree.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/BPlusTree.java
index 2aab831..f761975 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/BPlusTree.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/BPlusTree.java
@@ -55,8 +55,7 @@ import org.apache.ignite.internal.processors.cache.database.tree.io.PageIO;
 import org.apache.ignite.internal.processors.cache.database.tree.reuse.ReuseBag;
 import org.apache.ignite.internal.processors.cache.database.tree.reuse.ReuseList;
 import org.apache.ignite.internal.processors.cache.database.tree.util.PageHandler;
-import org.apache.ignite.internal.util.GridArrays;
-import org.apache.ignite.internal.util.GridLongList;
+import org.apache.ignite.internal.util.*;
 import org.apache.ignite.internal.util.lang.GridCursor;
 import org.apache.ignite.internal.util.lang.GridTreePrinter;
 import org.apache.ignite.internal.util.typedef.F;
@@ -83,7 +82,7 @@ import static org.apache.ignite.internal.processors.cache.database.tree.util.Pag
  * Abstract B+Tree.
  */
 @SuppressWarnings({"RedundantThrowsDeclaration", "ConstantValueVariableUse"})
-public abstract class BPlusTree<L, T extends L> extends DataStructure {
+public abstract class BPlusTree<L, T extends L> extends DataStructure implements IgniteTree<L, T> {
     /** */
     private static final Object[] EMPTY = {};
 
@@ -752,6 +751,16 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure {
         }
     }
 
+    public GridCursor<T> find(L lower, boolean lowerInclusive,
+                              L upper, boolean upperInclusive) throws IgniteCheckedException {
+        // TODO inclusive / exclusive logic should be implemented
+        return find(lower, upper);
+    }
+
+    public GridCursor<T> findAll() throws IgniteCheckedException {
+        return find(null, null);
+    }
+
     /**
      * @param row Lookup row for exact match.
      * @return Found row.
@@ -1253,6 +1262,10 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure {
         return doRemove(row, false, null);
     }
 
+    @Override public T removeNode(L key) throws IgniteCheckedException {
+        return doRemove(key, false, null);
+    }
+
     /**
      * @param row Lookup row.
      * @param ceil If we can remove ceil row when we can not find exact.
@@ -1503,9 +1516,14 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure {
     }
 
     /**
-     * @param row Row.
-     * @return Old row.
-     * @throws IgniteCheckedException If failed.
+     * {@inheritDoc}
+     */
+    public final long treeSize() throws IgniteCheckedException {
+        return size();
+    }
+
+    /**
+     * {@inheritDoc}
      */
     public final T put(T row) throws IgniteCheckedException {
         return put(row, null);

http://git-wip-us.apache.org/repos/asf/ignite/blob/b2999f2e/modules/core/src/main/java/org/apache/ignite/internal/util/GridCursorIteratorWrapper.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/GridCursorIteratorWrapper.java b/modules/core/src/main/java/org/apache/ignite/internal/util/GridCursorIteratorWrapper.java
new file mode 100644
index 0000000..bd30ace
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/GridCursorIteratorWrapper.java
@@ -0,0 +1,28 @@
+package org.apache.ignite.internal.util;
+
+import org.apache.ignite.*;
+import org.apache.ignite.internal.util.lang.*;
+
+import java.util.*;
+
+/**
+ * Wrap {@code Iterator} and adapt it to {@code GridCursor}.
+ */
+public class GridCursorIteratorWrapper<V> implements GridCursor<V> {
+    private Iterator<V> iter;
+    private V next;
+
+    public GridCursorIteratorWrapper(Iterator<V> iter) {
+        this.iter = iter;
+    }
+
+    @Override public V get() throws IgniteCheckedException {
+        return next;
+    }
+
+    @Override public boolean next() throws IgniteCheckedException {
+        next = iter.hasNext() ? iter.next() : null;
+
+        return next != null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/b2999f2e/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteTree.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteTree.java b/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteTree.java
index 2c1e1af..512792b 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteTree.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteTree.java
@@ -17,20 +17,22 @@
 
 package org.apache.ignite.internal.util;
 
+import org.apache.ignite.*;
+import org.apache.ignite.internal.util.lang.*;
+
 import java.util.*;
 
 /**
  * Interface for ignite internal tree.
  */
-public interface IgniteTree<K, V> {
+public interface IgniteTree<L, T> {
     /**
-     * Associates the specified value with the specified key in this tree.
+     * Put value in this tree.
      *
-     * @param key key with which the specified value is to be associated
      * @param value value to be associated with the specified key
      * @return the previous value associated with key
      */
-    V put(K key, V value);
+    T put(T value) throws IgniteCheckedException;
 
     /**
      * Returns the value to which the specified key is mapped, or {@code null} if this tree contains no mapping for the
@@ -40,66 +42,49 @@ public interface IgniteTree<K, V> {
      * @return the value to which the specified key is mapped, or {@code null} if this tree contains no mapping for the
      * key
      */
-    V get(Object key);
-
-    /**
-     * Removes the mapping for a key from this tree if it is present.
-     *
-     * @param key key whose mapping is to be removed from the tree
-     * @return the previous value associated with key, or null if there was no mapping for key.
-     */
-    V remove(Object key);
+    T findOne(L key) throws IgniteCheckedException;
 
     /**
-     * Returns the number of elements in this tree.
+     * Returns a cursor from lower to upper bounds.
      *
-     * @return the number of elements in this tree
+     * @param lower Lower bound or {@code null} if unbounded.
+     * @param lowerInclusive {@code true} if the low bound
+     *        is to be included in the returned view
+     * @param upper Upper bound or {@code null} if unbounded.
+     * @param upperInclusive {@code true} if the upper bound
+     *        is to be included in the returned view
+     * @return Cursor.
      */
-    int size();
+    GridCursor<T> find(L lower, boolean lowerInclusive,  L upper, boolean upperInclusive) throws IgniteCheckedException;
 
     /**
-     * Returns a {@link Collection} view of the values contained in this tree.
+     * Returns a cursor from lower to upper bounds inclusive.
      *
-     * @return a collection view of the values contained in this map
+     * @param lower Lower bound or {@code null} if unbounded.
+     * @param upper Upper bound or {@code null} if unbounded.
+     * @return Cursor.
      */
-    Collection<V> values();
+    GridCursor<T> find(L lower, L upper) throws IgniteCheckedException;
 
     /**
-     * Returns a view of the portion of this tree whose keys are less than (or equal to, if {@code inclusive} is true)
-     * {@code toKey}.  The returned tree is backed by this tree, so changes in the returned tree are reflected in this
-     * tree, and vice-versa.  The returned tree supports all optional tree operations that this tree supports.
-     *
-     * @param toKey high endpoint of the keys in the returned tree
-     * @param inclusive {@code true} if the high endpoint is to be included in the returned view
-     * @return a view of the portion of this tree whose keys are less than (or equal to, if {@code inclusive} is true)
-     * {@code toKey}
+     * Returns a cursor over all values.
+     * @return Cursor.
+     * @throws IgniteCheckedException
      */
-    IgniteTree<K, V> headTree(K toKey, boolean inclusive);
+    GridCursor<T> findAll() throws IgniteCheckedException;
 
     /**
-     * Returns a view of the portion of this tree whose keys are greater than (or equal to, if {@code inclusive} is
-     * true) {@code fromKey}.  The returned tree is backed by this tree, so changes in the returned tree are reflected
-     * in this tree, and vice-versa.  The returned tree supports all optional tree operations that this tree supports.
+     * Removes the mapping for a key from this tree if it is present.
      *
-     * @param fromKey low endpoint of the keys in the returned tree
-     * @param inclusive {@code true} if the low endpoint is to be included in the returned view
-     * @return a view of the portion of this tree whose keys are greater than (or equal to, if {@code inclusive} is
-     * true) {@code fromKey}
+     * @param key key whose mapping is to be removed from the tree
+     * @return the previous value associated with key, or null if there was no mapping for key.
      */
-    IgniteTree<K, V> tailTree(K fromKey, boolean inclusive);
+    T removeNode(L key) throws IgniteCheckedException;
 
     /**
-     * Returns a view of the portion of this tree whose keys range from {@code fromKey} to {@code toKey}.  If {@code
-     * fromKey} and {@code toKey} are equal, the returned tree is empty unless {@code fromInclusive} and {@code
-     * toInclusive} are both true.  The returned tree is backed by this tree, so changes in the returned tree are
-     * reflected in this tree, and vice-versa.  The returned tree supports all optional tree operations that this tree
-     * supports.
+     * Returns the number of elements in this tree.
      *
-     * @param fromKey low endpoint of the keys in the returned tree
-     * @param fromInclusive {@code true} if the low endpoint is to be included in the returned view
-     * @param toKey high endpoint of the keys in the returned tree
-     * @param toInclusive {@code true} if the high endpoint is to be included in the returned view
-     * @return a view of the portion of this tree whose keys range from {@code fromKey} to {@code toKey}
+     * @return the number of elements in this tree
      */
-    IgniteTree<K, V> subTree(final K fromKey, final boolean fromInclusive, final K toKey, final boolean toInclusive);
+    long treeSize() throws IgniteCheckedException;
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/b2999f2e/modules/core/src/main/java/org/apache/ignite/internal/util/lang/GridCursor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/lang/GridCursor.java b/modules/core/src/main/java/org/apache/ignite/internal/util/lang/GridCursor.java
index 37d3a48..da85f99 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/util/lang/GridCursor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/lang/GridCursor.java
@@ -18,6 +18,7 @@
 package org.apache.ignite.internal.util.lang;
 
 import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.internal.processors.cache.database.*;
 
 /**
  * Simple cursor abstraction. Initial state must be "before first".

http://git-wip-us.apache.org/repos/asf/ignite/blob/b2999f2e/modules/core/src/main/java/org/apache/ignite/internal/util/offheap/unsafe/GridOffHeapSnapTreeMap.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/offheap/unsafe/GridOffHeapSnapTreeMap.java b/modules/core/src/main/java/org/apache/ignite/internal/util/offheap/unsafe/GridOffHeapSnapTreeMap.java
index 681394f..eb09af5 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/util/offheap/unsafe/GridOffHeapSnapTreeMap.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/offheap/unsafe/GridOffHeapSnapTreeMap.java
@@ -54,8 +54,11 @@ import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+import org.apache.ignite.*;
 import org.apache.ignite.internal.processors.cache.distributed.dht.GridReservable;
 import org.apache.ignite.internal.util.*;
+import org.apache.ignite.internal.util.lang.*;
 import org.apache.ignite.internal.util.typedef.internal.SB;
 import org.jetbrains.annotations.Nullable;
 import org.jsr166.ConcurrentHashMap8;
@@ -3824,30 +3827,48 @@ public class GridOffHeapSnapTreeMap<K extends GridOffHeapSmartPointer, V extends
 
     //////////////// IgniteTree
 
-    /** {@inheritDoc} */
-    @Override public IgniteTree<K, V> headTree(final K toKey, final boolean inclusive) {
-        return new SubMap(this, null, null, false, toKey, comparable(toKey), inclusive, false);
+    @Override public V put(V value) throws IgniteCheckedException {
+        return put((K)value, value);
     }
 
-    /** {@inheritDoc} */
-    @Override public IgniteTree<K, V> tailTree(final K fromKey, final boolean inclusive) {
-        return new SubMap(this, fromKey, comparable(fromKey), inclusive, null, null, false, false);
+    @Override public V findOne(K key) throws IgniteCheckedException {
+        return get(key);
     }
 
-    /** {@inheritDoc} */
-    @Override public IgniteTree<K, V> subTree(final K fromKey, final boolean fromInclusive, final K toKey,
-        final boolean toInclusive) {
-        final Comparable<? super K> fromCmp = comparable(fromKey);
-        if (fromCmp.compareTo(toKey) > 0) {
+    @Override public GridCursor<V> findAll() throws IgniteCheckedException {
+        return find(null, null);
+    }
+
+    @Override public GridCursor<V> find(K lower, K upper) throws IgniteCheckedException {
+        return find(lower, true, upper, true);
+    }
+
+    @Override public GridCursor<V> find(K lower, boolean lowerInclusive,  K upper, boolean upperInclusive)
+        throws IgniteCheckedException {
+
+        final Comparable<? super K> fromCmp = comparable(lower);
+
+        if (fromCmp.compareTo(upper) > 0) {
             throw new IllegalArgumentException();
         }
-        return new SubMap(this, fromKey, fromCmp, fromInclusive, toKey, comparable(toKey), toInclusive, false);
+
+        SubMap subMap = new SubMap(this, lower, fromCmp, lowerInclusive, upper, comparable(upper), upperInclusive, false);
+
+        return new GridCursorIteratorWrapper<>(subMap.values().iterator());
+    }
+
+    @Override public V removeNode(K key) throws IgniteCheckedException {
+        return remove(key);
+    }
+
+    @Override public long treeSize() throws IgniteCheckedException {
+        return size();
     }
 
     /**
      * Submap.
      */
-    private class SubMap extends AbstractMap<K,V> implements ConcurrentNavigableMap<K,V>, IgniteTree<K, V> {
+    private class SubMap extends AbstractMap<K, V> implements ConcurrentNavigableMap<K, V>, IgniteTree<K, V> {
         /** */
         private final GridOffHeapSnapTreeMap<K,V> m;
 
@@ -4456,22 +4477,36 @@ public class GridOffHeapSnapTreeMap<K extends GridOffHeapSmartPointer, V extends
 
         /////////// IgniteTree
 
-        /** {@inheritDoc} */
-        @Override public IgniteTree<K, V> headTree(K toKey, boolean inclusive) {
-            return headMap(toKey, inclusive);
+        @Override public V put(V value) throws IgniteCheckedException {
+            return put((K)value, value);
         }
 
-        /** {@inheritDoc} */
-        @Override public IgniteTree<K, V> tailTree(K fromKey, boolean inclusive) {
-            return tailMap(fromKey, inclusive);
+        @Override public V findOne(K key) throws IgniteCheckedException {
+            return get(key);
         }
 
-        /** {@inheritDoc} */
-        @Override public IgniteTree<K, V> subTree(final K fromKey,
-            final boolean fromInclusive,
-            final K toKey,
-            final boolean toInclusive) {
-            return subMap(fromKey, fromInclusive, toKey, toInclusive);
+        @Override public GridCursor<V> findAll() throws IgniteCheckedException {
+            return find(null, null);
+        }
+
+        @Override public GridCursor<V> find(K lower, K upper) throws IgniteCheckedException {
+            return find(lower, true, upper, true);
+        }
+
+        @Override public GridCursor<V> find(K lower, boolean lowerInclusive,  K upper, boolean upperInclusive)
+            throws IgniteCheckedException {
+
+            SubMap subMap = subMap(lower, lowerInclusive, upper, upperInclusive);
+
+            return new GridCursorIteratorWrapper(subMap.values().iterator());
+        }
+
+        @Override public V removeNode(K key) throws IgniteCheckedException {
+            return remove(key);
+        }
+
+        @Override public long treeSize() throws IgniteCheckedException {
+            return size();
         }
     }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/b2999f2e/modules/core/src/main/java/org/apache/ignite/internal/util/snaptree/SnapTreeMap.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/snaptree/SnapTreeMap.java b/modules/core/src/main/java/org/apache/ignite/internal/util/snaptree/SnapTreeMap.java
index 064e7b0..8bd5f59 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/util/snaptree/SnapTreeMap.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/snaptree/SnapTreeMap.java
@@ -35,7 +35,9 @@
 
 package org.apache.ignite.internal.util.snaptree;
 
+import org.apache.ignite.*;
 import org.apache.ignite.internal.util.*;
+import org.apache.ignite.internal.util.lang.*;
 
 import java.io.IOException;
 import java.io.ObjectInputStream;
@@ -2347,24 +2349,43 @@ public class SnapTreeMap<K, V> extends AbstractMap<K, V> implements ConcurrentNa
 
     //////////////// IgniteTree
 
-    /** {@inheritDoc} */
-    @Override public IgniteTree<K, V> headTree(final K toKey, final boolean inclusive) {
-        return new SubMap<K,V>(this, null, null, false, toKey, comparable(toKey), inclusive, false);
+    @Override public GridCursor<V> find(K lower, boolean lowerInclusive,
+                                        K upper, boolean upperInclusive) throws IgniteCheckedException {
+        if (lower == null)
+            if (upper == null) // all
+                return new GridCursorIteratorWrapper<>(values().iterator());
+            else // head
+                return new GridCursorIteratorWrapper<>(headMap(upper, upperInclusive).values().iterator());
+        else
+            if (upper == null) // tail
+                return new GridCursorIteratorWrapper<>(tailMap(lower, lowerInclusive).values().iterator());
+            else // interval
+                return new GridCursorIteratorWrapper<>(subMap(lower, lowerInclusive, upper, upperInclusive)
+                    .values().iterator());
     }
 
-    /** {@inheritDoc} */
-    @Override public IgniteTree<K, V> tailTree(final K fromKey, final boolean inclusive) {
-        return new SubMap<K,V>(this, fromKey, comparable(fromKey), inclusive, null, null, false, false);
+    public GridCursor<V> find(K lower, K upper) throws IgniteCheckedException {
+        return find(lower, true, upper, true);
     }
 
-    /** {@inheritDoc} */
-    @Override public IgniteTree<K, V> subTree(final K fromKey, final boolean fromInclusive, final K toKey,
-        final boolean toInclusive) {
-        final Comparable<? super K> fromCmp = comparable(fromKey);
-        if (fromCmp.compareTo(toKey) > 0) {
-            throw new IllegalArgumentException();
-        }
-        return new SubMap<K,V>(this, fromKey, fromCmp, fromInclusive, toKey, comparable(toKey), toInclusive, false);
+    public GridCursor<V> findAll() throws IgniteCheckedException {
+        return find(null, null);
+    }
+
+    @Override public V findOne(K key) throws IgniteCheckedException {
+        return get(key);
+    }
+
+    @Override public long treeSize() throws IgniteCheckedException {
+        return size();
+    }
+
+    @Override public V put(V value) throws IgniteCheckedException {
+        return put((K)value, value);
+    }
+
+    @Override public V removeNode(K key) throws IgniteCheckedException {
+        return remove(key);
     }
 
     private static class SubMap<K, V> extends AbstractMap<K, V> implements ConcurrentNavigableMap<K, V>, Serializable,
@@ -2893,20 +2914,43 @@ public class SnapTreeMap<K, V> extends AbstractMap<K, V> implements ConcurrentNa
 
         /////// IgniteTree
 
-        /** {@inheritDoc} */
-        @Override public IgniteTree<K, V> headTree(final K toKey, final boolean inclusive) {
-            return headMap(toKey, inclusive);
+        @Override public V findOne(K key) throws IgniteCheckedException {
+            return get(key);
+        }
+
+        @Override public GridCursor<V> find(K lower, boolean lowerInclusive,
+                                            K upper, boolean upperInclusive) throws IgniteCheckedException {
+
+            if (lower == null)
+                if (upper == null) // all
+                    return new GridCursorIteratorWrapper<>(values().iterator());
+                else // head
+                    return new GridCursorIteratorWrapper<>(headMap(upper, upperInclusive).values().iterator());
+            else
+            if (upper == null) // tail
+                return new GridCursorIteratorWrapper<>(tailMap(lower, lowerInclusive).values().iterator());
+            else // interval
+                return new GridCursorIteratorWrapper<>(subMap(lower, lowerInclusive, upper, upperInclusive).values().iterator());
+        }
+
+        public GridCursor<V> find(K lower, K upper) throws IgniteCheckedException {
+            return find(lower, true, upper, true);
+        }
+
+        public GridCursor<V> findAll() throws IgniteCheckedException {
+            return find(null, null);
+        }
+
+        @Override public long treeSize() throws IgniteCheckedException {
+            return size();
         }
 
-        /** {@inheritDoc} */
-        @Override public IgniteTree<K, V> tailTree(final K fromKey, final boolean inclusive) {
-            return tailMap(fromKey, inclusive);
+        @Override public V put(V value) throws IgniteCheckedException {
+            return put((K)value, value);
         }
 
-        /** {@inheritDoc} */
-        @Override public IgniteTree<K, V> subTree(final K fromKey, final boolean fromInclusive, final K toKey,
-            final boolean toInclusive) {
-            return subMap(fromKey, fromInclusive, toKey, toInclusive);
+        @Override public V removeNode(K key) throws IgniteCheckedException {
+            return remove(key);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/b2999f2e/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/H2Cursor.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/H2Cursor.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/H2Cursor.java
new file mode 100644
index 0000000..d3b6265
--- /dev/null
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/H2Cursor.java
@@ -0,0 +1,84 @@
+package org.apache.ignite.internal.processors.query.h2;
+
+import org.apache.ignite.*;
+import org.apache.ignite.internal.processors.query.h2.opt.*;
+import org.apache.ignite.internal.util.lang.*;
+import org.apache.ignite.internal.util.typedef.internal.*;
+import org.apache.ignite.lang.*;
+import org.h2.index.*;
+import org.h2.message.*;
+import org.h2.result.*;
+
+/**
+ * Cursor.
+ */
+public class H2Cursor implements Cursor {
+    /** */
+    final GridCursor<GridH2Row> cursor;
+
+    /** */
+    final IgniteBiPredicate<Object,Object> filter;
+
+    /** */
+    final long time = U.currentTimeMillis();
+
+    /**
+     * @param cursor Cursor.
+     * @param filter Filter.
+     */
+    public H2Cursor(GridCursor<GridH2Row> cursor, IgniteBiPredicate<Object, Object> filter) {
+        assert cursor != null;
+
+        this.cursor = cursor;
+        this.filter = filter;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Row get() {
+        try {
+            return cursor.get();
+        }
+        catch (IgniteCheckedException e) {
+            throw DbException.convert(e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public SearchRow getSearchRow() {
+        return get();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean next() {
+        try {
+            while (cursor.next()) {
+                GridH2Row row = cursor.get();
+
+                if (row.expireTime() > 0 && row.expireTime() <= time)
+                    continue;
+
+                if (filter == null)
+                    return true;
+
+                Object key = row.getValue(0).getObject();
+                Object val = row.getValue(1).getObject();
+
+                assert key != null;
+                assert val != null;
+
+                if (filter.apply(key, val))
+                    return true;
+            }
+
+            return false;
+        }
+        catch (IgniteCheckedException e) {
+            throw DbException.convert(e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean previous() {
+        throw DbException.getUnsupportedException("previous");
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/b2999f2e/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 55d1b57..47ca598 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
@@ -98,7 +98,6 @@ import org.apache.ignite.internal.processors.query.h2.opt.GridH2Row;
 import org.apache.ignite.internal.processors.query.h2.opt.GridH2RowDescriptor;
 import org.apache.ignite.internal.processors.query.h2.opt.GridH2RowFactory;
 import org.apache.ignite.internal.processors.query.h2.opt.GridH2Table;
-import org.apache.ignite.internal.processors.query.h2.opt.GridH2TreeIndex;
 import org.apache.ignite.internal.processors.query.h2.opt.GridH2ValueCacheObject;
 import org.apache.ignite.internal.processors.query.h2.opt.GridLuceneIndex;
 import org.apache.ignite.internal.processors.query.h2.sql.GridSqlQuerySplitter;
@@ -2431,7 +2430,7 @@ public class IgniteH2Indexing implements GridQueryIndexing {
 
             // Add explicit affinity key index if nothing alike was found.
             if (affCol != null && !affIdxFound) {
-                idxs.add(new GridH2TreeIndex("AFFINITY_KEY", tbl, false,
+                idxs.add(createSortedIndex(cacheId, "AFFINITY_KEY", tbl, false,
                     treeIndexColumns(new ArrayList<IndexColumn>(2), affCol, keyCol)));
             }
 
@@ -2454,14 +2453,14 @@ public class IgniteH2Indexing implements GridQueryIndexing {
             List<IndexColumn> cols
         ) {
             try {
-                GridCacheSharedContext<Object,Object> scctx = ctx.cache().context();
+                GridCacheSharedContext<Object, Object> scctx = ctx.cache().context();
 
                 GridCacheContext cctx = scctx.cacheContext(cacheId);
 
-                if (cctx.affinityNode() && cctx.offheapIndex())
-                    return createIndex(cctx, name, tbl, pk, cols);
+                if (log.isInfoEnabled())
+                    log.info("Creating cache index [cacheId=" + cctx.cacheId() + ", idxName=" + name + ']');
 
-                return new GridH2TreeIndex(name, tbl, pk, cols);
+                return new H2TreeIndex(cctx, tbl, name, pk, cols);
             }
             catch (IgniteCheckedException e) {
                 throw new IgniteException(e);
@@ -2469,31 +2468,6 @@ public class IgniteH2Indexing implements GridQueryIndexing {
         }
 
         /**
-         * @param name Index name.
-         * @param tbl Table.
-         * @param pk Primary key flag.
-         * @param cols Columns.
-         * @return Index.
-         */
-        private Index createIndex(
-            GridCacheContext cctx,
-            String name,
-            GridH2Table tbl,
-            boolean pk,
-            List<IndexColumn> cols
-        ) throws IgniteCheckedException {
-            if (log.isInfoEnabled())
-                log.info("Creating cache index [cacheId=" + cctx.cacheId() + ", idxName=" + name + ']');
-
-            return new H2TreeIndex(
-                cctx,
-                tbl,
-                name,
-                pk,
-                cols);
-        }
-
-        /**
          *
          */
         void onDrop() {

http://git-wip-us.apache.org/repos/asf/ignite/blob/b2999f2e/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2TreeIndex.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2TreeIndex.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2TreeIndex.java
index 8bd8ebe..b56b1ed 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2TreeIndex.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2TreeIndex.java
@@ -26,18 +26,16 @@ import org.apache.ignite.internal.processors.cache.database.IgniteCacheDatabaseS
 import org.apache.ignite.internal.processors.cache.database.RootPage;
 import org.apache.ignite.internal.processors.cache.database.tree.BPlusTree;
 import org.apache.ignite.internal.processors.cache.database.tree.io.BPlusIO;
-import org.apache.ignite.internal.processors.query.h2.opt.GridH2IndexBase;
-import org.apache.ignite.internal.processors.query.h2.opt.GridH2Row;
-import org.apache.ignite.internal.processors.query.h2.opt.GridH2Table;
-import org.apache.ignite.internal.util.lang.GridCursor;
-import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.internal.processors.query.h2.*;
+import org.apache.ignite.internal.processors.query.h2.opt.*;
+import org.apache.ignite.internal.util.*;
+import org.apache.ignite.internal.util.lang.*;
 import org.apache.ignite.lang.IgniteBiPredicate;
 import org.apache.ignite.spi.indexing.IndexingQueryFilter;
 import org.h2.engine.Session;
 import org.h2.index.Cursor;
 import org.h2.index.IndexType;
 import org.h2.message.DbException;
-import org.h2.result.Row;
 import org.h2.result.SearchRow;
 import org.h2.result.SortOrder;
 import org.h2.table.IndexColumn;
@@ -215,77 +213,27 @@ public class H2TreeIndex extends GridH2IndexBase {
         return this;
     }
 
-    /**
-     * Cursor.
-     */
-    private static class H2Cursor implements Cursor {
-        /** */
-        final GridCursor<GridH2Row> cursor;
-
-        /** */
-        final IgniteBiPredicate<Object,Object> filter;
-
-        /** */
-        final long time = U.currentTimeMillis();
-
-        /**
-         * @param cursor Cursor.
-         * @param filter Filter.
-         */
-        private H2Cursor(GridCursor<GridH2Row> cursor, IgniteBiPredicate<Object,Object> filter) {
-            assert cursor != null;
-
-            this.cursor = cursor;
-            this.filter = filter;
-        }
-
-        /** {@inheritDoc} */
-        @Override public Row get() {
-            try {
-                return cursor.get();
-            }
-            catch (IgniteCheckedException e) {
-                throw DbException.convert(e);
-            }
-        }
-
-        /** {@inheritDoc} */
-        @Override public SearchRow getSearchRow() {
-            return get();
-        }
-
-        /** {@inheritDoc} */
-        @Override public boolean next() {
-            try {
-                while (cursor.next()) {
-                    GridH2Row row = cursor.get();
-
-                    if (row.expireTime() > 0 && row.expireTime() <= time)
-                        continue;
-
-                    if (filter == null)
-                        return true;
+    protected IgniteTree<SearchRow, GridH2Row> treeForRead() {
+        return tree;
+    }
 
-                    Object key = row.getValue(0).getObject();
-                    Object val = row.getValue(1).getObject();
+    protected GridCursor<GridH2Row> doFind0(IgniteTree t,
+        @Nullable SearchRow first,
+        boolean includeFirst,
+        @Nullable SearchRow last,
+        IndexingQueryFilter filter) {
+        includeFirst &= first != null;
 
-                    assert key != null;
-                    assert val != null;
+        try {
+            GridCursor<GridH2Row> range = tree.find(first, last);
 
-                    if (filter.apply(key, val))
-                        return true;
-                }
+            if (range == null)
+                return EMPTY_CURSOR;
 
-                return false;
-            }
-            catch (IgniteCheckedException e) {
-                throw DbException.convert(e);
-            }
+            return filter(range, filter);
         }
-
-        /** {@inheritDoc} */
-        @Override public boolean previous() {
-            throw DbException.getUnsupportedException("previous");
+        catch (IgniteCheckedException e) {
+            throw DbException.convert(e);
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/b2999f2e/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2IndexBase.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2IndexBase.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2IndexBase.java
index 032b548..84d3b6a 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2IndexBase.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2IndexBase.java
@@ -44,7 +44,7 @@ import org.apache.ignite.internal.processors.query.h2.twostep.msg.GridH2RowRange
 import org.apache.ignite.internal.processors.query.h2.twostep.msg.GridH2ValueMessage;
 import org.apache.ignite.internal.processors.query.h2.twostep.msg.GridH2ValueMessageFactory;
 import org.apache.ignite.internal.util.*;
-import org.apache.ignite.internal.util.lang.GridFilteredIterator;
+import org.apache.ignite.internal.util.lang.*;
 import org.apache.ignite.internal.util.typedef.CIX2;
 import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.internal.CU;
@@ -306,12 +306,12 @@ public abstract class GridH2IndexBase extends BaseIndex {
     /**
      * Filters rows from expired ones and using predicate.
      *
-     * @param iter Iterator over rows.
+     * @param cursor GridCursor over rows.
      * @param filter Optional filter.
      * @return Filtered iterator.
      */
-    protected Iterator<GridH2Row> filter(Iterator<GridH2Row> iter, IndexingQueryFilter filter) {
-        return new FilteringIterator(iter, U.currentTimeMillis(), filter, getTable().spaceName());
+    protected GridCursor<GridH2Row> filter(GridCursor<GridH2Row> cursor, IndexingQueryFilter filter) {
+        return new FilteringCursor(cursor, U.currentTimeMillis(), filter, getTable().spaceName());
     }
 
     /**
@@ -460,13 +460,7 @@ public abstract class GridH2IndexBase extends BaseIndex {
 
                     assert !msg.bounds().isEmpty() : "empty bounds";
 
-                    IgniteTree snapshotTree;
-
-                    if (snapshot0 instanceof IgniteTree)
-                        snapshotTree = (IgniteTree)snapshot0;
-                    else
-                        snapshotTree = new IgniteNavigableMapTree(
-                            (NavigableMap<GridSearchRowPointer, GridH2Row>) snapshot0);
+                    IgniteTree snapshotTree = (IgniteTree)snapshot0;
 
                     src = new RangeSource(msg.bounds(), snapshotTree, qctx.filter());
                 }
@@ -1367,7 +1361,7 @@ public abstract class GridH2IndexBase extends BaseIndex {
         int curRangeId = -1;
 
         /** */
-        Iterator<GridH2Row> curRange = emptyIterator();
+        GridCursor<GridH2Row> curRange = EMPTY_CURSOR;
 
         /** */
         final IgniteTree tree;
@@ -1393,8 +1387,8 @@ public abstract class GridH2IndexBase extends BaseIndex {
         /**
          * @return {@code true} If there are more rows in this source.
          */
-        public boolean hasMoreRows() {
-            return boundsIter.hasNext() || curRange.hasNext();
+        public boolean hasMoreRows() throws IgniteCheckedException {
+            return boundsIter.hasNext() || curRange.next();
         }
 
         /**
@@ -1404,56 +1398,60 @@ public abstract class GridH2IndexBase extends BaseIndex {
         public GridH2RowRange next(int maxRows) {
             assert maxRows > 0 : maxRows;
 
-            for (;;) {
-                if (curRange.hasNext()) {
-                    // Here we are getting last rows from previously partially fetched range.
-                    List<GridH2RowMessage> rows = new ArrayList<>();
+            try {
+                for (;;) {
+                    if (curRange.next()) {
+                        // Here we are getting last rows from previously partially fetched range.
+                        List<GridH2RowMessage> rows = new ArrayList<>();
 
-                    GridH2RowRange nextRange = new GridH2RowRange();
+                        GridH2RowRange nextRange = new GridH2RowRange();
 
-                    nextRange.rangeId(curRangeId);
-                    nextRange.rows(rows);
+                        nextRange.rangeId(curRangeId);
+                        nextRange.rows(rows);
 
-                    do {
-                        rows.add(toRowMessage(curRange.next()));
-                    }
-                    while (rows.size() < maxRows && curRange.hasNext());
+                        do {
+                            rows.add(toRowMessage(curRange.get()));
+                        }
+                        while (rows.size() < maxRows && curRange.next());
 
-                    if (curRange.hasNext())
-                        nextRange.setPartial();
-                    else
-                        curRange = emptyIterator();
+                        if (curRange.next())
+                            nextRange.setPartial();
+                        else
+                            curRange = EMPTY_CURSOR;
 
-                    return nextRange;
-                }
+                        return nextRange;
+                    }
 
-                curRange = emptyIterator();
+                    curRange = EMPTY_CURSOR;
 
-                if (!boundsIter.hasNext()) {
-                    boundsIter = emptyIterator();
+                    if (!boundsIter.hasNext()) {
+                        boundsIter = emptyIterator();
 
-                    return null;
-                }
+                        return null;
+                    }
 
-                GridH2RowRangeBounds bounds = boundsIter.next();
+                    GridH2RowRangeBounds bounds = boundsIter.next();
 
-                curRangeId = bounds.rangeId();
+                    curRangeId = bounds.rangeId();
 
-                SearchRow first = toSearchRow(bounds.first());
-                SearchRow last = toSearchRow(bounds.last());
+                    SearchRow first = toSearchRow(bounds.first());
+                    SearchRow last = toSearchRow(bounds.last());
 
-                IgniteTree t = tree != null ? tree : treeForRead();
+                    IgniteTree t = tree != null ? tree : treeForRead();
 
-                curRange = doFind0(t, first, true, last, filter);
+                    curRange = doFind0(t, first, true, last, filter);
 
-                if (!curRange.hasNext()) {
-                    // We have to return empty range here.
-                    GridH2RowRange emptyRange = new GridH2RowRange();
+                    if (!curRange.next()) {
+                        // We have to return empty range here.
+                        GridH2RowRange emptyRange = new GridH2RowRange();
 
-                    emptyRange.rangeId(curRangeId);
+                        emptyRange.rangeId(curRangeId);
 
-                    return emptyRange;
+                        return emptyRange;
+                    }
                 }
+            } catch (IgniteCheckedException e) {
+                throw DbException.convert(e);
             }
         }
     }
@@ -1461,7 +1459,7 @@ public abstract class GridH2IndexBase extends BaseIndex {
     /**
      * @return Snapshot for current thread if there is one.
      */
-    protected IgniteTree treeForRead() {
+    protected <K, V> IgniteTree<K, V> treeForRead() {
         throw new UnsupportedOperationException();
     }
 
@@ -1473,7 +1471,7 @@ public abstract class GridH2IndexBase extends BaseIndex {
      * @param filter Filter.
      * @return Iterator over rows in given range.
      */
-    protected Iterator<GridH2Row> doFind0(IgniteTree t,
+    protected GridCursor<GridH2Row> doFind0(IgniteTree t,
         @Nullable SearchRow first,
         boolean includeFirst,
         @Nullable SearchRow last,
@@ -1482,9 +1480,11 @@ public abstract class GridH2IndexBase extends BaseIndex {
     }
 
     /**
-     * Iterator which filters by expiration time and predicate.
+     * Cursor which filters by expiration time and predicate.
      */
-    protected static class FilteringIterator extends GridFilteredIterator<GridH2Row> {
+    protected static class FilteringCursor implements GridCursor<GridH2Row> {
+        /** */
+        private final GridCursor<GridH2Row> cursor;
         /** */
         private final IgniteBiPredicate<Object, Object> fltr;
 
@@ -1494,17 +1494,19 @@ public abstract class GridH2IndexBase extends BaseIndex {
         /** Is value required for filtering predicate? */
         private final boolean isValRequired;
 
+        private GridH2Row next;
+
         /**
-         * @param iter Iterator.
+         * @param cursor GridCursor.
          * @param time Time for expired rows filtering.
          * @param qryFilter Filter.
          * @param spaceName Space name.
          */
-        protected FilteringIterator(Iterator<GridH2Row> iter,
+        protected FilteringCursor(GridCursor<GridH2Row> cursor,
             long time,
             IndexingQueryFilter qryFilter,
             String spaceName) {
-            super(iter);
+            this.cursor = cursor;
 
             this.time = time;
 
@@ -1524,7 +1526,7 @@ public abstract class GridH2IndexBase extends BaseIndex {
          * @return If this row was accepted.
          */
         @SuppressWarnings("unchecked")
-        @Override protected boolean accept(GridH2Row row) {
+        protected boolean accept(GridH2Row row) {
             if (row.expireTime() <= time)
                 return false;
 
@@ -1539,62 +1541,40 @@ public abstract class GridH2IndexBase extends BaseIndex {
 
             return fltr.apply(key, val);
         }
-    }
-
-    /**
-     * Adapter from {@link NavigableMap} to {@link IgniteTree}.
-     */
-    protected static class IgniteNavigableMapTree implements IgniteTree<GridSearchRowPointer, GridH2Row> {
-        private NavigableMap<GridSearchRowPointer, GridH2Row> tree;
-
-        /**
-         * @param map the {@link NavigableMap} which should be adapted.
-         */
-        public IgniteNavigableMapTree(final NavigableMap<GridSearchRowPointer, GridH2Row> map) {
-            this.tree = map;
-        }
 
-        /** {@inheritDoc} */
-        @Override public GridH2Row put(final GridSearchRowPointer key, final GridH2Row value) {
-            return tree.put(key, value);
-        }
+        @Override public boolean next() throws IgniteCheckedException {
+            next = null;
 
-        /** {@inheritDoc} */
-        @Override public GridH2Row get(final Object key) {
-            return tree.get(key);
-        }
+            while (cursor.next()) {
+                GridH2Row t = cursor.get();
 
-        /** {@inheritDoc} */
-        @Override public GridH2Row remove(final Object key) {
-            return tree.remove(key);
-        }
+                if (accept(t)) {
+                    next = t;
+                    return true;
+                }
+            }
 
-        /** {@inheritDoc} */
-        @Override public int size() {
-            return tree.size();
+            return false;
         }
 
-        /** {@inheritDoc} */
-        @Override public Collection<GridH2Row> values() {
-            return tree.values();
-        }
+        @Override public GridH2Row get() throws IgniteCheckedException {
+            if (next == null)
+                throw new NoSuchElementException();
 
-        /** {@inheritDoc} */
-        @Override
-        public IgniteTree<GridSearchRowPointer, GridH2Row> headTree(GridSearchRowPointer toKey, boolean inclusive) {
-            return new IgniteNavigableMapTree(tree.headMap(toKey, inclusive));
+            return next;
         }
+    }
 
+    /** Empty cursor. */
+    protected static final GridCursor<GridH2Row> EMPTY_CURSOR = new GridCursor<GridH2Row>() {
         /** {@inheritDoc} */
-        @Override
-        public IgniteTree<GridSearchRowPointer, GridH2Row> tailTree(GridSearchRowPointer fromKey, boolean inclusive) {
-            return new IgniteNavigableMapTree(tree.tailMap(fromKey, inclusive));
+        @Override public boolean next() {
+            return false;
         }
 
         /** {@inheritDoc} */
-        @Override public IgniteTree<GridSearchRowPointer, GridH2Row> subTree(GridSearchRowPointer fromKey,
-            boolean fromInclusive, GridSearchRowPointer toKey, boolean toInclusive) {
-            return new IgniteNavigableMapTree(tree.subMap(fromKey, fromInclusive, toKey, toInclusive));
+        @Override public GridH2Row get() {
+            return null;
         }
-    }
+    };
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/b2999f2e/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java
index ef3dd35..bf390ba 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java
@@ -34,7 +34,7 @@ import org.apache.ignite.internal.processors.cache.CacheObject;
 import org.apache.ignite.internal.processors.cache.GridCacheContext;
 import org.apache.ignite.internal.processors.cache.KeyCacheObject;
 import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
-import org.apache.ignite.internal.processors.query.h2.database.H2RowFactory;
+import org.apache.ignite.internal.processors.query.h2.database.*;
 import org.apache.ignite.internal.util.offheap.unsafe.GridUnsafeMemory;
 import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.lang.IgniteBiTuple;
@@ -893,7 +893,7 @@ public class GridH2Table extends TableBase {
         /**
          * Create list of indexes. First must be primary key, after that all unique indexes and
          * only then non-unique indexes.
-         * All indexes must be subtypes of {@link GridH2TreeIndex}.
+         * All indexes must be subtypes of {@link H2TreeIndex}.
          *
          * @param tbl Table to create indexes for.
          * @return List of indexes.

http://git-wip-us.apache.org/repos/asf/ignite/blob/b2999f2e/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2TreeIndex.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2TreeIndex.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2TreeIndex.java
index b4cd76f..e03c1a1 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2TreeIndex.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2TreeIndex.java
@@ -18,13 +18,14 @@
 package org.apache.ignite.internal.processors.query.h2.opt;
 
 import java.util.Comparator;
-import java.util.Iterator;
 import java.util.List;
 import java.util.NavigableMap;
-import java.util.concurrent.ConcurrentNavigableMap;
 import java.util.concurrent.ConcurrentSkipListMap;
 
+import org.apache.ignite.*;
+import org.apache.ignite.internal.processors.query.h2.*;
 import org.apache.ignite.internal.util.*;
+import org.apache.ignite.internal.util.lang.*;
 import org.apache.ignite.internal.util.offheap.unsafe.GridOffHeapSnapTreeMap;
 import org.apache.ignite.internal.util.offheap.unsafe.GridUnsafeGuard;
 import org.apache.ignite.internal.util.snaptree.SnapTreeMap;
@@ -93,7 +94,7 @@ public class GridH2TreeIndex extends GridH2IndexBase implements Comparator<GridS
             }
             else {
                 tree = new IgniteNavigableMapTree(
-                    new ConcurrentSkipListMap<>(
+                    new ConcurrentSkipListMap<GridSearchRowPointer, GridH2Row>(
                         new Comparator<GridSearchRowPointer>() {
                             @Override public int compare(GridSearchRowPointer o1, GridSearchRowPointer o2) {
                                 if (o1 instanceof ComparableRow)
@@ -178,16 +179,22 @@ public class GridH2TreeIndex extends GridH2IndexBase implements Comparator<GridS
 
         // Fast path if we don't need to perform any filtering.
         if (f == null || f.forSpace((getTable()).spaceName()) == null)
-            return treeForRead().size();
+            try {
+                return treeForRead().treeSize();
+            } catch (IgniteCheckedException e) {
+                throw DbException.convert(e);
+            }
 
-        Iterator<GridH2Row> iter = doFind(null, false, null);
+        GridCursor<GridH2Row> cursor = doFind(null, false, null);
 
         long size = 0;
 
-        while (iter.hasNext()) {
-            iter.next();
-
-            size++;
+        try {
+            while (cursor.next())
+                size++;
+        }
+        catch (IgniteCheckedException e) {
+            throw DbException.convert(e);
         }
 
         return size;
@@ -240,12 +247,12 @@ public class GridH2TreeIndex extends GridH2IndexBase implements Comparator<GridS
 
     /** {@inheritDoc} */
     @Override public Cursor find(Session ses, @Nullable SearchRow first, @Nullable SearchRow last) {
-        return new GridH2Cursor(doFind(first, true, last));
+        return new H2Cursor(doFind(first, true, last), null);
     }
 
     /** {@inheritDoc} */
     @Override public Cursor findNext(Session ses, SearchRow higherThan, SearchRow last) {
-        return new GridH2Cursor(doFind(higherThan, false, last));
+        return new H2Cursor(doFind(higherThan, false, last), null);
     }
 
     /**
@@ -257,7 +264,11 @@ public class GridH2TreeIndex extends GridH2IndexBase implements Comparator<GridS
      * @return Row.
      */
     public GridH2Row findOne(GridH2Row row) {
-        return tree.get(row);
+        try {
+            return tree.findOne(row);
+        } catch (IgniteCheckedException e) {
+            throw DbException.convert(e);
+        }
     }
 
     /**
@@ -269,14 +280,14 @@ public class GridH2TreeIndex extends GridH2IndexBase implements Comparator<GridS
      * @return Iterator over rows in given range.
      */
     @SuppressWarnings("unchecked")
-    private Iterator<GridH2Row> doFind(@Nullable SearchRow first, boolean includeFirst, @Nullable SearchRow last) {
+    private GridCursor<GridH2Row> doFind(@Nullable SearchRow first, boolean includeFirst, @Nullable SearchRow last) {
         IgniteTree t = treeForRead();
 
         return doFind0(t, first, includeFirst, last, threadLocalFilter());
     }
 
     /** {@inheritDoc} */
-    @Override protected final Iterator<GridH2Row> doFind0(
+    @Override protected final GridCursor<GridH2Row> doFind0(
         IgniteTree t,
         @Nullable SearchRow first,
         boolean includeFirst,
@@ -285,13 +296,13 @@ public class GridH2TreeIndex extends GridH2IndexBase implements Comparator<GridS
     ) {
         includeFirst &= first != null;
 
-        IgniteTree<GridSearchRowPointer, GridH2Row> range = subTree(t, comparable(first, includeFirst ? -1 : 1),
+        GridCursor<GridH2Row> range = subTree(t, comparable(first, includeFirst ? -1 : 1),
             comparable(last, 1));
 
         if (range == null)
-            return new GridEmptyIterator<>();
+            return EMPTY_CURSOR;
 
-        return filter(range.values().iterator(), filter);
+        return filter(range, filter);
     }
 
     /**
@@ -318,25 +329,19 @@ public class GridH2TreeIndex extends GridH2IndexBase implements Comparator<GridS
      * @return Sub-map.
      */
     @SuppressWarnings({"IfMayBeConditional", "TypeMayBeWeakened"})
-    private IgniteTree subTree(IgniteTree tree,
+    private GridCursor<GridH2Row> subTree(IgniteTree tree,
         @Nullable GridSearchRowPointer first, @Nullable GridSearchRowPointer last) {
-        // We take exclusive bounds because it is possible that one search row will be equal to multiple key rows
-        // in tree and we must return them all.
-        if (first == null) {
-            if (last == null)
-                return tree;
-            else
-                return tree.headTree(last, false);
-        }
-        else {
-            if (last == null)
-                return tree.tailTree(first, false);
-            else {
-                if (compare(first, last) > 0)
-                    return null;
 
-                return tree.subTree(first, false, last, false);
-            }
+        if (first != null && last != null && compare(first, last) > 0)
+            return null;
+
+        try {
+            // We take exclusive bounds because it is possible that one search row will be equal to multiple key rows
+            // in tree and we must return them all.
+            return tree.find(first, false, last, false);
+        }
+        catch (IgniteCheckedException e) {
+            throw DbException.convert(e);
         }
     }
 
@@ -345,7 +350,7 @@ public class GridH2TreeIndex extends GridH2IndexBase implements Comparator<GridS
      *
      * @return Rows iterator.
      */
-    Iterator<GridH2Row> rows() {
+    GridCursor<GridH2Row> rows() {
         return doFind(null, false, null);
     }
 
@@ -361,12 +366,22 @@ public class GridH2TreeIndex extends GridH2IndexBase implements Comparator<GridS
 
     /** {@inheritDoc} */
     @Override public GridH2Row put(GridH2Row row) {
-        return tree.put(row, row);
+        try {
+            return tree.put(row);
+        }
+        catch (IgniteCheckedException e) {
+            throw DbException.convert(e);
+        }
     }
 
     /** {@inheritDoc} */
     @Override public GridH2Row remove(SearchRow row) {
-        return tree.remove(comparable(row, 0));
+        try {
+            return tree.removeNode(comparable(row, 0));
+        }
+        catch (IgniteCheckedException e) {
+            throw DbException.convert(e);
+        }
     }
 
     /**
@@ -471,14 +486,69 @@ public class GridH2TreeIndex extends GridH2IndexBase implements Comparator<GridS
 
         long i = 0;
 
-        for (GridH2Row row : tree.values()) {
-            // Check for interruptions every 1000 iterations.
-            if (++i % 1000 == 0 && thread.isInterrupted())
-                throw new InterruptedException();
+        try {
+            GridCursor<GridH2Row> cursor = tree.findAll();
 
-            idx.tree.put(row, row);
+            while(cursor.next()) {
+                GridH2Row row = cursor.get();
+
+                // Check for interruptions every 1000 iterations.
+                if (++i % 1000 == 0 && thread.isInterrupted())
+                    throw new InterruptedException();
+
+                idx.tree.put(row);
+            }
+        }
+        catch (IgniteCheckedException e) {
+            throw DbException.convert(e);
         }
 
         return idx;
     }
+
+    /**
+     * Adapter from {@link NavigableMap} to {@link IgniteTree}.
+     */
+    private final class IgniteNavigableMapTree implements IgniteTree<GridSearchRowPointer, GridH2Row> {
+        private NavigableMap<GridSearchRowPointer, GridH2Row> tree;
+
+        public IgniteNavigableMapTree(NavigableMap<GridSearchRowPointer, GridH2Row> tree) {
+            this.tree = tree;
+        }
+
+        @Override public GridH2Row put(GridH2Row value) throws IgniteCheckedException {
+            return tree.put(value, value);
+        }
+
+        @Override public GridH2Row findOne(GridSearchRowPointer key) throws IgniteCheckedException {
+            return tree.get(key);
+        }
+
+        @Override public GridCursor<GridH2Row> find(GridSearchRowPointer lower, boolean lowerInclusive,
+                                                    GridSearchRowPointer upper, boolean upperInclusive)
+            throws IgniteCheckedException {
+
+            NavigableMap<GridSearchRowPointer, GridH2Row> subMap =
+                tree.subMap(lower, lowerInclusive, upper, upperInclusive);
+
+            return new GridCursorIteratorWrapper<GridH2Row>(subMap.values().iterator());
+        }
+
+        public GridCursor<GridH2Row> find(GridSearchRowPointer lower, GridSearchRowPointer upper)
+            throws IgniteCheckedException {
+            return find(lower, true, upper, true);
+        }
+
+        public GridCursor<GridH2Row> findAll() throws IgniteCheckedException {
+            return find(null, null);
+        }
+
+        @Override public GridH2Row removeNode(GridSearchRowPointer key) throws IgniteCheckedException {
+            return tree.remove(key);
+        }
+
+        @Override public long treeSize() throws IgniteCheckedException {
+            return tree.size();
+        }
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/b2999f2e/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractQuerySelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractQuerySelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractQuerySelfTest.java
index e4b7dd3..15f110f 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractQuerySelfTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractQuerySelfTest.java
@@ -172,7 +172,7 @@ public abstract class IgniteCacheAbstractQuerySelfTest extends GridCommonAbstrac
         if (cacheMode() == CacheMode.PARTITIONED)
             cc.setBackups(gridCount());
 
-        cc.setSnapshotableIndex(snapshotableIndex());
+        //cc.setSnapshotableIndex(snapshotableIndex());
 
         return cc;
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/b2999f2e/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2TableSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2TableSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2TableSelfTest.java
index a0ac181..5daf415 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2TableSelfTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2TableSelfTest.java
@@ -33,7 +33,10 @@ import java.util.Set;
 import java.util.UUID;
 import java.util.concurrent.Callable;
 import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.ignite.*;
 import org.apache.ignite.internal.processors.query.h2.database.H2RowFactory;
+import org.apache.ignite.internal.util.lang.*;
 import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
 import org.h2.Driver;
@@ -283,11 +286,11 @@ public class GridH2TableSelfTest extends GridCommonAbstractTest {
      *
      * @param idx Index.
      */
-    private void dumpRows(GridH2TreeIndex idx) {
-        Iterator<GridH2Row> iter = idx.rows();
+    private void dumpRows(GridH2TreeIndex idx) throws IgniteCheckedException {
+        GridCursor<GridH2Row> cursor = idx.rows();
 
-        while (iter.hasNext())
-            System.out.println(iter.next().toString());
+        while (cursor.next())
+            System.out.println(cursor.get().toString());
     }
 
     /**
@@ -584,17 +587,17 @@ public class GridH2TableSelfTest extends GridCommonAbstractTest {
      * @param rowSet Rows.
      * @return Rows.
      */
-    private Set<Row> checkIndexesConsistent(ArrayList<Index> idxs, @Nullable Set<Row> rowSet) {
+    private Set<Row> checkIndexesConsistent(ArrayList<Index> idxs, @Nullable Set<Row> rowSet) throws IgniteCheckedException {
         for (Index idx : idxs) {
             if (!(idx instanceof GridH2TreeIndex))
                 continue;
 
             Set<Row> set = new HashSet<>();
 
-            Iterator<GridH2Row> iter = ((GridH2TreeIndex)idx).rows();
+            GridCursor<GridH2Row> cursor = ((GridH2TreeIndex)idx).rows();
 
-            while(iter.hasNext())
-                assertTrue(set.add(iter.next()));
+            while(cursor.next())
+                assertTrue(set.add(cursor.get()));
 
             //((GridH2SnapTreeSet)((GridH2Index)idx).tree).print();
 
@@ -610,7 +613,7 @@ public class GridH2TableSelfTest extends GridCommonAbstractTest {
     /**
      * @param idxs Indexes list.
      */
-    private void checkOrdered(ArrayList<Index> idxs) {
+    private void checkOrdered(ArrayList<Index> idxs) throws IgniteCheckedException {
         for (Index idx : idxs) {
             if (!(idx instanceof GridH2TreeIndex))
                 continue;
@@ -625,13 +628,13 @@ public class GridH2TableSelfTest extends GridCommonAbstractTest {
      * @param idx Index.
      * @param cmp Comparator.
      */
-    private void checkOrdered(GridH2TreeIndex idx, Comparator<? super GridH2Row> cmp) {
-        Iterator<GridH2Row> rows = idx.rows();
+    private void checkOrdered(GridH2TreeIndex idx, Comparator<? super GridH2Row> cmp) throws IgniteCheckedException {
+        GridCursor<GridH2Row> cursor = idx.rows();
 
         GridH2Row min = null;
 
-        while (rows.hasNext()) {
-            GridH2Row row = rows.next();
+        while (cursor.next()) {
+            GridH2Row row = cursor.get();
 
             assertNotNull(row);