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

[2/2] ignite git commit: Page memory integration WIP

Page memory integration WIP


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

Branch: refs/heads/sql-store
Commit: 7d9f37894e764a71bc3b3be8e71960837b6d9037
Parents: 70473e7
Author: Alexey Goncharuk <al...@gmail.com>
Authored: Mon Feb 1 14:11:12 2016 +0300
Committer: Alexey Goncharuk <al...@gmail.com>
Committed: Mon Feb 1 14:11:12 2016 +0300

----------------------------------------------------------------------
 .../internal/binary/BinaryEnumObjectImpl.java   |  7 +-
 .../internal/binary/BinaryObjectImpl.java       |  6 ++
 .../binary/BinaryObjectOffheapImpl.java         |  5 ++
 .../internal/processors/cache/CacheObject.java  | 14 ++++
 .../processors/cache/CacheObjectAdapter.java    |  8 ++
 .../cache/CacheObjectByteArrayImpl.java         |  4 +
 .../processors/cache/GridCacheAdapter.java      |  4 +-
 .../processors/cache/GridCacheContext.java      |  7 ++
 .../cache/GridCacheEvictionManager.java         |  2 +-
 .../processors/cache/GridCacheMapEntry.java     | 82 ++++++++++++--------
 .../binary/CacheObjectBinaryProcessorImpl.java  |  8 ++
 .../cache/query/GridCacheQueryManager.java      | 24 +++++-
 .../cache/store/CacheStoreManager.java          |  5 ++
 .../store/GridCacheStoreManagerAdapter.java     |  5 ++
 .../cacheobject/IgniteCacheObjectProcessor.java | 15 ++++
 .../IgniteCacheObjectProcessorImpl.java         | 26 +++++++
 .../processors/query/GridQueryIndexing.java     | 16 +++-
 .../processors/query/GridQueryProcessor.java    | 31 +++++++-
 .../processors/query/h2/IgniteH2Indexing.java   | 53 +++++++++----
 .../processors/query/h2/opt/GridH2Row.java      |  7 +-
 .../query/h2/opt/GridH2RowDescriptor.java       |  3 +-
 .../processors/query/h2/opt/GridH2Table.java    | 33 +++++++-
 .../IgniteCacheQueryMultiThreadedSelfTest.java  |  4 +-
 .../h2/GridIndexingSpiAbstractSelfTest.java     | 15 +++-
 24 files changed, 307 insertions(+), 77 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/7d9f3789/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryEnumObjectImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryEnumObjectImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryEnumObjectImpl.java
index 0e5d6df..8f3f8a4 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryEnumObjectImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryEnumObjectImpl.java
@@ -113,7 +113,7 @@ public class BinaryEnumObjectImpl implements BinaryObjectEx, Externalizable, Cac
     @Override public <T> T deserialize() throws BinaryObjectException {
         Class cls = BinaryUtils.resolveClass(ctx, typeId, clsName, null, true);
 
-        return BinaryEnumCache.get(cls, ord);
+        return (T)BinaryEnumCache.get(cls, ord);
     }
 
     /** {@inheritDoc} */
@@ -212,6 +212,11 @@ public class BinaryEnumObjectImpl implements BinaryObjectEx, Externalizable, Cac
     }
 
     /** {@inheritDoc} */
+    @Override public int valueBytesLength(CacheObjectContext ctx) throws IgniteCheckedException {
+        throw new UnsupportedOperationException("TODO implement.");
+    }
+
+    /** {@inheritDoc} */
     @Override public byte cacheObjectType() {
         return TYPE_BINARY;
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/7d9f3789/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectImpl.java
index a379dbd..c1b9953 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectImpl.java
@@ -133,6 +133,7 @@ public final class BinaryObjectImpl extends BinaryObjectExImpl implements Extern
         return arr0;
     }
 
+    /** {@inheritDoc} */
     @Override public boolean putValue(ByteBuffer buf, CacheObjectContext ctx) throws IgniteCheckedException {
         int len = length();
 
@@ -147,6 +148,11 @@ public final class BinaryObjectImpl extends BinaryObjectExImpl implements Extern
     }
 
     /** {@inheritDoc} */
+    @Override public int valueBytesLength(CacheObjectContext ctx) throws IgniteCheckedException {
+        return length() + 5;
+    }
+
+    /** {@inheritDoc} */
     @Override public CacheObject prepareForCache(CacheObjectContext ctx) {
         if (detached())
             return this;

http://git-wip-us.apache.org/repos/asf/ignite/blob/7d9f3789/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectOffheapImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectOffheapImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectOffheapImpl.java
index 56d8c1f..f39ca49 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectOffheapImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectOffheapImpl.java
@@ -135,6 +135,11 @@ public class BinaryObjectOffheapImpl extends BinaryObjectExImpl implements Exter
     }
 
     /** {@inheritDoc} */
