You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by sb...@apache.org on 2016/04/28 10:52:39 UTC
[09/50] ignite git commit: ignite-db - free
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 <sv...@gridgain.com>
Authored: Fri Apr 22 01:37:11 2016 +0300
Committer: S.Vladykin <sv...@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);