ignite-db-10884

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

Branch: refs/heads/ignite-db-x-10884
Commit: d69f6ea23a2d72e49e00ba84e8bfc2528bd4bad2
Parents: fc2d77d
Author: sboikov <[email protected]>
Authored: Tue Apr 19 15:57:54 2016 +0300
Committer: sboikov <[email protected]>
Committed: Tue Apr 19 15:57:54 2016 +0300

----------------------------------------------------------------------
 .../processors/cache/GridCacheContext.java      |   9 +
 .../processors/cache/GridCacheMapEntry.java     |  10 +-
 .../processors/cache/GridCacheProcessor.java    |  12 +-
 .../cache/IgniteCacheOffheapManager.java        | 522 +++++++++++++++++++
 .../cache/database/tree/io/PageIO.java          |  14 +-
 .../cache/database/IgniteDbPutGetTest.java      |  98 ++++
 .../loadtests/hashmap/GridCacheTestContext.java |   1 +
 7 files changed, 656 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/d69f6ea2/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 ba5a1d6..eeaf668 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
@@ -181,6 +181,9 @@ public class GridCacheContext<K, V> implements 
Externalizable {
     /** Database manager. */
     private IgniteCacheDatabaseManager dbMgr;
 
+    /** */
+    private IgniteCacheOffheapManager offheapMgr;
+
     /** Conflict resolver manager. */
     private CacheConflictResolutionManager rslvrMgr;
 
@@ -301,6 +304,7 @@ public class GridCacheContext<K, V> implements 
Externalizable {
         GridCacheTtlManager ttlMgr,
         GridCacheDrManager drMgr,
         IgniteCacheDatabaseManager dbMgr,
+        IgniteCacheOffheapManager offheapMgr,
         CacheConflictResolutionManager<K, V> rslvrMgr,
         CachePluginManager pluginMgr,
         GridCacheAffinityManager affMgr
@@ -344,6 +348,7 @@ public class GridCacheContext<K, V> implements 
Externalizable {
         this.ttlMgr = add(ttlMgr);
         this.drMgr = add(drMgr);
         this.dbMgr = add(dbMgr);
+        this.offheapMgr = add(offheapMgr);
         this.rslvrMgr = add(rslvrMgr);
         this.pluginMgr = add(pluginMgr);
         this.affMgr = add(affMgr);
@@ -1080,6 +1085,10 @@ public class GridCacheContext<K, V> implements 
Externalizable {
         return (T)dbMgr;
     }
 
+    public IgniteCacheOffheapManager offheap0() {
+        return offheapMgr;
+    }
+
     /**
      * @return TTL manager.
      */

http://git-wip-us.apache.org/repos/asf/ignite/blob/d69f6ea2/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 0efeaa1..6057567 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
@@ -483,7 +483,7 @@ public abstract class GridCacheMapEntry extends 
GridMetadataAwareAdapter impleme
 
             if (isStartVersion() && ((flags & IS_UNSWAPPED_MASK) == 0)) {
                 if (cctx.isDatabaseEnabled()) {
-                    IgniteBiTuple<CacheObject, GridCacheVersion> read = 
cctx.queries().read(key, partition());
+                    IgniteBiTuple<CacheObject, GridCacheVersion> read = 
cctx.offheap0().read(key, partition());
 
                     flags |= IS_UNSWAPPED_MASK;
 
@@ -1198,6 +1198,8 @@ public abstract class GridCacheMapEntry extends 
GridMetadataAwareAdapter impleme
 
             update(val, expireTime, ttl, newVer);
 
+            cctx.offheap0().put(key, val, newVer, partition());
+
             drReplicate(drType, val, newVer);
 
             recordNodeId(affNodeId, topVer);
@@ -1341,6 +1343,8 @@ public abstract class GridCacheMapEntry extends 
GridMetadataAwareAdapter impleme
             // can be updated without actually holding entry lock.
             clearIndex(old, ver);
 
+            cctx.offheap0().remove(key);
+
             boolean hadValPtr = hasOffHeapPointer();
 
             update(null, 0, 0, newVer);
@@ -2289,6 +2293,8 @@ public abstract class GridCacheMapEntry extends 
GridMetadataAwareAdapter impleme
 
                 update(updated, newExpireTime, newTtl, newVer);
 
+                cctx.offheap0().put(key, updated, newVer, partition());
+
                 updateCntr0 = nextPartCounter(topVer);
 
                 if (updateCntr != null)
@@ -2374,6 +2380,8 @@ public abstract class GridCacheMapEntry extends 
GridMetadataAwareAdapter impleme
                 // Clear value on backup. Entry will be removed from cache 
when it got evicted from queue.
                 update(null, CU.TTL_ETERNAL, CU.EXPIRE_TIME_ETERNAL, newVer);
 
+                cctx.offheap0().remove(key);
+
                 assert newSysTtl == CU.TTL_NOT_CHANGED;
                 assert newSysExpireTime == CU.EXPIRE_TIME_CALCULATE;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/d69f6ea2/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java
index d04ca9d..21a827d 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java
@@ -1300,6 +1300,10 @@ public class GridCacheProcessor extends 
GridProcessorAdapter {
         CacheStoreManager storeMgr = 
pluginMgr.createComponent(CacheStoreManager.class);
         IgniteCacheDatabaseManager dbMgr = createDatabaseManager(cfg);
 
+        boolean cacheIndexing = INDEXING.inClassPath() && 
GridQueryProcessor.isEnabled(cfg);
+
+        IgniteCacheOffheapManager offheapMgr = new 
IgniteCacheOffheapManager(cacheIndexing);
+
         storeMgr.initialize(cfgStore, sesHolders);
 
         GridCacheContext<?, ?> cacheCtx = new GridCacheContext(
@@ -1324,6 +1328,7 @@ public class GridCacheProcessor extends 
GridProcessorAdapter {
             ttlMgr,
             drMgr,
             dbMgr,
+            offheapMgr,
             rslvrMgr,
             pluginMgr,
             affMgr
@@ -1454,6 +1459,7 @@ public class GridCacheProcessor extends 
GridProcessorAdapter {
                 ttlMgr,
                 drMgr,
                 dbMgr,
+                offheapMgr,
                 rslvrMgr,
                 pluginMgr,
                 affMgr
@@ -1514,11 +1520,7 @@ public class GridCacheProcessor extends 
GridProcessorAdapter {
     }
 
     private IgniteCacheDatabaseManager 
createDatabaseManager(CacheConfiguration ccfg) throws IgniteCheckedException {
-        if (sharedCtx.database().enabled()) {
-            if (!INDEXING.inClassPath())
-                throw new IgniteCheckedException("Failed to create cache with 
database enabled (" + INDEXING.module() +
-                    " must be present in classpath)");
-
+        if (sharedCtx.database().enabled() && INDEXING.inClassPath()) {
             try {
                 return (IgniteCacheDatabaseManager)Class
                     
.forName("org.apache.ignite.internal.processors.cache.database.IgniteCacheH2DatabaseManager")

http://git-wip-us.apache.org/repos/asf/ignite/blob/d69f6ea2/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManager.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManager.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManager.java
new file mode 100644
index 0000000..9c16378
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManager.java
@@ -0,0 +1,522 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.cache;
+
+import java.nio.ByteBuffer;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.internal.pagemem.FullPageId;
+import org.apache.ignite.internal.pagemem.Page;
+import org.apache.ignite.internal.pagemem.PageIdUtils;
+import org.apache.ignite.internal.pagemem.PageMemory;
+import org.apache.ignite.internal.processors.cache.database.CacheDataRow;
+import 
org.apache.ignite.internal.processors.cache.database.IgniteCacheDatabaseSharedManager;
+import org.apache.ignite.internal.processors.cache.database.RowStore;
+import org.apache.ignite.internal.processors.cache.database.freelist.FreeList;
+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.cache.database.tree.io.BPlusInnerIO;
+import 
org.apache.ignite.internal.processors.cache.database.tree.io.BPlusLeafIO;
+import org.apache.ignite.internal.processors.cache.database.tree.io.DataPageIO;
+import org.apache.ignite.internal.processors.cache.database.tree.io.IOVersions;
+import org.apache.ignite.internal.processors.cache.database.tree.io.PageIO;
+import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.lang.IgniteBiTuple;
+import org.jetbrains.annotations.Nullable;
+
+import static org.apache.ignite.internal.pagemem.PageIdUtils.dwordsOffset;
+import static org.apache.ignite.internal.pagemem.PageIdUtils.pageId;
+
+/**
+ *
+ */
+public class IgniteCacheOffheapManager extends GridCacheManagerAdapter {
+    /** */
+    private CacheDataRowStore rowStore;
+
+    /** */
+    private CacheDataTree dataTree;
+
+    /** */
+    private boolean indexingEnabled;
+
+    /**
+     * @param indexingEnabled {@code True} if indexing is enabled for cache.
+     */
+    public IgniteCacheOffheapManager(boolean indexingEnabled) {
+        this.indexingEnabled = indexingEnabled;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void start0() throws IgniteCheckedException {
+        super.start0();
+
+        if (!indexingEnabled) {
+            IgniteCacheDatabaseSharedManager dbMgr = cctx.shared().database();
+
+            IgniteBiTuple<FullPageId, Boolean> page = 
dbMgr.meta().getOrAllocateForIndex(cctx.cacheId(), cctx.namexx());
+
+            rowStore = new CacheDataRowStore(cctx, null);
+
+            dataTree = new CacheDataTree(rowStore, cctx, dbMgr.pageMemory(), 
page.get1(), page.get2());
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void onKernalStart0() throws IgniteCheckedException {
+        super.onKernalStart0();
+    }
+
+    /**
+     * @param key Key.
+     * @param val Value.
+     * @param ver Version.
+     * @param part Partition.
+     * @throws IgniteCheckedException If failed.
+     */
+    public void put(KeyCacheObject key, CacheObject val, GridCacheVersion ver, 
int part) throws IgniteCheckedException {
+        if (indexingEnabled)
+            return;
+
+        DataRow dataRow = new DataRow(key, val, ver, part, 0);
+
+        rowStore.addRow(dataRow);
+
+        dataTree.put(dataRow);
+    }
+
+    /**
+     * @param key Key.
+     * @throws IgniteCheckedException If failed.
+     */
+    public void remove(KeyCacheObject key) throws IgniteCheckedException {
+        if (indexingEnabled)
+            return;
+
+        DataRow dataRow = dataTree.remove(new KeySearchRow(key));
+
+        if (dataRow != null) {
+            assert dataRow.link != 0 : dataRow;
+
+            rowStore.removeRow(dataRow.link);
+        }
+    }
+
+    /**
+     * @param key Key to read.
+     * @param part Partition.
+     * @return Value tuple, if available.
+     * @throws IgniteCheckedException If failed.
+     */
+    @Nullable public IgniteBiTuple<CacheObject, GridCacheVersion> 
read(KeyCacheObject key, int part)
+        throws IgniteCheckedException {
+        if (indexingEnabled)
+            return cctx.queries().read(key, part);
+
+        DataRow dataRow = dataTree.findOne(new KeySearchRow(key));
+
+        return dataRow != null ? F.t(dataRow.val, dataRow.ver) : null;
+    }
+
+    /**
+     *
+     */
+    static class KeySearchRow {
+        /** */
+        protected final CacheObject key;
+
+        /**
+         * @param key Key.
+         */
+        public KeySearchRow(CacheObject key) {
+            this.key = key;
+        }
+    }
+
+    /**
+     *
+     */
+    static class DataRow extends KeySearchRow implements CacheDataRow {
+        /** */
+        private CacheObject val;
+
+        /** */
+        private GridCacheVersion ver;
+
+        /** */
+        private int part;
+
+        /** */
+        private long link;
+
+        /**
+         * @param key Key.
+         * @param val Value.
+         * @param ver Version.
+         * @param part Partition.
+         * @param link Link.
+         */
+        public DataRow(CacheObject key, CacheObject val, GridCacheVersion ver, 
int part, long link) {
+            super(key);
+            this.val = val;
+            this.ver = ver;
+            this.part = part;
+            this.link = link;
+        }
+
+        /** {@inheritDoc} */
+        @Override public CacheObject key() {
+            return key;
+        }
+
+        /** {@inheritDoc} */
+        @Override public CacheObject value() {
+            return val;
+        }
+
+        /** {@inheritDoc} */
+        @Override public GridCacheVersion version() {
+            return ver;
+        }
+
+        /** {@inheritDoc} */
+        @Override public int partition() {
+            return part;
+        }
+
+        /** {@inheritDoc} */
+        @Override public long link() {
+            return link;
+        }
+
+        /** {@inheritDoc} */
+        @Override public void link(long link) {
+            this.link = link;
+        }
+    }
+
+    /**
+     *
+     */
+    static class CacheDataTree extends BPlusTree<KeySearchRow, DataRow> {
+        /** */
+        private final CacheDataRowStore rowStore;
+
+        /** */
+        private final GridCacheContext cctx;
+
+        /**
+         * @param rowStore Row store.
+         * @param cctx Context.
+         * @param pageMem Page memory.
+         * @param metaPageId Meta page ID.
+         * @param initNew Initialize new index.
+         * @throws IgniteCheckedException If failed.
+         */
+        public CacheDataTree(CacheDataRowStore rowStore,
+            GridCacheContext cctx,
+            PageMemory pageMem,
+            FullPageId metaPageId,
+            boolean initNew) throws IgniteCheckedException {
+            super(cctx.cacheId(), pageMem, metaPageId);
+
+            this.rowStore = rowStore;
+            this.cctx = cctx;
+
+            if (initNew)
+                initNew();
+        }
+
+        /** {@inheritDoc} */
+        @Override protected BPlusIO<KeySearchRow> io(int type, int ver) {
+            if (type == PageIO.T_DATA_REF_INNER)
+                return DataInnerIO.VERSIONS.forVersion(ver);
+
+            assert type == PageIO.T_DATA_REF_LEAF: type;
+
+            return DataLeafIO.VERSIONS.forVersion(ver);
+        }
+
+        /** {@inheritDoc} */
+        @Override protected BPlusInnerIO<KeySearchRow> latestInnerIO() {
+            return DataInnerIO.VERSIONS.latest();
+        }
+
+        /** {@inheritDoc} */
+        @Override protected BPlusLeafIO<KeySearchRow> latestLeafIO() {
+            return DataLeafIO.VERSIONS.latest();
+        }
+
+        /** {@inheritDoc} */
+        @Override protected int compare(BPlusIO<KeySearchRow> io, ByteBuffer 
buf, int idx, KeySearchRow row) throws IgniteCheckedException {
+            KeySearchRow row0 = io.getLookupRow(this, buf, idx);
+
+            return compareKeys(row0.key, row.key);
+        }
+
+        /** {@inheritDoc} */
+        @Override protected DataRow getRow(BPlusIO<KeySearchRow> io, 
ByteBuffer buf, int idx) throws IgniteCheckedException {
+            long link = ((RowLinkIO)io).getLink(buf, idx);
+
+            return rowStore.dataRow(link);
+        }
+
+        /**
+         * @param key1 First key.
+         * @param key2 Second key.
+         * @return Compare result.
+         * @throws IgniteCheckedException If failed.
+         */
+        private int compareKeys(CacheObject key1, CacheObject key2) throws 
IgniteCheckedException {
+            byte[] bytes1 = key1.valueBytes(cctx.cacheObjectContext());
+            byte[] bytes2 = key2.valueBytes(cctx.cacheObjectContext());
+
+            int len = Math.min(bytes1.length, bytes2.length);
+
+            for (int i = 0; i < len; i++) {
+                byte b1 = bytes1[i];
+                byte b2 = bytes2[i];
+
+                if (b1 != b2)
+                    return b1 > b2 ? 1 : -1;
+            }
+
+            return Integer.compare(bytes1.length, bytes2.length);
+        }
+    }
+
+    /**
+     *
+     */
+    static class CacheDataRowStore extends RowStore<DataRow> {
+        /**
+         * @param cctx Cache context.
+         * @param freeList Free list.
+         */
+        public CacheDataRowStore(GridCacheContext<?, ?> cctx, FreeList 
freeList) {
+            super(cctx, freeList);
+        }
+
+        public KeySearchRow keySearchRow(long link) throws 
IgniteCheckedException {
+            return getRow(link, KeyRowClosure.INSTANCE);
+        }
+
+        public DataRow dataRow(long link) throws IgniteCheckedException {
+            return getRow(link, DataRowClosure.INSTANCE);
+        }
+
+        private <T> T getRow(long link, RowClosure<T> c) throws 
IgniteCheckedException {
+            try (Page page = page(pageId(link))) {
+                ByteBuffer buf = page.getForRead();
+
+                try {
+                    DataPageIO io = DataPageIO.VERSIONS.forPage(buf);
+
+                    int dataOff = io.getDataOffset(buf, dwordsOffset(link));
+
+                    buf.position(dataOff);
+
+                    // Skip entry size.
+                    buf.getShort();
+
+                    T row;
+
+                    try {
+                        row = c.create(buf, link, cctx);
+                    }
+                    catch (IgniteCheckedException e) {
+                        throw new IgniteException(e);
+                    }
+
+                    return row;
+                }
+                finally {
+                    page.releaseRead();
+                }
+            }
+        }
+
+        /**
+         *
+         */
+        private interface RowClosure<T> {
+            T create(ByteBuffer buf, long link, GridCacheContext cctx) throws 
IgniteCheckedException;
+        }
+
+        /**
+         *
+         */
+        static class KeyRowClosure implements RowClosure<KeySearchRow> {
+            /** */
+            static final KeyRowClosure INSTANCE = new KeyRowClosure();
+
+            /** {@inheritDoc} */
+            @Override public KeySearchRow create(ByteBuffer buf, long link, 
GridCacheContext cctx) throws IgniteCheckedException {
+                CacheObject key = 
cctx.cacheObjects().toCacheObject(cctx.cacheObjectContext(), buf);
+
+                return new KeySearchRow(key);
+            }
+        }
+
+        /**
+         *
+         */
+        static class DataRowClosure implements RowClosure<DataRow> {
+            /** */
+            static final DataRowClosure INSTANCE = new DataRowClosure();
+
+            /** {@inheritDoc} */
+            @Override public DataRow create(ByteBuffer buf, long link, 
GridCacheContext cctx) throws IgniteCheckedException {
+                CacheObject key = 
cctx.cacheObjects().toCacheObject(cctx.cacheObjectContext(), buf);
+                CacheObject val = 
cctx.cacheObjects().toCacheObject(cctx.cacheObjectContext(), buf);
+
+                int topVer = buf.getInt();
+                int nodeOrderDrId = buf.getInt();
+                long globalTime = buf.getLong();
+                long order = buf.getLong();
+
+                GridCacheVersion ver = new GridCacheVersion(topVer, 
nodeOrderDrId, globalTime, order);
+
+                return new DataRow(key, val, ver, PageIdUtils.partId(link), 
link);
+            }
+        }
+    }
+
+    /**
+     *
+     */
+    interface RowLinkIO {
+        /**
+         * @param buf Buffer.
+         * @param idx Index.
+         * @return Row link.
+         */
+        public long getLink(ByteBuffer buf, int idx);
+
+        /**
+         * @param buf Buffer.
+         * @param idx Index.
+         * @param link Row link.
+         */
+        public void setLink(ByteBuffer buf, int idx, long link);
+    }
+
+    /**
+     *
+     */
+    static class DataInnerIO extends BPlusInnerIO<KeySearchRow> implements 
RowLinkIO {
+        /** */
+        public static final IOVersions<DataInnerIO> VERSIONS = new 
IOVersions<>(
+            new DataInnerIO(1)
+        );
+
+        /**
+         * @param ver Page format version.
+         */
+        private DataInnerIO(int ver) {
+            super(T_DATA_REF_INNER, ver, true, 8);
+        }
+
+        /** {@inheritDoc} */
+        @Override public void store(ByteBuffer buf, int idx, KeySearchRow row) 
{
+            DataRow row0 = (DataRow)row;
+
+            assert row0.link != 0;
+
+            setLink(buf, idx, row0.link);
+        }
+
+        /** {@inheritDoc} */
+        @Override public KeySearchRow getLookupRow(BPlusTree<KeySearchRow,?> 
tree, ByteBuffer buf, int idx)
+            throws IgniteCheckedException {
+            long link = getLink(buf, idx);
+
+            return ((CacheDataTree)tree).rowStore.keySearchRow(link);
+        }
+
+        /** {@inheritDoc} */
+        @Override public void store(ByteBuffer dst, int dstIdx, 
BPlusIO<KeySearchRow> srcIo, ByteBuffer src, int srcIdx) {
+            long link = ((RowLinkIO)srcIo).getLink(src, srcIdx);
+
+            setLink(dst, dstIdx, link);
+        }
+
+        /** {@inheritDoc} */
+        @Override public long getLink(ByteBuffer buf, int idx) {
+            assert idx < getCount(buf): idx;
+
+            return buf.getLong(offset(idx, SHIFT_LINK));
+        }
+
+        /** {@inheritDoc} */
+        @Override public void setLink(ByteBuffer buf, int idx, long link) {
+            buf.putLong(offset(idx, SHIFT_LINK), link);
+
+            assert getLink(buf, idx) == link;
+        }
+    }
+
+    /**
+     *
+     */
+    static class DataLeafIO extends BPlusLeafIO<KeySearchRow> implements 
RowLinkIO {
+        /** */
+        public static final IOVersions<DataLeafIO> VERSIONS = new IOVersions<>(
+            new DataLeafIO(1)
+        );
+
+        /**
+         * @param ver Page format version.
+         */
+        protected DataLeafIO(int ver) {
+            super(T_DATA_REF_LEAF, ver, 8);
+        }
+
+        /** {@inheritDoc} */
+        @Override public void store(ByteBuffer buf, int idx, KeySearchRow row) 
{
+            DataRow row0 = (DataRow)row;
+
+            assert row0.link != 0;
+
+            setLink(buf, idx, row0.link);
+        }
+
+        /** {@inheritDoc} */
+        @Override public KeySearchRow getLookupRow(BPlusTree<KeySearchRow,?> 
tree, ByteBuffer buf, int idx)
+            throws IgniteCheckedException {
+            long link = getLink(buf, idx);
+
+            return ((CacheDataTree)tree).rowStore.keySearchRow(link);
+        }
+
+        /** {@inheritDoc} */
+        @Override public long getLink(ByteBuffer buf, int idx) {
+            assert idx < getCount(buf): idx;
+
+            return buf.getLong(offset(idx));
+        }
+
+        /** {@inheritDoc} */
+        @Override public void setLink(ByteBuffer buf, int idx, long link) {
+            buf.putLong(offset(idx), link);
+
+            assert getLink(buf, idx) == link;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/d69f6ea2/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/PageIO.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/PageIO.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/PageIO.java
index 62b72eb..c9ae050 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/PageIO.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/PageIO.java
@@ -53,13 +53,19 @@ public abstract class PageIO {
     public static final short T_H2_REF_INNER = 4;
 
     /** */
-    public static final short T_FREE_LEAF = 5;
+    public static final short T_DATA_REF_INNER = 5;
 
     /** */
-    public static final short T_FREE_INNER = 6;
+    public static final short T_DATA_REF_LEAF = 6;
 
     /** */
-    public static final short T_REUSE_LEAF = 7;
+    public static final short T_FREE_LEAF = 7;
+
+    /** */
+    public static final short T_FREE_INNER = 8;
+
+    /** */
+    public static final short T_REUSE_LEAF = 9;
 
     /** */
     public static final short T_REUSE_INNER = 8;
@@ -94,7 +100,7 @@ public abstract class PageIO {
      * @param type Type.
      */
     public static void setType(ByteBuffer buf, int type) {
-        assert type >= T_DATA && type <= T_H2_REF_INNER : type;
+        assert type >= T_DATA && type <= T_DATA_REF_LEAF : type;
 
         buf.putShort(TYPE_OFF, (short)type);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/d69f6ea2/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/database/IgniteDbPutGetTest.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/database/IgniteDbPutGetTest.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/database/IgniteDbPutGetTest.java
new file mode 100644
index 0000000..fe39d30
--- /dev/null
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/database/IgniteDbPutGetTest.java
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.cache.database;
+
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.DatabaseConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+
+/**
+ *
+ */
+public class IgniteDbPutGetTest extends GridCommonAbstractTest {
+    /** */
+    private static final TcpDiscoveryIpFinder IP_FINDER = new 
TcpDiscoveryVmIpFinder(true);
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String gridName) 
throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(gridName);
+
+        ((TcpDiscoverySpi)cfg.getDiscoverySpi()).setIpFinder(IP_FINDER);
+
+        DatabaseConfiguration dbCfg = new DatabaseConfiguration();
+
+        dbCfg.setConcurrencyLevel(Runtime.getRuntime().availableProcessors() * 
4);
+
+        dbCfg.setPageSize(256);
+
+        dbCfg.setPageCacheSize(100 * 1024 * 1024);
+
+        cfg.setDatabaseConfiguration(dbCfg);
+
+        CacheConfiguration ccfg = new CacheConfiguration();
+
+        ccfg.setAtomicityMode(CacheAtomicityMode.TRANSACTIONAL);
+
+        cfg.setCacheConfiguration(ccfg);
+
+        return cfg;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        super.beforeTestsStarted();
+
+        startGrids(1);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTestsStopped() throws Exception {
+        stopAllGrids();
+
+        super.afterTestsStopped();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testPutGet() throws Exception {
+        Ignite ignite = ignite(0);
+
+        IgniteCache<Integer, Integer> cache = ignite.cache(null);
+
+        cache.put(1, 1);
+        cache.put(2, 2);
+
+        assertEquals(1, (Object)cache.get(1));
+
+        cache.remove(1);
+        assertNull(cache.get(1));
+        assertEquals(2, (Object)cache.get(2));
+
+        cache.remove(2);
+
+        assertNull(cache.get(2));
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/d69f6ea2/modules/core/src/test/java/org/apache/ignite/loadtests/hashmap/GridCacheTestContext.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/test/java/org/apache/ignite/loadtests/hashmap/GridCacheTestContext.java
 
b/modules/core/src/test/java/org/apache/ignite/loadtests/hashmap/GridCacheTestContext.java
index 5474f57..280b250 100644
--- 
a/modules/core/src/test/java/org/apache/ignite/loadtests/hashmap/GridCacheTestContext.java
+++ 
b/modules/core/src/test/java/org/apache/ignite/loadtests/hashmap/GridCacheTestContext.java
@@ -86,6 +86,7 @@ public class GridCacheTestContext<K, V> extends 
GridCacheContext<K, V> {
             new GridCacheTtlManager(),
             new GridOsCacheDrManager(),
             null,
+            null,
             new CacheOsConflictResolutionManager<K, V>(),
             new CachePluginManager(ctx, new CacheConfiguration()),
             new GridCacheAffinityManager()

Reply via email to