+    @Override public int valueBytesLength(CacheObjectContext ctx) throws IgniteCheckedException {
+        throw new UnsupportedOperationException("TODO implement");
+    }
+
+    /** {@inheritDoc} */
     @Override public long offheapAddress() {
         return ptr;
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/7d9f3789/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObject.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObject.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObject.java
index 6315ec3..6fdbdf2 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObject.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObject.java
@@ -49,6 +49,20 @@ public interface CacheObject extends Message {
      */
     public byte[] valueBytes(CacheObjectContext ctx) throws IgniteCheckedException;
 
+    /**
+     * @param ctx Cache object context.
+     * @return Size required to store this value object.
+     * @throws IgniteCheckedException If failed.
+     */
+    public int valueBytesLength(CacheObjectContext ctx) throws IgniteCheckedException;
+
+    /**
+     * @param buf Buffer to write value to.
+     * @param ctx Cache object context.
+     * @return {@code True} if value was successfully written, {@code false} if there was not enough space in the
+     *      buffer.
+     * @throws IgniteCheckedException If failed.
+     */
     public boolean putValue(ByteBuffer buf, CacheObjectContext ctx) throws IgniteCheckedException;
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/7d9f3789/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObjectAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObjectAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObjectAdapter.java
index 28a95d8..d1577ee 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObjectAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObjectAdapter.java
@@ -85,6 +85,14 @@ public abstract class CacheObjectAdapter implements CacheObject, Externalizable
     }
 
     /** {@inheritDoc} */
+    @Override public int valueBytesLength(CacheObjectContext ctx) throws IgniteCheckedException {
+        if (valBytes == null)
+            valueBytes(ctx);
+
+        return valBytes.length + 5;
+    }
+
+    /** {@inheritDoc} */
     @Override public boolean readFrom(ByteBuffer buf, MessageReader reader) {
         reader.setBuffer(buf);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/7d9f3789/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObjectByteArrayImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObjectByteArrayImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObjectByteArrayImpl.java
index d69e5dc..0e41b3e 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObjectByteArrayImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObjectByteArrayImpl.java
@@ -86,6 +86,10 @@ public class CacheObjectByteArrayImpl implements CacheObject, Externalizable {
         return true;
     }
 
+    @Override public int valueBytesLength(CacheObjectContext ctx) throws IgniteCheckedException {
+        return val.length + 5;
+    }
+
     /** {@inheritDoc} */
     @Override public byte cacheObjectType() {
         return TYPE_BYTE_ARR;

http://git-wip-us.apache.org/repos/asf/ignite/blob/7d9f3789/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAdapter.java
index 2582e6c..e2d73ba 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAdapter.java
@@ -1671,7 +1671,7 @@ public abstract class GridCacheAdapter<K, V> implements IgniteInternalCache<K, V
 
                 final boolean storeEnabled = !skipVals && readThrough && ctx.readThrough();
 
-                final boolean needEntry = storeEnabled || ctx.isSwapOrOffheapEnabled();
+                final boolean needEntry = storeEnabled || ctx.isSwapOrOffheapEnabled() || ctx.isDatabaseEnabled();
 
                 Map<KeyCacheObject, GridCacheVersion> misses = null;
 
@@ -1688,7 +1688,7 @@ public abstract class GridCacheAdapter<K, V> implements IgniteInternalCache<K, V
 
                         try {
                             T2<CacheObject, GridCacheVersion> res = entry.innerGetVersioned(null,
-                                ctx.isSwapOrOffheapEnabled(),
+                                ctx.isSwapOrOffheapEnabled() || ctx.isDatabaseEnabled(),
                                 /*unmarshal*/true,
                                 /*update-metrics*/!skipVals,
                                 /*event*/!skipVals,

http://git-wip-us.apache.org/repos/asf/ignite/blob/7d9f3789/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheContext.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheContext.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheContext.java
index fc48b9d..3c5ec8b 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheContext.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheContext.java
@@ -1428,6 +1428,13 @@ public class GridCacheContext<K, V> implements Externalizable {
     }
 
     /**
+     * @return If database is enabled.
+     */
+    public boolean isDatabaseEnabled() {
+        return storeMgr.isDatabaseEnabled();
+    }
+
+    /**
      * @return {@code True} if store read-through mode is enabled.
      */
     public boolean readThrough() {

http://git-wip-us.apache.org/repos/asf/ignite/blob/7d9f3789/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheEvictionManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheEvictionManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheEvictionManager.java
index 845e204..75eddf3 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheEvictionManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheEvictionManager.java
@@ -794,7 +794,7 @@ public class GridCacheEvictionManager extends GridCacheManagerAdapter {
             U.error(log, "Failed to evict entry from cache: " + e, ex);
         }
 
-        if (!cctx.isNear() && memoryMode == OFFHEAP_TIERED) {
+        if (!cctx.isNear() && (memoryMode == OFFHEAP_TIERED || cctx.isDatabaseEnabled())) {
             try {
                 evict0(cctx.cache(), e, cctx.versions().next(), null, false);
             }

http://git-wip-us.apache.org/repos/asf/ignite/blob/7d9f3789/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 d973459..0ac7781 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
@@ -475,62 +475,78 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
         throws IgniteCheckedException, GridCacheEntryRemovedException {
         boolean swapEnabled = cctx.swap().swapEnabled();
 
-        if (!swapEnabled && !cctx.isOffHeapEnabled())
+        if (!swapEnabled && !cctx.isOffHeapEnabled() && !cctx.isDatabaseEnabled())
             return null;
 
         synchronized (this) {
             checkObsolete();
 
             if (isStartVersion() && ((flags & IS_UNSWAPPED_MASK) == 0)) {
-                GridCacheSwapEntry e;
+                if (cctx.isDatabaseEnabled()) {
+                    IgniteBiTuple<CacheObject, GridCacheVersion> read = cctx.queries().read(key);
 
-                if (cctx.offheapTiered()) {
-                    e = cctx.swap().readOffheapPointer(this);
+                    flags |= IS_UNSWAPPED_MASK;
 
-                    if (e != null) {
-                        if (e.offheapPointer() > 0) {
-                            offHeapPointer(e.offheapPointer());
+                    if (read != null) {
+                        CacheObject idxVal = read.get1();
 
-                            flags |= IS_OFFHEAP_PTR_MASK;
+                        // Set unswapped value.
+                        update(idxVal, 0, 0, read.get2());
 
-                            if (needVal) {
-                                CacheObject val = cctx.fromOffheap(offHeapPointer(), false);
+                        return idxVal;
+                    }
+                }
+                else {
+                    GridCacheSwapEntry e;
 
-                                e.value(val);
+                    if (cctx.offheapTiered()) {
+                        e = cctx.swap().readOffheapPointer(this);
+
+                        if (e != null) {
+                            if (e.offheapPointer() > 0) {
+                                offHeapPointer(e.offheapPointer());
+
+                                flags |= IS_OFFHEAP_PTR_MASK;
+
+                                if (needVal) {
+                                    CacheObject val = cctx.fromOffheap(offHeapPointer(), false);
+
+                                    e.value(val);
+                                }
                             }
+                            else // Read from swap.
+                                offHeapPointer(0);
                         }
-                        else // Read from swap.
-                            offHeapPointer(0);
                     }
-                }
-                else
-                    e = detached() ? cctx.swap().read(this, true, true, true, false) : cctx.swap().readAndRemove(this);
+                    else
+                        e = detached() ? cctx.swap().read(this, true, true, true, false) : cctx.swap().readAndRemove(this);
 
-                if (log.isDebugEnabled())
-                    log.debug("Read swap entry [swapEntry=" + e + ", cacheEntry=" + this + ']');
+                    if (log.isDebugEnabled())
+                        log.debug("Read swap entry [swapEntry=" + e + ", cacheEntry=" + this + ']');
 
-                flags |= IS_UNSWAPPED_MASK;
+                    flags |= IS_UNSWAPPED_MASK;
 
-                // If there is a value.
-                if (e != null) {
-                    long delta = e.expireTime() == 0 ? 0 : e.expireTime() - U.currentTimeMillis();
+                    // If there is a value.
+                    if (e != null) {
+                        long delta = e.expireTime() == 0 ? 0 : e.expireTime() - U.currentTimeMillis();
 
-                    if (delta >= 0) {
-                        CacheObject val = e.value();
+                        if (delta >= 0) {
+                            CacheObject val = e.value();
 
-                        val = cctx.kernalContext().cacheObjects().prepareForCache(val, cctx);
+                            val = cctx.kernalContext().cacheObjects().prepareForCache(val, cctx);
 
-                        // Set unswapped value.
-                        update(val, e.expireTime(), e.ttl(), e.version());
+                            // Set unswapped value.
+                            update(val, e.expireTime(), e.ttl(), e.version());
 
-                        // Must update valPtr again since update() will reset it.
-                        if (cctx.offheapTiered() && e.offheapPointer() > 0)
-                            offHeapPointer(e.offheapPointer());
+                            // Must update valPtr again since update() will reset it.
+                            if (cctx.offheapTiered() && e.offheapPointer() > 0)
+                                offHeapPointer(e.offheapPointer());
 
-                        return val;
+                            return val;
+                        }
+                        else
+                            clearIndex(e.value(), e.version());
                     }
-                    else
-                        clearIndex(e.value(), e.version());
                 }
             }
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/7d9f3789/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessorImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessorImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessorImpl.java
index 02351ec..f562259 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessorImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessorImpl.java
@@ -746,6 +746,14 @@ public class CacheObjectBinaryProcessorImpl extends IgniteCacheObjectProcessorIm
     }
 
     /** {@inheritDoc} */
+    @Override public KeyCacheObject toKeyCacheObject(CacheObjectContext ctx, byte type, byte[] bytes) throws IgniteCheckedException {
+        if (type == BinaryObjectImpl.TYPE_BINARY)
+            return new BinaryObjectImpl(binaryContext(), bytes, 0);
+
+        return super.toKeyCacheObject(ctx, type, bytes);
+    }
+
+    /** {@inheritDoc} */
     @Override public CacheObject toCacheObject(GridCacheContext ctx, long valPtr, boolean tmp)
         throws IgniteCheckedException {
         if (!((CacheObjectBinaryContext)ctx.cacheObjectContext()).binaryEnabled())

http://git-wip-us.apache.org/repos/asf/ignite/blob/7d9f3789/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryManager.java
index 4f20b79..413cd0e 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryManager.java
@@ -342,7 +342,7 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
      * @param key Key.
      * @throws IgniteCheckedException If failed.
      */
-    public void onSwap(CacheObject key) throws IgniteCheckedException {
+    public void onSwap(KeyCacheObject key) throws IgniteCheckedException {
         if (!enterBusy())
             return; // Ignore index update when node is stopping.
 
@@ -361,7 +361,7 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
      * @param val Value
      * @throws IgniteCheckedException If failed.
      */
-    public void onUnswap(CacheObject key, CacheObject val) throws IgniteCheckedException {
+    public void onUnswap(KeyCacheObject key, CacheObject val) throws IgniteCheckedException {
         if (!enterBusy())
             return; // Ignore index update when node is stopping.
 
@@ -390,7 +390,7 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
      * @param expirationTime Expiration time or 0 if never expires.
      * @throws IgniteCheckedException In case of error.
      */
-    public void store(CacheObject key, CacheObject val, GridCacheVersion ver, long expirationTime)
+    public void store(KeyCacheObject key, CacheObject val, GridCacheVersion ver, long expirationTime)
         throws IgniteCheckedException {
         assert key != null;
         assert val != null;
@@ -413,12 +413,28 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
     }
 
     /**
+     * @param key Key to read.
+     * @return Value tuple, if available.
+     */
+    public IgniteBiTuple<CacheObject, GridCacheVersion> read(KeyCacheObject key) throws IgniteCheckedException {
+        if (!enterBusy())
+            return null; // Ignore index update when node is stopping.
+
+        try {
+            return qryProc.read(space, key);
+        }
+        finally {
+            leaveBusy();
+        }
+    }
+
+    /**
      * @param key Key.
      * @param val Value.
      * @throws IgniteCheckedException Thrown in case of any errors.
      */
     @SuppressWarnings("SimplifiableIfStatement")
-    public void remove(CacheObject key, CacheObject val, GridCacheVersion ver) throws IgniteCheckedException {
+    public void remove(KeyCacheObject key, CacheObject val, GridCacheVersion ver) throws IgniteCheckedException {
         assert key != null;
 
         if (!GridQueryProcessor.isEnabled(cctx.config()) && !(key instanceof GridCacheInternal))

http://git-wip-us.apache.org/repos/asf/ignite/blob/7d9f3789/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/store/CacheStoreManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/store/CacheStoreManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/store/CacheStoreManager.java
index 16fbf9e..384befa 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/store/CacheStoreManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/store/CacheStoreManager.java
@@ -51,6 +51,11 @@ public interface CacheStoreManager extends GridCacheManager {
     public boolean configured();
 
     /**
+     * @return {@code True} if database is enabled.
+     */
+    public boolean isDatabaseEnabled();
+
+    /**
      * @return Wrapped store.
      */
     public CacheStore<Object, Object> store();

http://git-wip-us.apache.org/repos/asf/ignite/blob/7d9f3789/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/store/GridCacheStoreManagerAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/store/GridCacheStoreManagerAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/store/GridCacheStoreManagerAdapter.java
index f1cfd94..e03c244 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/store/GridCacheStoreManagerAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/store/GridCacheStoreManagerAdapter.java
@@ -255,6 +255,11 @@ public abstract class GridCacheStoreManagerAdapter extends GridCacheManagerAdapt
     }
 
     /** {@inheritDoc} */
+    @Override public boolean isDatabaseEnabled() {
+        return false;
+    }
+
+    /** {@inheritDoc} */
     @Override public CacheStore<?, ?> configuredStore() {
         return cfgStore;
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/7d9f3789/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessor.java
index b7290b6..a4d9250 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessor.java
@@ -154,12 +154,27 @@ public interface IgniteCacheObjectProcessor extends GridProcessor {
 
     /**
      * @param ctx Cache context.
+     * @param type Object type.
+     * @param bytes Object bytes.
+     * @return Cache object.
+     */
+    public KeyCacheObject toKeyCacheObject(CacheObjectContext ctx, byte type, byte[] bytes) throws IgniteCheckedException;
+
+    /**
+     * @param ctx Cache context.
      * @param buf Buffer to read from.
      * @return Cache object.
      */
     public CacheObject toCacheObject(CacheObjectContext ctx, ByteBuffer buf);
 
     /**
+     * @param ctx Cache context.
+     * @param buf Buffer to read from.
+     * @return Cache object.
+     */
+    public KeyCacheObject toKeyCacheObject(CacheObjectContext ctx, ByteBuffer buf) throws IgniteCheckedException;
+
+    /**
      * @param ctx Context.
      * @param valPtr Value pointer.
      * @param tmp If {@code true} can return temporary instance which is valid while entry lock is held.

http://git-wip-us.apache.org/repos/asf/ignite/blob/7d9f3789/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessorImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessorImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessorImpl.java
index 47af341..8ba0b9e 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessorImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessorImpl.java
@@ -173,6 +173,19 @@ public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter impleme
     }
 
     /** {@inheritDoc} */
+    @Override public KeyCacheObject toKeyCacheObject(CacheObjectContext ctx, byte type, byte[] bytes) throws IgniteCheckedException {
+        switch (type) {
+            case CacheObject.TYPE_BYTE_ARR:
+                throw new IllegalArgumentException("Byte arrays cannot be used as cache keys.");
+
+            case CacheObject.TYPE_REGULAR:
+                return new KeyCacheObjectImpl(ctx.processor().unmarshal(ctx, bytes, null), bytes);
+        }
+
+        throw new IllegalArgumentException("Invalid object type: " + type);
+    }
+
+    /** {@inheritDoc} */
     @Override public CacheObject toCacheObject(CacheObjectContext ctx, ByteBuffer buf) {
         byte type = buf.get();
 
@@ -186,6 +199,19 @@ public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter impleme
     }
 
     /** {@inheritDoc} */
+    @Override public KeyCacheObject toKeyCacheObject(CacheObjectContext ctx, ByteBuffer buf) throws IgniteCheckedException {
+        byte type = buf.get();
+
+        int len = buf.getInt();
+
+        byte[] data = new byte[len];
+
+        buf.get(data);
+
+        return toKeyCacheObject(ctx, type, data);
+    }
+
+    /** {@inheritDoc} */
     @Nullable @Override public CacheObject toCacheObject(CacheObjectContext ctx,
         @Nullable Object obj,
         boolean userObj)

http://git-wip-us.apache.org/repos/asf/ignite/blob/7d9f3789/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryIndexing.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryIndexing.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryIndexing.java
index 0ce93f1..2e2afb7 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryIndexing.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryIndexing.java
@@ -29,6 +29,7 @@ import org.apache.ignite.internal.GridKernalContext;
 import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
 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.query.GridCacheTwoStepQuery;
 import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
 import org.apache.ignite.internal.util.GridSpinBusyLock;
@@ -186,7 +187,7 @@ public interface GridQueryIndexing {
      * @param expirationTime Expiration time or 0 if never expires.
      * @throws IgniteCheckedException If failed.
      */
-    public void store(@Nullable String spaceName, GridQueryTypeDescriptor type, CacheObject key, CacheObject val,
+    public void store(@Nullable String spaceName, GridQueryTypeDescriptor type, KeyCacheObject key, CacheObject val,
         GridCacheVersion ver, long expirationTime) throws IgniteCheckedException;
 
     /**
@@ -197,7 +198,14 @@ public interface GridQueryIndexing {
      * @param val Value.
      * @throws IgniteCheckedException If failed.
      */
-    public void remove(@Nullable String spaceName, CacheObject key, CacheObject val, GridCacheVersion ver) throws IgniteCheckedException;
+    public void remove(@Nullable String spaceName, KeyCacheObject key, CacheObject val, GridCacheVersion ver) throws IgniteCheckedException;
+
+    /**
+     * @param space Space name.
+     * @param key Key.
+     * @return Read versioned value.
+     */
+    IgniteBiTuple<CacheObject,GridCacheVersion> read(String space, KeyCacheObject key) throws IgniteCheckedException;
 
     /**
      * Will be called when entry with given key is swapped.
@@ -206,7 +214,7 @@ public interface GridQueryIndexing {
      * @param key Key.
      * @throws IgniteCheckedException If failed.
      */
-    public void onSwap(@Nullable String spaceName, CacheObject key) throws IgniteCheckedException;
+    public void onSwap(@Nullable String spaceName, KeyCacheObject key) throws IgniteCheckedException;
 
     /**
      * Will be called when entry with given key is unswapped.
@@ -216,7 +224,7 @@ public interface GridQueryIndexing {
      * @param val Value.
      * @throws IgniteCheckedException If failed.
      */
-    public void onUnswap(@Nullable String spaceName, CacheObject key, CacheObject val) throws IgniteCheckedException;
+    public void onUnswap(@Nullable String spaceName, KeyCacheObject key, CacheObject val) throws IgniteCheckedException;
 
     /**
      * Rebuilds all indexes of given type.

http://git-wip-us.apache.org/repos/asf/ignite/blob/7d9f3789/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
index f6d19e7..cb4be3a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
@@ -41,6 +41,7 @@ import org.apache.ignite.internal.processors.cache.CacheEntryImpl;
 import org.apache.ignite.internal.processors.cache.CacheObject;
 import org.apache.ignite.internal.processors.cache.CacheObjectContext;
 import org.apache.ignite.internal.processors.cache.GridCacheContext;
+import org.apache.ignite.internal.processors.cache.KeyCacheObject;
 import org.apache.ignite.internal.processors.cache.QueryCursorImpl;
 import org.apache.ignite.internal.processors.cache.binary.CacheObjectBinaryProcessorImpl;
 import org.apache.ignite.internal.processors.cache.query.CacheQueryFuture;
@@ -637,7 +638,7 @@ public class GridQueryProcessor extends GridProcessorAdapter {
      * @throws IgniteCheckedException In case of error.
      */
     @SuppressWarnings("unchecked")
-    public void store(final String space, final CacheObject key, final CacheObject val,
+    public void store(final String space, final KeyCacheObject key, final CacheObject val,
         GridCacheVersion ver, long expirationTime) throws IgniteCheckedException {
         assert key != null;
         assert val != null;
@@ -706,6 +707,28 @@ public class GridQueryProcessor extends GridProcessorAdapter {
     }
 
     /**
+     * @param space Space name.
+     * @param key Key to read.
+     * @return Read versioned value.
+     * @throws IgniteCheckedException
+     */
+    public IgniteBiTuple<CacheObject, GridCacheVersion> read(final String space, final KeyCacheObject key)
+        throws IgniteCheckedException {
+        if (idx == null)
+            return null;
+
+        if (!busyLock.enterBusy())
+            throw new IllegalStateException("Failed to write to index (grid is stopping).");
+
+        try {
+            return idx.read(space, key);
+        }
+        finally {
+            busyLock.leaveBusy();
+        }
+    }
+
+    /**
      * @throws IgniteCheckedException If failed.
      */
     private void checkEnabled() throws IgniteCheckedException {
@@ -993,7 +1016,7 @@ public class GridQueryProcessor extends GridProcessorAdapter {
      * @param key Key.
      * @throws IgniteCheckedException Thrown in case of any errors.
      */
-    public void remove(String space, CacheObject key, CacheObject val, GridCacheVersion ver) throws IgniteCheckedException {
+    public void remove(String space, KeyCacheObject key, CacheObject val, GridCacheVersion ver) throws IgniteCheckedException {
         assert key != null;
 
         if (log.isDebugEnabled())
@@ -1167,7 +1190,7 @@ public class GridQueryProcessor extends GridProcessorAdapter {
      * @param key key.
      * @throws IgniteCheckedException If failed.
      */
-    public void onSwap(String spaceName, CacheObject key) throws IgniteCheckedException {
+    public void onSwap(String spaceName, KeyCacheObject key) throws IgniteCheckedException {
         if (log.isDebugEnabled())
             log.debug("Swap [space=" + spaceName + ", key=" + key + "]");
 
@@ -1205,7 +1228,7 @@ public class GridQueryProcessor extends GridProcessorAdapter {
      * @param val Value.
      * @throws IgniteCheckedException If failed.
      */
-    public void onUnswap(String spaceName, CacheObject key, CacheObject val)
+    public void onUnswap(String spaceName, KeyCacheObject key, CacheObject val)
         throws IgniteCheckedException {
         if (log.isDebugEnabled())
             log.debug("Unswap [space=" + spaceName + ", key=" + key + ", val=" + val + "]");

http://git-wip-us.apache.org/repos/asf/ignite/blob/7d9f3789/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 b94c489..93f6a41 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
@@ -73,6 +73,7 @@ import org.apache.ignite.internal.processors.cache.GridCacheAdapter;
 import org.apache.ignite.internal.processors.cache.GridCacheAffinityManager;
 import org.apache.ignite.internal.processors.cache.GridCacheContext;
 import org.apache.ignite.internal.processors.cache.IgniteInternalCache;
+import org.apache.ignite.internal.processors.cache.KeyCacheObject;
 import org.apache.ignite.internal.processors.cache.QueryCursorImpl;
 import org.apache.ignite.internal.processors.cache.query.GridCacheTwoStepQuery;
 import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
@@ -452,7 +453,7 @@ public class IgniteH2Indexing implements GridQueryIndexing {
      * @param tblToUpdate Table to update.
      * @throws IgniteCheckedException In case of error.
      */
-    private void removeKey(@Nullable String spaceName, CacheObject key, GridCacheVersion ver, TableDescriptor tblToUpdate)
+    private void removeKey(@Nullable String spaceName, KeyCacheObject key, GridCacheVersion ver, TableDescriptor tblToUpdate)
         throws IgniteCheckedException {
         try {
             Collection<TableDescriptor> tbls = tables(schema(spaceName));
@@ -513,7 +514,7 @@ public class IgniteH2Indexing implements GridQueryIndexing {
     }
 
     /** {@inheritDoc} */
-    @Override public void store(@Nullable String spaceName, GridQueryTypeDescriptor type, CacheObject k, CacheObject v,
+    @Override public void store(@Nullable String spaceName, GridQueryTypeDescriptor type, KeyCacheObject k, CacheObject v,
         GridCacheVersion ver, long expirationTime) throws IgniteCheckedException {
         TableDescriptor tbl = tableDescriptor(spaceName, type);
 
@@ -576,7 +577,7 @@ public class IgniteH2Indexing implements GridQueryIndexing {
     }
 
     /** {@inheritDoc} */
-    @Override public void remove(@Nullable String spaceName, CacheObject key, CacheObject val, GridCacheVersion ver) throws IgniteCheckedException {
+    @Override public void remove(@Nullable String spaceName, KeyCacheObject key, CacheObject val, GridCacheVersion ver) throws IgniteCheckedException {
         if (log.isDebugEnabled())
             log.debug("Removing key from cache query index [locId=" + nodeId + ", key=" + key + ", val=" + val + ']');
 
@@ -599,7 +600,32 @@ public class IgniteH2Indexing implements GridQueryIndexing {
     }
 
     /** {@inheritDoc} */
-    @Override public void onSwap(@Nullable String spaceName, CacheObject key) throws IgniteCheckedException {
+    @Override public IgniteBiTuple<CacheObject, GridCacheVersion> read(String spaceName, KeyCacheObject key) throws IgniteCheckedException {
+        if (log.isDebugEnabled())
+            log.debug("Reading stored value from cache query index [locId=" + nodeId + ", key=" + key + ']');
+
+        GridCacheContext cctx = cacheContext(spaceName);
+
+        CacheObjectContext coctx = objectContext(spaceName);
+
+        Class<?> keyCls = getClass(coctx, key);
+
+        IgniteBiTuple<CacheObject, GridCacheVersion> res = null;
+
+        for (TableDescriptor tbl : tables(schema(spaceName))) {
+            if (tbl.type().keyClass().isAssignableFrom(keyCls)) {
+                res = tbl.tbl.read(cctx, key);
+
+                if (res != null)
+                    break;
+            }
+        }
+
+        return res;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void onSwap(@Nullable String spaceName, KeyCacheObject key) throws IgniteCheckedException {
         Schema schema = schemas.get(schema(spaceName));
 
         if (schema == null)
@@ -621,7 +647,7 @@ public class IgniteH2Indexing implements GridQueryIndexing {
     }
 
     /** {@inheritDoc} */
-    @Override public void onUnswap(@Nullable String spaceName, CacheObject key, CacheObject val)
+    @Override public void onUnswap(@Nullable String spaceName, KeyCacheObject key, CacheObject val)
         throws IgniteCheckedException {
         assert val != null;
 
@@ -2446,7 +2472,7 @@ public class IgniteH2Indexing implements GridQueryIndexing {
         }
 
         /** {@inheritDoc} */
-        @Override public GridH2Row createRow(CacheObject key, @Nullable CacheObject val, GridCacheVersion ver,
+        @Override public GridH2Row createRow(KeyCacheObject key, @Nullable CacheObject val, GridCacheVersion ver,
             long expirationTime) throws IgniteCheckedException {
             GridH2Row row;
 
@@ -2464,18 +2490,13 @@ public class IgniteH2Indexing implements GridQueryIndexing {
                     "or configure key type as common super class for all actual keys for this value type.", e);
             }
 
-            if (val != null) {
-                row.ver = ver;
+            GridCacheContext cctx = cacheContext(schema.spaceName);
 
-                CacheObjectContext coctx = cacheContext(schema.spaceName).cacheObjectContext();
+            if (cctx.isDatabaseEnabled()) {
+                row.ver = ver;
 
-                try {
-                    row.key = key.valueBytes(coctx);
-                    row.val = val.valueBytes(coctx);
-                }
-                catch (IgniteCheckedException e) {
-                    throw new IgniteException(e);
-                }
+                row.key = key;
+                row.val = val;
             }
 
             return row;

http://git-wip-us.apache.org/repos/asf/ignite/blob/7d9f3789/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 d5b5e0d..38753e4 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
@@ -17,6 +17,8 @@
 
 package org.apache.ignite.internal.processors.query.h2.opt;
 
+import org.apache.ignite.internal.processors.cache.CacheObject;
+import org.apache.ignite.internal.processors.cache.KeyCacheObject;
 import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
 import org.h2.result.Row;
 import org.h2.value.Value;
@@ -29,15 +31,14 @@ public class GridH2Row extends Row implements GridSearchRowPointer {
     public long link; // TODO remove
 
     /** */
-    public byte[] key; // TODO remove
+    public KeyCacheObject key; // TODO remove
 
     /** */
-    public byte[] val; // TODO remove
+    public CacheObject val; // TODO remove
 
     /** */
     public GridCacheVersion ver; // TODO remove
 
-
     /**
      * @param data Column values.
      */

http://git-wip-us.apache.org/repos/asf/ignite/blob/7d9f3789/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 530f68c..3a2ff8b 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
@@ -19,6 +19,7 @@ package org.apache.ignite.internal.processors.query.h2.opt;
 
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.internal.processors.cache.CacheObject;
+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.IgniteH2Indexing;
 import org.apache.ignite.internal.util.offheap.unsafe.GridOffHeapSmartPointerFactory;
@@ -46,7 +47,7 @@ public interface GridH2RowDescriptor extends GridOffHeapSmartPointerFactory<Grid
      * @return Row.
      * @throws IgniteCheckedException If failed.
      */
-    public GridH2Row createRow(CacheObject key, @Nullable CacheObject val, GridCacheVersion ver, long expirationTime)
+    public GridH2Row createRow(KeyCacheObject key, @Nullable CacheObject val, GridCacheVersion ver, long expirationTime)
         throws IgniteCheckedException;
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/7d9f3789/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 b39cce0..eb4fdc9 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
@@ -30,8 +30,13 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.IgniteException;
 import org.apache.ignite.internal.processors.cache.CacheObject;
+import org.apache.ignite.internal.processors.cache.CacheObjectContext;
+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.util.offheap.unsafe.GridUnsafeMemory;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.lang.IgniteBiTuple;
 import org.h2.api.TableEngine;
 import org.h2.command.ddl.CreateTableData;
 import org.h2.engine.Constants;
@@ -135,7 +140,7 @@ public class GridH2Table extends TableBase {
      * @return {@code true} If row was found.
      * @throws IgniteCheckedException If failed.
      */
-    public boolean onSwap(CacheObject key) throws IgniteCheckedException {
+    public boolean onSwap(KeyCacheObject key) throws IgniteCheckedException {
         return onSwapUnswap(key, null);
     }
 
@@ -147,7 +152,7 @@ public class GridH2Table extends TableBase {
      * @return {@code true} If row was found.
      * @throws IgniteCheckedException If failed.
      */
-    public boolean onUnswap(CacheObject key, CacheObject val) throws IgniteCheckedException {
+    public boolean onUnswap(KeyCacheObject key, CacheObject val) throws IgniteCheckedException {
         assert val != null : "Key=" + key;
 
         return onSwapUnswap(key, val);
@@ -162,7 +167,7 @@ public class GridH2Table extends TableBase {
      * @throws IgniteCheckedException If failed.
      */
     @SuppressWarnings("LockAcquiredButNotSafelyReleased")
-    private boolean onSwapUnswap(CacheObject key, @Nullable CacheObject val) throws IgniteCheckedException {
+    private boolean onSwapUnswap(KeyCacheObject key, @Nullable CacheObject val) throws IgniteCheckedException {
         assert key != null;
 
         GridH2IndexBase pk = pk();
@@ -331,7 +336,7 @@ public class GridH2Table extends TableBase {
      * @return {@code true} If operation succeeded.
      * @throws IgniteCheckedException If failed.
      */
-    public boolean update(CacheObject key, CacheObject val, GridCacheVersion ver, long expirationTime, boolean rmv)
+    public boolean update(KeyCacheObject key, CacheObject val, GridCacheVersion ver, long expirationTime, boolean rmv)
         throws IgniteCheckedException {
         assert desc != null;
 
@@ -341,6 +346,26 @@ public class GridH2Table extends TableBase {
     }
 
     /**
+     * @param key Key to read.
+     * @return Read value.
+     * @throws IgniteCheckedException If failed.
+     */
+    public IgniteBiTuple<CacheObject, GridCacheVersion> read(
+        GridCacheContext cctx,
+        KeyCacheObject key
+    ) throws IgniteCheckedException {
+        assert desc != null;
+
+        GridH2Row row = desc.createRow(key, null, null, 0);
+
+        GridH2IndexBase primaryIdx = pk();
+
+        GridH2Row res = primaryIdx.findOne(row);
+
+        return res != null ? F.t(res.val, res.ver) : null;
+    }
+
+    /**
      * Gets index by index.
      *
      * @param idx Index in list.

http://git-wip-us.apache.org/repos/asf/ignite/blob/7d9f3789/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheQueryMultiThreadedSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheQueryMultiThreadedSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheQueryMultiThreadedSelfTest.java
index be644e2..8b81889 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheQueryMultiThreadedSelfTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheQueryMultiThreadedSelfTest.java
@@ -148,13 +148,13 @@ public class IgniteCacheQueryMultiThreadedSelfTest extends GridCommonAbstractTes
      *
      */
     private static class FakeIndexing extends IgniteH2Indexing {
-        @Override public void onSwap(@Nullable String spaceName, CacheObject key) throws IgniteCheckedException {
+        @Override public void onSwap(@Nullable String spaceName, KeyCacheObject key) throws IgniteCheckedException {
             super.onSwap(spaceName, key);
 
             idxSwapCnt.incrementAndGet();
         }
 
-        @Override public void onUnswap(@Nullable String spaceName, CacheObject key, CacheObject val)
+        @Override public void onUnswap(@Nullable String spaceName, KeyCacheObject key, CacheObject val)
         throws IgniteCheckedException {
             super.onUnswap(spaceName, key, val);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/7d9f3789/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/GridIndexingSpiAbstractSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/GridIndexingSpiAbstractSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/GridIndexingSpiAbstractSelfTest.java
index cd7a203..b37055d 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/GridIndexingSpiAbstractSelfTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/GridIndexingSpiAbstractSelfTest.java
@@ -31,6 +31,7 @@ import org.apache.ignite.IgniteLogger;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.internal.processors.cache.CacheObject;
 import org.apache.ignite.internal.processors.cache.CacheObjectContext;
+import org.apache.ignite.internal.processors.cache.KeyCacheObject;
 import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
 import org.apache.ignite.internal.processors.query.GridQueryFieldsResult;
 import org.apache.ignite.internal.processors.query.GridQueryIndexDescriptor;
@@ -191,7 +192,7 @@ public abstract class GridIndexingSpiAbstractSelfTest extends GridCommonAbstract
      * @param key Key.
      * @return Cache object.
      */
-    private CacheObject key(int key) {
+    private KeyCacheObject key(int key) {
         return new TestCacheObject(key);
     }
 
@@ -563,7 +564,7 @@ public abstract class GridIndexingSpiAbstractSelfTest extends GridCommonAbstract
 
     /**
      */
-    private static class TestCacheObject implements CacheObject {
+    private static class TestCacheObject implements KeyCacheObject {
         /** */
         private Object val;
 
@@ -590,6 +591,11 @@ public abstract class GridIndexingSpiAbstractSelfTest extends GridCommonAbstract
         }
 
         /** {@inheritDoc} */
+        @Override public int valueBytesLength(CacheObjectContext ctx) throws IgniteCheckedException {
+            return 0;
+        }
+
+        /** {@inheritDoc} */
         @Override public byte cacheObjectType() {
             throw new UnsupportedOperationException();
         }
@@ -633,5 +639,10 @@ public abstract class GridIndexingSpiAbstractSelfTest extends GridCommonAbstract
         @Override public byte fieldsCount() {
             throw new UnsupportedOperationException();
         }
+
+        /** {@inheritDoc} */
+        @Override public boolean internal() {
+            return false;
+        }
     }
 }
\ No newline at end of file