http://git-wip-us.apache.org/repos/asf/ignite/blob/cbfed9cf/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/BPlusIOLeaf.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/BPlusIOLeaf.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/BPlusIOLeaf.java
new file mode 100644
index 0000000..0aaa3b8
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/BPlusIOLeaf.java
@@ -0,0 +1,84 @@
+/*
+ * 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.tree.io;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Abstract IO routines for B+Tree leaf pages.
+ */
+public abstract class BPlusIOLeaf<L> extends BPlusIO<L> {
+    /** */
+    protected static final int ITEM_SIZE = 8;
+
+    /**
+     * @param ver Page format version.
+     */
+    protected BPlusIOLeaf(int ver) {
+        super(ver);
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isLeaf() {
+        return true;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int getMaxCount(ByteBuffer buf) {
+        return (buf.capacity() - ITEMS_OFF) >>> 3; // divide by ITEM_SIZE
+    }
+
+//        /** {@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;
+//        }
+
+    /** {@inheritDoc} */
+    @Override public void copyItems(ByteBuffer src, ByteBuffer dst, int 
srcIdx, int dstIdx, int cnt,
+        boolean cpLeft) {
+        assert srcIdx != dstIdx || src != dst;
+
+        if (dstIdx > srcIdx) {
+            for (int i = cnt - 1; i >= 0; i--)
+                dst.putLong(offset(dstIdx + i), src.getLong(offset(srcIdx + 
i)));
+        }
+        else {
+            for (int i = 0; i < cnt; i++)
+                dst.putLong(offset(dstIdx + i), src.getLong(offset(srcIdx + 
i)));
+        }
+    }
+
+    /**
+     * @param idx Index of item.
+     * @return Offset.
+     */
+    protected static int offset(int idx) {
+        assert idx >= 0: idx;
+
+        return ITEMS_OFF + idx * ITEM_SIZE;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/cbfed9cf/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/BPlusIOMeta.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/BPlusIOMeta.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/BPlusIOMeta.java
new file mode 100644
index 0000000..f5d31ad
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/BPlusIOMeta.java
@@ -0,0 +1,117 @@
+/*
+ * 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.tree.io;
+
+import java.nio.ByteBuffer;
+
+/**
+ * IO routines for B+Tree meta pages.
+ */
+public class BPlusIOMeta extends PageIO {
+    /** */
+    public static final IORegistry<BPlusIOMeta> VERSIONS = new IORegistry<>(
+        new BPlusIOMeta(1)
+    );
+
+    /** */
+    private static final int LVLS_OFF = COMMON_HEADER_END;
+
+    /** */
+    private static final int REFS_OFF = LVLS_OFF + 1;
+
+    /**
+     * @param ver Page format version.
+     */
+    protected BPlusIOMeta(int ver) {
+        super(ver);
+    }
+
+    /** {@inheritDoc} */
+    @Override public int getType() {
+        return T_BPLUS_META;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void initNewPage(ByteBuffer buf, long pageId) {
+        super.initNewPage(buf, pageId);
+
+        setLevelsCount(buf, 0);
+    }
+
+    /**
+     * @param buf Buffer.
+     * @return Number of levels in this tree.
+     */
+    public int getLevelsCount(ByteBuffer buf) {
+        return buf.get(LVLS_OFF);
+    }
+
+    /**
+     * @param buf  Buffer.
+     * @param lvls Number of levels in this tree.
+     */
+    public void setLevelsCount(ByteBuffer buf, int lvls) {
+        assert lvls >= 0 && lvls < 30;
+
+        buf.put(LVLS_OFF, (byte)lvls);
+
+        assert getLevelsCount(buf) == lvls;
+    }
+
+    /**
+     * @param lvl Level.
+     * @return Offset for page reference.
+     */
+    private static int offset(int lvl) {
+        return lvl * 8 + REFS_OFF;
+    }
+
+    /**
+     * @param buf Buffer.
+     * @param lvl Level.
+     * @return Page reference at that level.
+     */
+    public long getLeftmostPageId(ByteBuffer buf, int lvl) {
+        return buf.getLong(offset(lvl));
+    }
+
+    /**
+     * @param buf    Buffer.
+     * @param lvl    Level.
+     * @param pageId Page ID.
+     */
+    public void setLeftmostPageId(ByteBuffer buf, int lvl, long pageId) {
+        assert lvl >= 0 && lvl < getLevelsCount(buf);
+
+        buf.putLong(offset(lvl), pageId);
+
+        assert getLeftmostPageId(buf, lvl) == pageId;
+    }
+
+    /**
+     * @param buf Buffer.
+     * @return Root level.
+     */
+    public int getRootLevel(ByteBuffer buf) {
+        int lvls = getLevelsCount(buf); // The highest level page is root.
+
+        assert lvls > 0 : lvls;
+
+        return lvls - 1;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/cbfed9cf/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/DataPageIO.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/DataPageIO.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/DataPageIO.java
new file mode 100644
index 0000000..ffa5fc1
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/DataPageIO.java
@@ -0,0 +1,268 @@
+/*
+ * 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.tree.io;
+
+import java.nio.ByteBuffer;
+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.version.GridCacheVersion;
+
+/**
+ * Data pages IO.
+ */
+public class DataPageIO extends PageIO {
+    /** */
+    public static final IORegistry<DataPageIO> VERSIONS = new IORegistry<>(
+        new DataPageIO(1)
+    );
+
+    /** */
+    private static final int OCCUPIED_SIZE_OFF = COMMON_HEADER_END;
+
+    /** */
+    private static final int ALL_CNT_OFF = OCCUPIED_SIZE_OFF + 2;
+
+    /** */
+    private static final int LIVE_CNT_OFF = ALL_CNT_OFF + 2;
+
+    /** */
+    private static final int ITEMS_OFF = LIVE_CNT_OFF + 2;
+
+    /** */
+    private static final int ITEM_SIZE = 2;
+
+    /**
+     * @param ver Page format version.
+     */
+    protected DataPageIO(int ver) {
+        super(ver);
+    }
+
+    /** {@inheritDoc} */
+    @Override public int getType() {
+        return T_DATA;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void initNewPage(ByteBuffer buf, long pageId) {
+        super.initNewPage(buf, pageId);
+
+        setAllCount(buf, 0);
+        setLiveCount(buf, 0);
+        setOccupiedSize(buf, 0);
+    }
+
+    public int getOccupiedSize(ByteBuffer buf) {
+        return buf.getShort(OCCUPIED_SIZE_OFF) & 0xFFFF;
+    }
+
+    public void setOccupiedSize(ByteBuffer buf, int size) {
+        buf.putShort(OCCUPIED_SIZE_OFF, (short)size);
+
+        assert getOccupiedSize(buf) == size;
+    }
+
+    public int getAllCount(ByteBuffer buf) {
+        return buf.getShort(ALL_CNT_OFF) & 0xFFFF;
+    }
+
+    public void setAllCount(ByteBuffer buf, int cnt) {
+        buf.putShort(ALL_CNT_OFF, (short)cnt);
+
+        assert cnt == getAllCount(buf);
+    }
+
+    public int getLiveCount(ByteBuffer buf) {
+        return buf.getShort(LIVE_CNT_OFF) & 0xFFFF;
+    }
+
+    public void setLiveCount(ByteBuffer buf, int cnt) {
+        buf.putShort(LIVE_CNT_OFF, (short)cnt);
+
+        assert cnt == getLiveCount(buf);
+    }
+
+    public boolean canAddEntry(ByteBuffer buf, int entrySize) {
+        int free = buf.capacity() - ITEMS_OFF - getOccupiedSize(buf);
+
+        if (free < entrySize)
+            return false;
+
+        free -= (getAllCount(buf) - getLiveCount(buf)) * ITEM_SIZE;
+
+        return free >= entrySize;
+    }
+
+    /**
+     * @param keySize Key size.
+     * @param valSize Value size.
+     * @return Entry size including item.
+     */
+    private static int entrySize(int keySize, int valSize) {
+        return ITEM_SIZE + 2/*key+val len*/ + keySize + valSize + 24/*ver*/;
+    }
+
+    /**
+     * @param idx Index of item.
+     * @return Offset in bytes.
+     */
+    private static int offset(int idx) {
+        return ITEMS_OFF + idx * ITEM_SIZE;
+    }
+
+    /**
+     * @param buf Buffer.
+     * @param idx Index of item.
+     * @return Data offset in bytes.
+     */
+    public int getDataOffset(ByteBuffer buf, int idx) {
+        return buf.getShort(offset(idx)) & 0xFFFF;
+    }
+
+    /**
+     * @param buf Buffer.
+     * @param idx Index of item.
+     * @param dataOff Data offset in bytes.
+     */
+    private void setDataOffset(ByteBuffer buf, int idx, int dataOff) {
+        buf.putShort(offset(idx), (short)dataOff);
+
+        assert dataOff == getDataOffset(buf, idx);
+    }
+
+    /**
+     * Make a window for data entry.
+     *
+     * @param buf Buffer.
+     * @param idx Index of the new item.
+     * @param allCnt All count.
+     * @param entrySize Entry size.
+     * @return Data offset for the new entry.
+     */
+    public int makeWindow(ByteBuffer buf, int idx, int allCnt, int entrySize) {
+        if (idx == allCnt) { // Adding to the end of items.
+            int off = offset(idx);
+            int lastDataOff = allCnt == 0 ? buf.capacity() : 
getDataOffset(buf, allCnt - 1);
+
+            if (lastDataOff - off < entrySize) // TODO try to defragment
+                return -1;
+
+            return lastDataOff - entrySize + ITEM_SIZE;
+        }
+        else {
+            //TODO defragment page with respect to idx and entrySize (if idx 
is not last, the window must be not first)
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    public int addRow(
+        CacheObjectContext coctx,
+        ByteBuffer buf,
+        CacheObject key,
+        CacheObject val,
+        GridCacheVersion ver) throws IgniteCheckedException
+    {
+        int keyLen = key.valueBytesLength(coctx);
+        int valLen = val.valueBytesLength(coctx);
+        int entrySize = entrySize(keyLen, valLen);
+
+        if (entrySize >= buf.capacity() - ITEMS_OFF)
+            throw new IgniteException("Too big entry: " + keyLen + " " + 
valLen);
+
+        if (!canAddEntry(buf, entrySize))
+            return -1;
+
+        int liveCnt = getLiveCount(buf);
+        int allCnt = getAllCount(buf);
+        int idx = 0;
+
+        if (allCnt == liveCnt)
+            idx = allCnt; // Allocate new idx at allCnt if all are alive.
+        else {
+            // Lookup for a free parking lot.
+            while (idx < allCnt) {
+                if (getDataOffset(buf, idx) == 0)
+                    break;
+
+                idx++;
+            }
+        }
+
+        int dataOff = makeWindow(buf, idx, allCnt, entrySize);
+
+        if (dataOff == -1)
+            return -1;
+
+        // Write data.
+        writeRowDataInPlace(coctx, buf, dataOff, keyLen + valLen, key, val, 
ver);
+        // Write item.
+        setDataOffset(buf, idx, dataOff);
+
+        // Update header.
+        setOccupiedSize(buf, getOccupiedSize(buf) + entrySize);
+        setAllCount(buf, allCnt + 1);
+        setLiveCount(buf, liveCnt + 1);
+
+        return idx;
+    }
+
+    /**
+     * @param buf Buffer.
+     * @param dataOff Data offset.
+     * @param key Key.
+     * @param val Value.
+     * @param ver Version.
+     */
+    public void writeRowDataInPlace(
+        CacheObjectContext coctx,
+        ByteBuffer buf,
+        int dataOff,
+        int keyValLen,
+        CacheObject key,
+        CacheObject val,
+        GridCacheVersion ver
+    ) throws IgniteCheckedException {
+        try {
+            buf.position(dataOff);
+
+            buf.putShort((short)keyValLen);
+
+            boolean written = key.putValue(buf, coctx);
+
+            assert written;
+
+            written = val.putValue(buf, coctx);
+
+            assert written;
+
+            buf.putInt(ver.topologyVersion());
+            buf.putInt(ver.nodeOrderAndDrIdRaw());
+            buf.putLong(ver.globalTime());
+            buf.putLong(ver.order());
+        }
+        finally {
+            buf.position(0);
+        }
+    }
+
+    public int getKeyValueSize(ByteBuffer buf, int idx) {
+        return buf.getShort(getDataOffset(buf, idx)) & 0xFFFF;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/cbfed9cf/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/IORegistry.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/IORegistry.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/IORegistry.java
new file mode 100644
index 0000000..c95a45d
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/IORegistry.java
@@ -0,0 +1,82 @@
+/*
+ * 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.tree.io;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Registry for IO versions.
+ */
+public final class IORegistry<V extends PageIO> {
+    /** */
+    private final V[] vers;
+
+    /**
+     * @param vers Versions.
+     */
+    @SafeVarargs
+    public IORegistry(V... vers) {
+        assert vers != null;
+        assert vers.length > 0;
+
+        this.vers = vers;
+
+        assert checkVersions();
+    }
+
+    /**
+     * @return {@code true} If versions are correct.
+     */
+    private boolean checkVersions() {
+        for (int i = 0; i < vers.length; i++) {
+            if (vers[i].getVersion() != i + 1)
+                return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * @return Latest IO version.
+     */
+    public V latest() {
+        return forVersion(vers.length);
+    }
+
+    /**
+     * @param ver Version.
+     * @return IO.
+     */
+    public V forVersion(int ver) {
+        return vers[ver - 1];
+    }
+
+    /**
+     * @param buf Buffer.
+     * @return IO.
+     */
+    public V forPage(ByteBuffer buf) {
+        int ver = PageIO.getVersion(buf);
+
+        V res = forVersion(ver);
+
+        assert res.getType() == PageIO.getType(buf);
+
+        return res;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/cbfed9cf/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
new file mode 100644
index 0000000..001d5cc
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/PageIO.java
@@ -0,0 +1,166 @@
+/*
+ * 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.tree.io;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Base format for all the page types.
+ */
+public abstract class PageIO {
+    /** */
+    private static final int TYPE_OFF = 0;
+
+    /** */
+    private static final int VER_OFF = TYPE_OFF + 2;
+
+    /** */
+    private static final int PAGE_ID_OFF = VER_OFF + 2;
+
+    /** */
+    private static final int CRC_OFF = PAGE_ID_OFF + 8;
+
+    /** */
+    public static final int COMMON_HEADER_END = 32; // type(2) + ver(2) + 
pageId(8) + crc(4) + reserved(16)
+
+    /* All the page types. */
+
+    /** */
+    public static final short T_DATA = 1;
+
+    /** */
+    public static final short T_BPLUS_META = 2;
+
+    /** */
+    public static final short T_H2_REF_LEAF = 3;
+
+    /** */
+    public static final short T_H2_REF_INNER = 4;
+
+    /** */
+    private final int ver;
+
+    /**
+     * @param ver Page format version.
+     */
+    protected PageIO(int ver) {
+        assert ver > 0 && ver < 65535: ver;
+
+        this.ver = ver;
+    }
+
+
+
+    /**
+     * @return Page type.
+     */
+    public static int getType(ByteBuffer buf) {
+        return buf.getShort(TYPE_OFF) & 0xFFFF;
+    }
+
+    /**
+     * @param buf Buffer.
+     * @param type Type.
+     */
+    public static void setType(ByteBuffer buf, int type) {
+        assert type >= T_DATA && type <= T_H2_REF_INNER : type;
+
+        buf.putShort(TYPE_OFF, (short)type);
+
+        assert getType(buf) == type;
+    }
+
+    /**
+     * @param buf Buffer.
+     * @return Version.
+     */
+    public static int getVersion(ByteBuffer buf) {
+        return buf.getShort(VER_OFF) & 0xFFFF;
+    }
+
+    /**
+     * @param buf Buffer.
+     * @param ver Version.
+     */
+    public static void setVersion(ByteBuffer buf, int ver) {
+        buf.putShort(VER_OFF, (short)ver);
+
+        assert getVersion(buf) == ver;
+    }
+
+    /**
+     * @param buf Buffer.
+     * @return Page ID.
+     */
+    public static long getPageId(ByteBuffer buf) {
+        return buf.getLong(PAGE_ID_OFF);
+    }
+
+    /**
+     * @param buf Buffer.
+     * @param pageId Page ID.
+     */
+    public static void setPageId(ByteBuffer buf, long pageId) {
+        buf.putLong(PAGE_ID_OFF, pageId);
+
+        assert getPageId(buf) == pageId;
+    }
+
+    /**
+     * @param buf Buffer.
+     * @return Checksum.
+     */
+    public static int getCrc(ByteBuffer buf) {
+        return buf.getInt(CRC_OFF);
+    }
+
+    /**
+     * @param buf Buffer.
+     * @param crc Checksum.
+     */
+    public static void setCrc(ByteBuffer buf, int crc) {
+        buf.putInt(CRC_OFF, crc);
+    }
+
+    /**
+     * @return Type.
+     */
+    public abstract int getType();
+
+    /**
+     * @return Version.
+     */
+    public final int getVersion() {
+        return ver;
+    }
+
+    /**
+     * @param buf Buffer.
+     * @param pageId Page ID.
+     */
+    public void initNewPage(ByteBuffer buf, long pageId) {
+        setType(buf, getType());
+        setVersion(buf, getVersion());
+        setPageId(buf, pageId);
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return getClass().getSimpleName() + "[ver=" + getVersion() + "]";
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/cbfed9cf/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/util/PageHandler.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/util/PageHandler.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/util/PageHandler.java
new file mode 100644
index 0000000..3d1b4e4
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/util/PageHandler.java
@@ -0,0 +1,111 @@
+/*
+ * 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.tree.util;
+
+import java.nio.ByteBuffer;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.internal.pagemem.Page;
+
+/**
+ * Page handler. Can do {@link #readPage(Page, PageHandler, Object, int, int)}
+ * and {@link #writePage(Page, PageHandler, Object, int, int)} operations.
+ */
+public abstract class PageHandler<X> {
+    /**
+     * @param page Page.
+     * @param buf Page buffer.
+     * @param arg Argument.
+     * @param intArg Argument of type {@code int}.
+     * @return Result.
+     * @throws IgniteCheckedException If failed.
+     */
+    public abstract int run(Page page, ByteBuffer buf, X arg, int intArg) 
throws IgniteCheckedException;
+
+    /**
+     * @param page Page.
+     * @param arg Argument.
+     * @param intArg Argument of type {@code int}.
+     * @return {@code true} If release.
+     */
+    public boolean releaseAfterWrite(Page page, X arg, int intArg) {
+        return true;
+    }
+
+    /**
+     * @param page Page.
+     * @param h Handler.
+     * @param arg Argument.
+     * @param intArg Argument of type {@code int}.
+     * @param dfltRes Default result in case of page invalidation.
+     * @return Handler result.
+     * @throws IgniteCheckedException If failed.
+     */
+    public static <X> int readPage(Page page, PageHandler<X> h, X arg, int 
intArg, int dfltRes)
+        throws IgniteCheckedException {
+        if (page == null)
+            return dfltRes;
+
+        ByteBuffer buf = page.getForRead();
+
+        if (buf == null)
+            return dfltRes;
+
+        try {
+            return h.run(page, buf, arg, intArg);
+        }
+        finally {
+            page.releaseRead();
+        }
+    }
+
+    /**
+     * @param page Page.
+     * @param h Handler.
+     * @param arg Argument.
+     * @param intArg Argument of type {@code int}.
+     * @param dfltRes Default result in case of page invalidation.
+     * @return Handler result.
+     * @throws IgniteCheckedException If failed.
+     */
+    public static <X> int writePage(Page page, PageHandler<X> h, X arg, int 
intArg, int dfltRes)
+        throws IgniteCheckedException {
+        if (page == null)
+            return dfltRes;
+
+        int res;
+
+        boolean ok = false;
+
+        ByteBuffer buf = page.getForWrite();
+
+        if (buf == null)
+            return dfltRes;
+
+        try {
+            res = h.run(page, buf, arg, intArg);
+
+            ok = true;
+        }
+        finally {
+            if (h.releaseAfterWrite(page, arg, intArg))
+                page.releaseWrite(ok);
+        }
+
+        return res;
+    }
+}

Reply via email to