ignite-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sboi...@apache.org
Subject [09/50] ignite git commit: ignite-db - free
Date Thu, 28 Apr 2016 08:52:39 GMT
ignite-db - free


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

Branch: refs/heads/ignite-db-x-10884
Commit: e7d7e2cfad67c28ec448803239fd13ae8fbfa26e
Parents: d914e21
Author: S.Vladykin <svladykin@gridgain.com>
Authored: Fri Apr 22 01:37:11 2016 +0300
Committer: S.Vladykin <svladykin@gridgain.com>
Committed: Fri Apr 22 01:37:11 2016 +0300

----------------------------------------------------------------------
 .../processors/cache/database/RowStore.java     |  28 ++--
 .../cache/database/freelist/FreeItem.java       |  48 +------
 .../cache/database/freelist/FreeList.java       | 131 +++++++++++--------
 .../cache/database/freelist/FreeTree.java       |  24 +++-
 .../cache/database/freelist/io/FreeIO.java      |   8 +-
 .../cache/database/freelist/io/FreeInnerIO.java |  51 +++++---
 .../cache/database/freelist/io/FreeLeafIO.java  |  28 ++--
 .../cache/database/tree/io/DataPageIO.java      |  57 +++++---
 .../cache/database/tree/util/PageHandler.java   |   4 +-
 9 files changed, 210 insertions(+), 169 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/e7d7e2cf/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/RowStore.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/RowStore.java
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/RowStore.java
index 2ea2ee4..fdfadd6 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/RowStore.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/RowStore.java
@@ -54,25 +54,30 @@ public class RowStore<T extends CacheDataRow> {
     private volatile long lastDataPageId;
 
     /** */
+    @Deprecated
     private final PageHandler<CacheDataRow> writeRow = new PageHandler<CacheDataRow>()
{
         @Override public int run(Page page, ByteBuffer buf, CacheDataRow row, int ignore)
throws IgniteCheckedException {
             int entrySize = DataPageIO.getEntrySize(coctx, row.key(), row.value());
 
             DataPageIO io = DataPageIO.VERSIONS.forPage(buf);
 
+            if (io.isEnoughSpace(buf, entrySize))
+                return -1;
+
             int idx = io.addRow(coctx, buf, row.key(), row.value(), row.version(), entrySize);
 
-            if (idx != -1) {
-                row.link(linkFromDwordOffset(page.id(), idx));
+            assert idx >= 0: idx;
 
-                assert row.link() != 0;
-            }
+            row.link(linkFromDwordOffset(page.id(), idx));
+
+            assert row.link() != 0;
 
             return idx;
         }
     };
 
     /** */
+    @Deprecated
     private final PageHandler<Void> rmvRow = new PageHandler<Void>() {
         @Override public int run(Page page, ByteBuffer buf, Void ignore, int itemId) throws
IgniteCheckedException {
             DataPageIO io = DataPageIO.VERSIONS.forPage(buf);
@@ -125,9 +130,13 @@ public class RowStore<T extends CacheDataRow> {
     public void removeRow(long link) throws IgniteCheckedException {
         assert link != 0;
 
-        try (Page page = page(pageId(link))) {
-            writePage(page, rmvRow, null, dwordsOffset(link), 0);
+        if (freeList == null) {
+            try (Page page = page(pageId(link))) {
+                writePage(page, rmvRow, null, dwordsOffset(link), 0);
+            }
         }
+        else
+            freeList.removeRow(link);
     }
 
     /**
@@ -156,16 +165,17 @@ public class RowStore<T extends CacheDataRow> {
      */
     public void addRow(CacheDataRow row) throws IgniteCheckedException {
         if (freeList == null)
-            writeRowData0(row);
+            writeRowDataOld(row);
         else
-            freeList.writeRowData(row);
+            freeList.insertRow(row);
     }
 
     /**
      * @param row Row.
      * @throws IgniteCheckedException If failed.
      */
-    private void writeRowData0(CacheDataRow row) throws IgniteCheckedException {
+    @Deprecated
+    private void writeRowDataOld(CacheDataRow row) throws IgniteCheckedException {
         assert row.link() == 0;
 
         while (row.link() == 0) {

http://git-wip-us.apache.org/repos/asf/ignite/blob/e7d7e2cf/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/FreeItem.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/FreeItem.java
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/FreeItem.java
index 7de30c7..2c81074 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/FreeItem.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/FreeItem.java
@@ -26,38 +26,17 @@ public class FreeItem extends FullPageId {
     /** */
     private short freeSpace;
 
-    /** */
-    private short dispersion;
-
     /**
      * @param freeSpace Free space.
-     * @param dispersion Dispersion.
      * @param pageId  Page ID.
      * @param cacheId Cache ID.
      */
-    public FreeItem(short freeSpace, short dispersion, long pageId, int cacheId) {
+    public FreeItem(int freeSpace, long pageId, int cacheId) {
         super(pageId, cacheId);
 
-        assert freeSpace >= 0: freeSpace;
-
-        this.freeSpace = freeSpace;
-        this.dispersion = dispersion;
-    }
-
-    /**
-     * @param freeSpace Free space.
-     * @param dispersion Dispersion.
-     * @return Dispersed free space.
-     */
-    public static int disperse(int freeSpace, int dispersion) {
-        return (freeSpace << 16) | dispersion;
-    }
+        assert freeSpace >= 0 && freeSpace <= Short.MAX_VALUE: freeSpace;
 
-    /**
-     * @return Dispersed free space.
-     */
-    public int dispersedFreeSpace() {
-        return disperse(freeSpace, dispersion);
+        this.freeSpace = (short)freeSpace;
     }
 
     /**
@@ -66,25 +45,4 @@ public class FreeItem extends FullPageId {
     public short freeSpace() {
         return freeSpace;
     }
-
-    /**
-     * @param freeSpace Free space.
-     */
-    public void freeSpace(short freeSpace) {
-        this.freeSpace = freeSpace;
-    }
-
-    /**
-     * @return Dispersion.
-     */
-    public short dispersion() {
-        return dispersion;
-    }
-
-    /**
-     * @param dispersion Dispersion.
-     */
-    public void dispersion(short dispersion) {
-        this.dispersion = dispersion;
-    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/e7d7e2cf/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/FreeList.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/FreeList.java
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/FreeList.java
index a7507a0..68780c2 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/FreeList.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/FreeList.java
@@ -18,11 +18,11 @@
 package org.apache.ignite.internal.processors.cache.database.freelist;
 
 import java.nio.ByteBuffer;
-import java.util.concurrent.ThreadLocalRandom;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.internal.pagemem.FullPageId;
 import org.apache.ignite.internal.pagemem.Page;
 import org.apache.ignite.internal.pagemem.PageIdAllocator;
+import org.apache.ignite.internal.pagemem.PageIdUtils;
 import org.apache.ignite.internal.pagemem.PageMemory;
 import org.apache.ignite.internal.processors.cache.GridCacheContext;
 import org.apache.ignite.internal.processors.cache.database.CacheDataRow;
@@ -61,7 +61,41 @@ public class FreeList {
 
             assert idx >= 0;
 
-            return io.getFreeSpace(buf);
+            int freeSpace = io.getFreeSpace(buf);
+
+            // Put our free item.
+            tree(row.partition()).put(new FreeItem(freeSpace, page.id(), cctx.cacheId()));
+
+            return 0;
+        }
+    };
+
+    /** */
+    private final PageHandler<FreeTree> removeRow = new PageHandler<FreeTree>()
{
+        @Override public int run(Page page, ByteBuffer buf, FreeTree tree, int itemId) throws
IgniteCheckedException {
+            DataPageIO io = DataPageIO.VERSIONS.forPage(buf);
+
+            assert DataPageIO.check(itemId): itemId;
+
+            int oldFreeSpace = io.getFreeSpace(buf);
+
+            io.removeRow(buf, (byte)itemId);
+
+            int newFreeSpace = io.getFreeSpace(buf);
+
+            // Move page to the new position with respect to the new free space.
+            FreeItem item = tree.remove(new FreeItem(oldFreeSpace, page.id(), cctx.cacheId()));
+
+            // If item is null, then it was removed concurrently by insertRow, because
+            // in removeRow we own the write lock on this page. Thus we can be sure that
+            // insertRow will update position correctly after us.
+            if (item != null) {
+                FreeItem old = tree.put(new FreeItem(newFreeSpace, page.id(), cctx.cacheId()));
+
+                assert old == null;
+            }
+
+            return 0;
         }
     };
 
@@ -83,14 +117,12 @@ public class FreeList {
 
     /**
      * @param tree Tree.
-     * @param neededSpace Needed free space.
+     * @param lookupItem Lookup item.
      * @return Free item or {@code null} if it was impossible to find one.
      * @throws IgniteCheckedException If failed.
      */
-    private FreeItem take(FreeTree tree, short neededSpace) throws IgniteCheckedException
{
-        assert neededSpace > 0 && neededSpace < Short.MAX_VALUE: neededSpace;
-
-        FreeItem res = tree.removeCeil(new FreeItem(neededSpace, dispersion(), 0, 0));
+    private FreeItem take(FreeTree tree, FreeItem lookupItem) throws IgniteCheckedException
{
+        FreeItem res = tree.removeCeil(lookupItem);
 
         assert res == null || (res.pageId() != 0 && res.cacheId() == cctx.cacheId()):
res;
 
@@ -98,35 +130,28 @@ public class FreeList {
     }
 
     /**
-     * @return Random dispersion value.
-     */
-    private static short dispersion() {
-        return (short)ThreadLocalRandom.current().nextInt(Short.MIN_VALUE, Short.MAX_VALUE);
-    }
-
-    /**
-     * @param part Partition.
+     * @param partId Partition.
      * @return Tree.
      * @throws IgniteCheckedException If failed.
      */
-    private FreeTree tree(Integer part) throws IgniteCheckedException {
-        assert part >= 0 && part < Short.MAX_VALUE: part;
+    private FreeTree tree(Integer partId) throws IgniteCheckedException {
+        assert partId >= 0 && partId < Short.MAX_VALUE: partId;
 
-        GridFutureAdapter<FreeTree> fut = trees.get(part);
+        GridFutureAdapter<FreeTree> fut = trees.get(partId);
 
         if (fut == null) {
             fut = new GridFutureAdapter<>();
 
-            if (trees.putIfAbsent(part, fut) != null)
-                fut = trees.get(part);
+            if (trees.putIfAbsent(partId, fut) != null)
+                fut = trees.get(partId);
             else {
                 // Index name will be the same across restarts.
-                String idxName = part + "$$" + cctx.cacheId() + "_free";
+                String idxName = partId + "$$" + cctx.cacheId() + "_free";
 
                 IgniteBiTuple<FullPageId,Boolean> t = cctx.shared().database().meta()
                     .getOrAllocateForIndex(cctx.cacheId(), idxName);
 
-                fut.onDone(new FreeTree(reuseList, cctx.cacheId(), pageMem, t.get1(), t.get2()));
+                fut.onDone(new FreeTree(reuseList, cctx.cacheId(), partId, pageMem, t.get1(),
t.get2()));
             }
         }
 
@@ -134,59 +159,51 @@ public class FreeList {
     }
 
     /**
+     * @param link Row link.
+     * @throws IgniteCheckedException
+     */
+    public void removeRow(long link) throws IgniteCheckedException {
+        assert link != 0;
+
+        long pageId = PageIdUtils.pageId(link);
+        int itemId = PageIdUtils.dwordsOffset(link);
+
+        try (Page page = pageMem.page(new FullPageId(pageId, cctx.cacheId()))) {
+            writePage(page, removeRow, null, itemId, -1);
+        }
+    }
+
+    /**
      * @param row Row.
      * @throws IgniteCheckedException If failed.
      */
-    public void writeRowData(CacheDataRow row) throws IgniteCheckedException {
-        // assert row.link == 0;
+    public void insertRow(CacheDataRow row) throws IgniteCheckedException {
+        assert row.link() == 0: row.link();
 
         int entrySize = DataPageIO.getEntrySize(cctx.cacheObjectContext(), row.key(), row.value());
 
         assert entrySize > 0 && entrySize < Short.MAX_VALUE: entrySize;
 
         FreeTree tree = tree(row.partition());
-        FreeItem item = take(tree, (short)entrySize);
 
-        Page page = null;
-        int freeSpace = -1;
+        // TODO add random pageIndex here for lower contention?
+        FreeItem item = take(tree, new FreeItem(entrySize, 0, cctx.cacheId()));
 
-        try {
+        try (Page page = item == null ?
+            allocateDataPage(row.partition()) :
+            pageMem.page(item)
+        ) {
             if (item == null) {
                 DataPageIO io = DataPageIO.VERSIONS.latest();
 
-                page = allocatePage(row.partition());
-
                 ByteBuffer buf = page.getForInitialWrite();
 
                 io.initNewPage(buf, page.id());
 
-                freeSpace = writeRow.run(page, buf, row, entrySize);
-            }
-            else {
-                page = pageMem.page(item);
-
-                freeSpace = writePage(page, writeRow, row, entrySize, -1);
-            }
-        }
-        finally {
-            if (page != null) {
-                page.close();
-
-                if (freeSpace != -1) { // Put back to the tree.
-                    assert freeSpace >= 0 && freeSpace < Short.MAX_VALUE: freeSpace;
-
-                    if (item == null)
-                        item = new FreeItem((short)freeSpace, dispersion(), page.id(), cctx.cacheId());
-                    else {
-                        item.freeSpace((short)freeSpace);
-                        item.dispersion(dispersion());
-                    }
-
-                    FreeItem old = tree.put(item);
-
-                    assert old == null;
-                }
+                writeRow.run(page, buf, row, entrySize);
             }
+            else
+                writePage(page, writeRow, row, entrySize, -1);
         }
     }
 
@@ -195,7 +212,7 @@ public class FreeList {
      * @return Page.
      * @throws IgniteCheckedException If failed.
      */
-    private Page allocatePage(int part) throws IgniteCheckedException {
+    private Page allocateDataPage(int part) throws IgniteCheckedException {
         FullPageId pageId = pageMem.allocatePage(cctx.cacheId(), part, PageIdAllocator.FLAG_DATA);
 
         return pageMem.page(pageId);

http://git-wip-us.apache.org/repos/asf/ignite/blob/e7d7e2cf/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/FreeTree.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/FreeTree.java
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/FreeTree.java
index 8af7561..c5138c5 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/FreeTree.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/FreeTree.java
@@ -35,6 +35,9 @@ import org.apache.ignite.internal.processors.cache.database.tree.reuse.ReuseList
  * Data structure for data pages and their free spaces.
  */
 public class FreeTree extends BPlusTree<FreeItem, FreeItem> {
+    /** */
+    private final int partId;
+
     /**
      * @param reuseList Reuse list.
      * @param cacheId Cache ID.
@@ -43,16 +46,25 @@ public class FreeTree extends BPlusTree<FreeItem, FreeItem> {
      * @param initNew    Initialize new index.
      * @throws IgniteCheckedException If failed.
      */
-    public FreeTree(ReuseList reuseList, int cacheId, PageMemory pageMem, FullPageId metaPageId,
boolean initNew)
+    public FreeTree(ReuseList reuseList, int cacheId, int partId, PageMemory pageMem, FullPageId
metaPageId, boolean initNew)
         throws IgniteCheckedException {
         super(cacheId, pageMem, metaPageId, reuseList);
 
+        this.partId = partId;
+
         assert pageMem != null;
 
         if (initNew)
             initNew();
     }
 
+    /**
+     * @return Partition ID.
+     */
+    public int getPartId() {
+        return partId;
+    }
+
     /** {@inheritDoc} */
     @Override protected BPlusIO<FreeItem> io(int type, int ver) {
         if (type == PageIO.T_FREE_INNER)
@@ -76,12 +88,12 @@ public class FreeTree extends BPlusTree<FreeItem, FreeItem> {
     /** {@inheritDoc} */
     @Override protected int compare(BPlusIO<FreeItem> io, ByteBuffer buf, int idx,
FreeItem row)
         throws IgniteCheckedException {
-        if (io.isLeaf()) // In a leaf we can do a fair compare.
-            return Short.compare(((FreeIO)io).freeSpace(buf, idx), row.freeSpace());
+        int res = Short.compare(((FreeIO)io).getFreeSpace(buf, idx), row.freeSpace());
+
+        if (res == 0)
+            res = Long.compare(((FreeLeafIO)io).getPageIndex(buf, idx), FreeInnerIO.pageIndex(row.pageId()));
 
-        // In inner pages we do compare on dispersed free space to avoid contention on a
single page
-        // when all the entries are equal and many pages have the same free space.
-        return Integer.compare(((FreeIO)io).dispersedFreeSpace(buf, idx), row.dispersedFreeSpace());
+        return res;
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/e7d7e2cf/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/io/FreeIO.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/io/FreeIO.java
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/io/FreeIO.java
index de28b22..d893b27 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/io/FreeIO.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/io/FreeIO.java
@@ -26,14 +26,14 @@ public interface FreeIO {
     /**
      * @param buf Buffer.
      * @param idx Index.
-     * @return Dispersed free space.
+     * @return Free space.
      */
-    public int dispersedFreeSpace(ByteBuffer buf, int idx);
+    public short getFreeSpace(ByteBuffer buf, int idx);
 
     /**
      * @param buf Buffer.
      * @param idx Index.
-     * @return Free space.
+     * @return Page index.
      */
-    public short freeSpace(ByteBuffer buf, int idx);
+    public int getPageIndex(ByteBuffer buf, int idx);
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/e7d7e2cf/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/io/FreeInnerIO.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/io/FreeInnerIO.java
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/io/FreeInnerIO.java
index b9d13b8..14c7a00 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/io/FreeInnerIO.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/io/FreeInnerIO.java
@@ -1,7 +1,10 @@
 package org.apache.ignite.internal.processors.cache.database.freelist.io;
 
 import java.nio.ByteBuffer;
+import org.apache.ignite.internal.pagemem.PageIdAllocator;
+import org.apache.ignite.internal.pagemem.PageIdUtils;
 import org.apache.ignite.internal.processors.cache.database.freelist.FreeItem;
+import org.apache.ignite.internal.processors.cache.database.freelist.FreeTree;
 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;
@@ -20,48 +23,62 @@ public class FreeInnerIO extends BPlusInnerIO<FreeItem> implements
FreeIO {
      * @param ver Page format version.
      */
     protected FreeInnerIO(int ver) {
-        super(T_FREE_INNER, ver, false, 4); // freeSpace(2) + dispersion(2)
+        super(T_FREE_INNER, ver, false, 6); // freeSpace(2) + pageIndex(4)
+    }
+
+    /**
+     * @param pageId Page Id.
+     * @return Page index.
+     */
+    public static int pageIndex(long pageId) {
+        long idx = PageIdUtils.pageIdx(pageId);
+
+        assert idx >= 0 && idx < Integer.MAX_VALUE: idx;
+
+        return (int)idx;
     }
 
     /** {@inheritDoc} */
     @Override public void store(ByteBuffer buf, int idx, FreeItem row) {
-        store(buf, idx, row.dispersedFreeSpace());
+        int off = offset(idx);
+
+        buf.putShort(off, row.freeSpace());
+        buf.putInt(off + 2, pageIndex(row.pageId()));
     }
 
     /** {@inheritDoc} */
     @Override public void store(ByteBuffer dst, int dstIdx, BPlusIO<FreeItem> srcIo,
ByteBuffer src, int srcIdx) {
-        store(dst, dstIdx, ((FreeIO)srcIo).dispersedFreeSpace(src, srcIdx));
-    }
+        FreeIO srcFreeIo = (FreeIO)srcIo;
 
-    /**
-     * @param buf Buffer.
-     * @param idx Index.
-     * @param dispersedFreeSpace Dispersed free space.
-     */
-    private void store(ByteBuffer buf, int idx, int dispersedFreeSpace) {
-        int off = offset(idx);
+        int off = offset(dstIdx);
 
-        buf.putInt(off, dispersedFreeSpace);
+        dst.putShort(off, srcFreeIo.getFreeSpace(src, srcIdx));
+        dst.putInt(off + 2, srcFreeIo.getPageIndex(src, srcIdx));
     }
 
     /** {@inheritDoc} */
-    @Override public int dispersedFreeSpace(ByteBuffer buf, int idx) {
+    @Override public short getFreeSpace(ByteBuffer buf, int idx) {
         int off = offset(idx);
 
-        return buf.getInt(off);
+        return buf.getShort(off);
     }
 
     /** {@inheritDoc} */
-    @Override public short freeSpace(ByteBuffer buf, int idx) {
+    @Override public int getPageIndex(ByteBuffer buf, int idx) {
         int off = offset(idx);
 
-        return buf.getShort(off);
+        return buf.getInt(off + 2);
     }
 
     /** {@inheritDoc} */
     @Override public FreeItem getLookupRow(BPlusTree<FreeItem, ?> tree, ByteBuffer
buf, int idx) {
         int off = offset(idx);
 
-        return new FreeItem(buf.getShort(off), buf.getShort(off + 2), 0, 0);
+        short freeSpace = buf.getShort(off);
+        int pageIdx = buf.getInt(off + 2);
+
+        long pageId = PageIdUtils.pageId(((FreeTree)tree).getPartId(), PageIdAllocator.FLAG_DATA,
pageIdx);
+
+        return new FreeItem(freeSpace, pageId, tree.getCacheId());
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/e7d7e2cf/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/io/FreeLeafIO.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/io/FreeLeafIO.java
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/io/FreeLeafIO.java
index 5496897..8503c7d 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/io/FreeLeafIO.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/io/FreeLeafIO.java
@@ -18,10 +18,13 @@
 package org.apache.ignite.internal.processors.cache.database.freelist.io;
 
 import java.nio.ByteBuffer;
+import org.apache.ignite.internal.pagemem.PageIdAllocator;
+import org.apache.ignite.internal.pagemem.PageIdUtils;
+import org.apache.ignite.internal.processors.cache.database.freelist.FreeItem;
+import org.apache.ignite.internal.processors.cache.database.freelist.FreeTree;
 import org.apache.ignite.internal.processors.cache.database.tree.BPlusTree;
 import org.apache.ignite.internal.processors.cache.database.tree.io.BPlusLeafIO;
 import org.apache.ignite.internal.processors.cache.database.tree.io.IOVersions;
-import org.apache.ignite.internal.processors.cache.database.freelist.FreeItem;
 
 /**
  * Routines for free list leaf pages.
@@ -36,35 +39,40 @@ public class FreeLeafIO extends BPlusLeafIO<FreeItem> implements
FreeIO {
      * @param ver Page format version.
      */
     protected FreeLeafIO(int ver) {
-        super(T_FREE_LEAF, ver, 12); // freeSpace(2) + dispersion(2) + pageId(8)
+        super(T_FREE_LEAF, ver, 6); // freeSpace(2) + pageIndex(4)
     }
 
     /** {@inheritDoc} */
-    @Override public final void store(ByteBuffer buf, int idx, FreeItem row) {
+    @Override public void store(ByteBuffer buf, int idx, FreeItem row) {
         int off = offset(idx);
 
-        buf.putInt(off, row.dispersedFreeSpace());
-        buf.putLong(off + 4, row.pageId());
+        buf.putShort(off, row.freeSpace());
+        buf.putInt(off + 2, FreeInnerIO.pageIndex(row.pageId()));
     }
 
     /** {@inheritDoc} */
-    @Override public int dispersedFreeSpace(ByteBuffer buf, int idx) {
+    @Override public short getFreeSpace(ByteBuffer buf, int idx) {
         int off = offset(idx);
 
-        return buf.getInt(off);
+        return buf.getShort(off);
     }
 
     /** {@inheritDoc} */
-    @Override public short freeSpace(ByteBuffer buf, int idx) {
+    @Override public int getPageIndex(ByteBuffer buf, int idx) {
         int off = offset(idx);
 
-        return buf.getShort(off);
+        return buf.getInt(off + 2);
     }
 
     /** {@inheritDoc} */
     @Override public FreeItem getLookupRow(BPlusTree<FreeItem, ?> tree, ByteBuffer
buf, int idx) {
         int off = offset(idx);
 
-        return new FreeItem(buf.getShort(off), buf.getShort(off + 2), buf.getLong(off + 4),
tree.getCacheId());
+        short freeSpace = buf.getShort(off);
+        int pageIdx = buf.getInt(off + 2);
+
+        long pageId = PageIdUtils.pageId(((FreeTree)tree).getPartId(), PageIdAllocator.FLAG_DATA,
pageIdx);
+
+        return new FreeItem(freeSpace, pageId, tree.getCacheId());
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/e7d7e2cf/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
index beaed49..a5efb5d 100644
--- 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
@@ -250,9 +250,9 @@ public class DataPageIO extends PageIO {
             assert indirectItemIdx >= directCnt && indirectItemIdx < directCnt
+ indirectCnt: indirectCnt;
 
             itemId = directItemIndex(getItem(buf, indirectItemIdx));
-        }
 
-        assert itemId >= 0 && itemId < directCnt: itemId; // Direct item must
be here.
+            assert itemId >= 0 && itemId < directCnt: itemId; // Direct item
must be here.
+        }
 
         return toOffset(getItem(buf, itemId));
     }
@@ -393,10 +393,17 @@ public class DataPageIO extends PageIO {
             return; // TODO May be have a separate list of free pages?
         }
 
+        // Get the entry size before the actual remove.
+        int rmvEntrySize = getEntrySize(buf, getDataOffset(buf, itemId), false);
+
         if (itemId < directCnt)
             removeDirectItem(buf, itemId, directCnt, indirectCnt);
         else
             removeIndirectItem(buf, itemId, directCnt, indirectCnt);
+
+        // Increase free space.
+        setFreeSpace(buf, getFreeSpace(buf) + rmvEntrySize +
+            ITEM_SIZE * (directCnt - getDirectCount(buf) + indirectCnt - getIndirectCount(buf)));
     }
 
     /**
@@ -482,14 +489,24 @@ public class DataPageIO extends PageIO {
     }
 
     /**
-     * @param entrySize Entry size as returned by {@link #getEntrySize(int, int)}.
-     * @param firstOff First entry data offset.
+     * @param newEntrySizeWithItem New entry size as returned by {@link #getEntrySize(int,
int)}.
+     * @param firstEntryOff First entry data offset.
      * @param directCnt Direct items count.
      * @param indirectCnt Indirect items count.
      * @return {@code true} If there is enough space for the entry.
      */
-    private static boolean enoughSpaceForEntry(int entrySize, int firstOff, int directCnt,
int indirectCnt) {
-        return ITEMS_OFF + ITEM_SIZE * (directCnt + indirectCnt) <= firstOff - entrySize;
+    public static boolean isEnoughSpace(int newEntrySizeWithItem, int firstEntryOff, int
directCnt, int indirectCnt) {
+        return ITEMS_OFF + ITEM_SIZE * (directCnt + indirectCnt) <= firstEntryOff - newEntrySizeWithItem;
+    }
+
+    /**
+     * @param buf Buffer.
+     * @param newEntrySizeWithItem New entry size as returned by {@link #getEntrySize(int,
int)}.
+     * @return {@code true} If there is enough space for the entry.
+     */
+    public boolean isEnoughSpace(ByteBuffer buf, int newEntrySizeWithItem) {
+        return isEnoughSpace(newEntrySizeWithItem,
+            getFirstEntryOffset(buf), getDirectCount(buf), getIndirectCount(buf));
     }
 
     /**
@@ -498,7 +515,7 @@ public class DataPageIO extends PageIO {
      * @param key Key.
      * @param val Value.
      * @param ver Version.
-     * @param entrySize Entry size as returned by {@link #getEntrySize(int, int)}.
+     * @param entrySizeWithItem Entry size as returned by {@link #getEntrySize(int, int)}.
      * @return Item ID.
      * @throws IgniteCheckedException If failed.
      */
@@ -508,29 +525,26 @@ public class DataPageIO extends PageIO {
         CacheObject key,
         CacheObject val,
         GridCacheVersion ver,
-        int entrySize
+        int entrySizeWithItem
     ) throws IgniteCheckedException {
-        if (entrySize > buf.capacity() - ITEMS_OFF) // TODO span multiple data pages with
a single large entry
+        if (entrySizeWithItem > buf.capacity() - ITEMS_OFF) // TODO span multiple data
pages with a single large entry
             throw new IgniteException("Too big entry: " + key + " " + val);
 
         int directCnt = getDirectCount(buf);
         int indirectCnt = getIndirectCount(buf);
-
         int dataOff = getFirstEntryOffset(buf);
 
-        // Compact if we do not have enough space.
-        if (!enoughSpaceForEntry(entrySize, dataOff, directCnt, indirectCnt)) {
+        // Compact if we do not have enough space for entry.
+        if (!isEnoughSpace(entrySizeWithItem, dataOff, directCnt, indirectCnt)) {
             dataOff = compactDataEntries(buf, directCnt);
 
-//            assert enoughSpaceForEntry(entrySize, dataOff, directCnt, indirectCnt);
-            if (!enoughSpaceForEntry(entrySize, dataOff, directCnt, indirectCnt))
-                return -1; // TODO replace with assert
+            assert isEnoughSpace(entrySizeWithItem, dataOff, directCnt, indirectCnt);
         }
 
-        // Attempt to write data right before the first entry.
-        dataOff -= entrySize - ITEM_SIZE;
+        // Write data right before the first entry.
+        dataOff -= entrySizeWithItem - ITEM_SIZE;
 
-        writeRowData(coctx, buf, dataOff, entrySize, key, val, ver);
+        writeRowData(coctx, buf, dataOff, entrySizeWithItem, key, val, ver);
 
         setFirstEntryOffset(buf, dataOff);
 
@@ -538,6 +552,11 @@ public class DataPageIO extends PageIO {
 
         assert check(itemId): itemId;
 
+        // Update free space. If number of direct items did not change, then we were able
to reuse item slot.
+        setFreeSpace(buf, getFreeSpace(buf) - entrySizeWithItem + (getDirectCount(buf) ==
directCnt ? ITEM_SIZE : 0));
+
+        assert getFreeSpace(buf) >= 0;
+
         return (byte)itemId;
     }
 
@@ -653,7 +672,7 @@ public class DataPageIO extends PageIO {
      * @param val Value.
      * @param ver Version.
      */
-    public void writeRowData(
+    private void writeRowData(
         CacheObjectContext coctx,
         ByteBuffer buf,
         int dataOff,

http://git-wip-us.apache.org/repos/asf/ignite/blob/e7d7e2cf/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
index 3d1b4e4..4e1ff0d 100644
--- 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
@@ -85,7 +85,7 @@ public abstract class PageHandler<X> {
     public static <X> int writePage(Page page, PageHandler<X> h, X arg, int intArg,
int dfltRes)
         throws IgniteCheckedException {
         if (page == null)
-            return dfltRes;
+            return dfltRes; // TODO drop dfltRes parameter and assert not null
 
         int res;
 
@@ -94,7 +94,7 @@ public abstract class PageHandler<X> {
         ByteBuffer buf = page.getForWrite();
 
         if (buf == null)
-            return dfltRes;
+            return dfltRes; // TODO ---//---
 
         try {
             res = h.run(page, buf, arg, intArg);


Mime
View raw message