ignite-db-x Made H2RowStore abstract to be reused from core module.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/2f7a22c1 Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/2f7a22c1 Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/2f7a22c1 Branch: refs/heads/ignite-db-x-10884 Commit: 2f7a22c11abc6c2bcba34ef9c902c9f0c607c85c Parents: 4282d80 Author: sboikov <[email protected]> Authored: Tue Apr 19 12:03:13 2016 +0300 Committer: sboikov <[email protected]> Committed: Tue Apr 19 12:03:13 2016 +0300 ---------------------------------------------------------------------- .../processors/cache/database/CacheDataRow.java | 38 +++ .../processors/cache/database/RowStore.java | 273 +++++++++++++++++++ .../cache/database/freelist/FreeItem.java | 90 ++++++ .../cache/database/freelist/FreeList.java | 196 +++++++++++++ .../cache/database/freelist/FreeTree.java | 96 +++++++ .../cache/database/freelist/io/FreeIO.java | 39 +++ .../cache/database/freelist/io/FreeInnerIO.java | 67 +++++ .../cache/database/freelist/io/FreeLeafIO.java | 70 +++++ .../query/h2/database/H2RowStore.java | 234 ++-------------- .../query/h2/database/freelist/FreeItem.java | 90 ------ .../query/h2/database/freelist/FreeList.java | 196 ------------- .../query/h2/database/freelist/FreeTree.java | 96 ------- .../query/h2/database/freelist/io/FreeIO.java | 39 --- .../h2/database/freelist/io/FreeInnerIO.java | 67 ----- .../h2/database/freelist/io/FreeLeafIO.java | 70 ----- .../processors/query/h2/opt/GridH2Row.java | 33 ++- 16 files changed, 928 insertions(+), 766 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/2f7a22c1/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/CacheDataRow.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/CacheDataRow.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/CacheDataRow.java new file mode 100644 index 0000000..a4cbd32 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/CacheDataRow.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.cache.database; + +import org.apache.ignite.internal.processors.cache.CacheObject; +import org.apache.ignite.internal.processors.cache.version.GridCacheVersion; + +/** + * + */ +public interface CacheDataRow { + public CacheObject key(); + + public CacheObject value(); + + public GridCacheVersion version(); + + public int partition(); + + public long link(); + + public void link(long link); +} http://git-wip-us.apache.org/repos/asf/ignite/blob/2f7a22c1/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 new file mode 100644 index 0000000..50bf490 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/RowStore.java @@ -0,0 +1,273 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.cache.database; + +import java.nio.ByteBuffer; +import org.apache.ignite.IgniteCheckedException; +import org.apache.ignite.IgniteException; +import org.apache.ignite.internal.pagemem.FullPageId; +import org.apache.ignite.internal.pagemem.Page; +import org.apache.ignite.internal.pagemem.PageIdAllocator; +import org.apache.ignite.internal.pagemem.PageMemory; +import org.apache.ignite.internal.processors.cache.CacheObject; +import org.apache.ignite.internal.processors.cache.CacheObjectContext; +import org.apache.ignite.internal.processors.cache.GridCacheContext; +import org.apache.ignite.internal.processors.cache.database.freelist.FreeList; +import org.apache.ignite.internal.processors.cache.database.tree.io.DataPageIO; +import org.apache.ignite.internal.processors.cache.database.tree.util.PageHandler; +import org.apache.ignite.internal.processors.cache.version.GridCacheVersion; + +import static org.apache.ignite.internal.pagemem.PageIdUtils.dwordsOffset; +import static org.apache.ignite.internal.pagemem.PageIdUtils.linkFromDwordOffset; +import static org.apache.ignite.internal.pagemem.PageIdUtils.pageId; +import static org.apache.ignite.internal.processors.cache.database.tree.util.PageHandler.writePage; + +/** + * Data store for H2 rows. + */ +public class RowStore<T extends CacheDataRow> { + /** */ + private final FreeList freeList; + + /** */ + private final PageMemory pageMem; + + /** */ + private final GridCacheContext<?,?> cctx; + + /** */ + private final CacheObjectContext coctx; + + /** */ + private volatile long lastDataPageId; + + /** */ + private final RowFactory<T> rowFactory; + + /** */ + 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); + + int idx = io.addRow(coctx, buf, row.key(), row.value(), row.version(), entrySize); + + if (idx != -1) { + row.link(linkFromDwordOffset(page.id(), idx)); + + assert row.link() != 0; + } + + return idx; + } + }; + + /** */ + 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); + + assert DataPageIO.check(itemId): itemId; + + io.removeRow(buf, (byte)itemId); + + return 0; + } + }; + + /** + * @param cctx Cache context. + */ + public RowStore(GridCacheContext<?,?> cctx, RowFactory<T> rowFactory, FreeList freeList) { + assert rowFactory != null; + assert cctx != null; + + this.cctx = cctx; + this.freeList = freeList; + this.rowFactory = rowFactory; + + coctx = cctx.cacheObjectContext(); + pageMem = cctx.shared().database().pageMemory(); + } + + /** + * @param pageId Page ID. + * @return Page. + * @throws IgniteCheckedException If failed. + */ + private Page page(long pageId) throws IgniteCheckedException { + return pageMem.page(new FullPageId(pageId, cctx.cacheId())); + } + + /** + * @param part Partition. + * @return Allocated page. + * @throws IgniteCheckedException if failed. + */ + private Page allocatePage(int part) throws IgniteCheckedException { + FullPageId fullPageId = pageMem.allocatePage(cctx.cacheId(), part, PageIdAllocator.FLAG_DATA); + + return pageMem.page(fullPageId); + } + + /** + * @param link Row link. + * @throws IgniteCheckedException If failed. + */ + public void removeRow(long link) throws IgniteCheckedException { + assert link != 0; + + try (Page page = page(pageId(link))) { + writePage(page, rmvRow, null, dwordsOffset(link), 0); + } + } + + /** + * !!! This method must be invoked in read or write lock of referring index page. It is needed to + * !!! make sure that row at this link will be invisible, when the link will be removed from + * !!! from all the index pages, so that row can be safely erased from the data page. + * + * @param link Link. + * @return Row. + * @throws IgniteCheckedException If failed. + */ + public T getRow(long link) throws IgniteCheckedException { + try (Page page = page(pageId(link))) { + ByteBuffer buf = page.getForRead(); + + try { + T existing = rowFactory.cachedRow(link); + + if (existing != null) + return existing; + + DataPageIO io = DataPageIO.VERSIONS.forPage(buf); + + int dataOff = io.getDataOffset(buf, dwordsOffset(link)); + + buf.position(dataOff); + + // Skip entry size. + buf.getShort(); + + CacheObject key = coctx.processor().toCacheObject(coctx, buf); + CacheObject val = coctx.processor().toCacheObject(coctx, buf); + + int topVer = buf.getInt(); + int nodeOrderDrId = buf.getInt(); + long globalTime = buf.getLong(); + long order = buf.getLong(); + + GridCacheVersion ver = new GridCacheVersion(topVer, nodeOrderDrId, globalTime, order); + + T row; + + try { + row = rowFactory.createRow(key, val, ver, link, 0); + } + catch (IgniteCheckedException e) { + throw new IgniteException(e); + } + + assert row.version() != null : row; + + return row; + } + finally { + page.releaseRead(); + } + } + } + + /** + * @param expLastDataPageId Expected last data page ID. + * @return Next data page ID. + */ + private synchronized long nextDataPage(long expLastDataPageId, int partId) throws IgniteCheckedException { + if (expLastDataPageId != lastDataPageId) + return lastDataPageId; + + long pageId; + + try (Page page = allocatePage(partId)) { + pageId = page.id(); + + ByteBuffer buf = page.getForInitialWrite(); + + DataPageIO.VERSIONS.latest().initNewPage(buf, page.id()); + } + + return lastDataPageId = pageId; + } + + /** + * @param row Row. + */ + public void addRow(CacheDataRow row) throws IgniteCheckedException { + if (freeList == null) + writeRowData0(row); + else + freeList.writeRowData(row); + } + + /** + * @param row Row. + * @throws IgniteCheckedException If failed. + */ + private void writeRowData0(CacheDataRow row) throws IgniteCheckedException { + assert row.link() == 0; + + while (row.link() == 0) { + long pageId = lastDataPageId; + + if (pageId == 0) + pageId = nextDataPage(0, row.partition()); + + try (Page page = page(pageId)) { + if (writePage(page, writeRow, row, -1, -1) >= 0) + return; // Successful write. + } + + nextDataPage(pageId, row.partition()); + } + } + + /** + * + */ + protected interface RowFactory<T> { + /** + * @param link Link. + * @return Row. + */ + T cachedRow(long link); + + /** + * @param key Key. + * @param val Value. + * @param ver Version. + * @param link Link. + * @param expirationTime Expiration time. + * @return Row. + * @throws IgniteCheckedException If failed. + */ + T createRow(CacheObject key, CacheObject val, GridCacheVersion ver, long link, long expirationTime) + throws IgniteCheckedException; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/2f7a22c1/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 new file mode 100644 index 0000000..7de30c7 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/FreeItem.java @@ -0,0 +1,90 @@ +/* + * 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.freelist; + +import org.apache.ignite.internal.pagemem.FullPageId; + +/** + * Free list item. + */ +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) { + 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; + } + + /** + * @return Dispersed free space. + */ + public int dispersedFreeSpace() { + return disperse(freeSpace, dispersion); + } + + /** + * @return Free space in the page. + */ + 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/2f7a22c1/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 new file mode 100644 index 0000000..0f94bb1 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/FreeList.java @@ -0,0 +1,196 @@ +/* + * 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.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.PageMemory; +import org.apache.ignite.internal.processors.cache.GridCacheContext; +import org.apache.ignite.internal.processors.cache.database.CacheDataRow; +import org.apache.ignite.internal.processors.cache.database.tree.io.DataPageIO; +import org.apache.ignite.internal.processors.cache.database.tree.util.PageHandler; +import org.apache.ignite.internal.util.future.GridFutureAdapter; +import org.apache.ignite.lang.IgniteBiTuple; +import org.jsr166.ConcurrentHashMap8; + +import static org.apache.ignite.internal.processors.cache.database.tree.util.PageHandler.writePage; + +/** + * Free data page list. + */ +public class FreeList { + /** */ + private final GridCacheContext<?,?> cctx; + + /** */ + private final PageMemory pageMem; + + /** */ + private final ConcurrentHashMap8<Integer,GridFutureAdapter<FreeTree>> trees = new ConcurrentHashMap8<>(); + + /** */ + private final PageHandler<CacheDataRow> writeRow = new PageHandler<CacheDataRow>() { + @Override public int run(Page page, ByteBuffer buf, CacheDataRow row, int entrySize) + throws IgniteCheckedException { + DataPageIO io = DataPageIO.VERSIONS.forPage(buf); + + int idx = io.addRow(cctx.cacheObjectContext(), buf, row.key(), row.value(), row.version(), entrySize); + + assert idx >= 0; + + return io.getFreeSpace(buf); + } + }; + + /** + * @param cctx Cache context. + */ + public FreeList(GridCacheContext<?,?> cctx) { + assert cctx != null; + + this.cctx = cctx; + + pageMem = cctx.shared().database().pageMemory(); + + assert pageMem != null; + } + + /** + * @param tree Tree. + * @param neededSpace Needed free space. + * @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)); + + assert res == null || (res.pageId() != 0 && res.cacheId() == cctx.cacheId()): res; + + return res; + } + + /** + * @return Random dispersion value. + */ + private static short dispersion() { + return (short)ThreadLocalRandom.current().nextInt(Short.MIN_VALUE, Short.MAX_VALUE); + } + + /** + * @param part Partition. + * @return Tree. + * @throws IgniteCheckedException If failed. + */ + private FreeTree tree(Integer part) throws IgniteCheckedException { + assert part >= 0 && part < Short.MAX_VALUE: part; + + GridFutureAdapter<FreeTree> fut = trees.get(part); + + if (fut == null) { + fut = new GridFutureAdapter<>(); + + if (trees.putIfAbsent(part, fut) != null) + fut = trees.get(part); + else { + // Index name will be the same across restarts. + String idxName = part + "$$" + cctx.cacheId() + "_free"; + + IgniteBiTuple<FullPageId,Boolean> t = cctx.shared().database().meta() + .getOrAllocateForIndex(cctx.cacheId(), idxName); + + fut.onDone(new FreeTree(cctx.cacheId(), pageMem, t.get1(), t.get2())); + } + } + + return fut.get(); + } + + /** + * @param row Row. + * @throws IgniteCheckedException If failed. + */ + public void writeRowData(CacheDataRow row) throws IgniteCheckedException { + // assert row.link == 0; + + 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; + + try { + 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; + } + } + } + } + + /** + * @param part Partition. + * @return Page. + * @throws IgniteCheckedException If failed. + */ + private Page allocatePage(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/2f7a22c1/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 new file mode 100644 index 0000000..31f9a1d --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/FreeTree.java @@ -0,0 +1,96 @@ +/* + * 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.freelist; + +import java.nio.ByteBuffer; +import org.apache.ignite.IgniteCheckedException; +import org.apache.ignite.internal.pagemem.FullPageId; +import org.apache.ignite.internal.pagemem.PageMemory; +import org.apache.ignite.internal.processors.cache.database.tree.BPlusTree; +import org.apache.ignite.internal.processors.cache.database.tree.io.BPlusIO; +import org.apache.ignite.internal.processors.cache.database.tree.io.BPlusInnerIO; +import org.apache.ignite.internal.processors.cache.database.tree.io.BPlusLeafIO; +import org.apache.ignite.internal.processors.cache.database.tree.io.PageIO; +import org.apache.ignite.internal.processors.cache.database.freelist.io.FreeIO; +import org.apache.ignite.internal.processors.cache.database.freelist.io.FreeInnerIO; +import org.apache.ignite.internal.processors.cache.database.freelist.io.FreeLeafIO; + +/** + * Data structure for data pages and their free spaces. + */ +public class FreeTree extends BPlusTree<FreeItem, FreeItem> { + /** + * @param cacheId Cache ID. + * @param pageMem Page memory. + * @param metaPageId Meta page ID. + * @param initNew Initialize new index. + * @throws IgniteCheckedException If failed. + */ + public FreeTree(int cacheId, PageMemory pageMem, FullPageId metaPageId, boolean initNew) + throws IgniteCheckedException { + super(cacheId, pageMem, metaPageId); + + assert pageMem != null; + + if (initNew) + initNew(); + } + + /** {@inheritDoc} */ + @Override protected BPlusIO<FreeItem> io(int type, int ver) { + if (type == PageIO.T_FREE_INNER) + return FreeInnerIO.VERSIONS.forVersion(ver); + + assert type == PageIO.T_FREE_LEAF: type; + + return FreeLeafIO.VERSIONS.forVersion(ver); + } + + /** {@inheritDoc} */ + @Override protected BPlusInnerIO<FreeItem> latestInnerIO() { + return FreeInnerIO.VERSIONS.latest(); + } + + /** {@inheritDoc} */ + @Override protected BPlusLeafIO<FreeItem> latestLeafIO() { + return FreeLeafIO.VERSIONS.latest(); + } + + /** {@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()); + + // 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()); + } + + /** {@inheritDoc} */ + @Override protected FreeItem getRow(BPlusIO<FreeItem> io, ByteBuffer buf, int idx) throws IgniteCheckedException { + assert io.isLeaf(); + + FreeItem row = io.getLookupRow(this, buf, idx); + + assert row.pageId() != 0; + assert row.cacheId() == cacheId; + + return row; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/2f7a22c1/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 new file mode 100644 index 0000000..de28b22 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/io/FreeIO.java @@ -0,0 +1,39 @@ +/* + * 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.freelist.io; + +import java.nio.ByteBuffer; + +/** + * Common routines for free list pages. + */ +public interface FreeIO { + /** + * @param buf Buffer. + * @param idx Index. + * @return Dispersed free space. + */ + public int dispersedFreeSpace(ByteBuffer buf, int idx); + + /** + * @param buf Buffer. + * @param idx Index. + * @return Free space. + */ + public short freeSpace(ByteBuffer buf, int idx); +} http://git-wip-us.apache.org/repos/asf/ignite/blob/2f7a22c1/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 new file mode 100644 index 0000000..bfaaaa2 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/io/FreeInnerIO.java @@ -0,0 +1,67 @@ +package org.apache.ignite.internal.processors.cache.database.freelist.io; + +import java.nio.ByteBuffer; +import org.apache.ignite.internal.processors.cache.database.freelist.FreeItem; +import org.apache.ignite.internal.processors.cache.database.tree.BPlusTree; +import org.apache.ignite.internal.processors.cache.database.tree.io.BPlusIO; +import org.apache.ignite.internal.processors.cache.database.tree.io.BPlusInnerIO; +import org.apache.ignite.internal.processors.cache.database.tree.io.IOVersions; + +/** + * Routines for free list inner pages. + */ +public class FreeInnerIO extends BPlusInnerIO<FreeItem> implements FreeIO { + /** */ + public static final IOVersions<FreeInnerIO> VERSIONS = new IOVersions<>( + new FreeInnerIO(1) + ); + + /** + * @param ver Page format version. + */ + protected FreeInnerIO(int ver) { + super(T_FREE_INNER, ver, false, 4); // freeSpace(2) + dispersion(2) + } + + /** {@inheritDoc} */ + @Override public void store(ByteBuffer buf, int idx, FreeItem row) { + store(buf, idx, row.dispersedFreeSpace()); + } + + /** {@inheritDoc} */ + @Override public void store(ByteBuffer dst, int dstIdx, BPlusIO<FreeItem> srcIo, ByteBuffer src, int srcIdx) { + store(dst, dstIdx, ((FreeIO)srcIo).dispersedFreeSpace(src, srcIdx)); + } + + /** + * @param buf Buffer. + * @param idx Index. + * @param dispersedFreeSpace Dispersed free space. + */ + private void store(ByteBuffer buf, int idx, int dispersedFreeSpace) { + int off = offset(idx, SHIFT_LINK); + + buf.putInt(off, dispersedFreeSpace); + } + + /** {@inheritDoc} */ + @Override public int dispersedFreeSpace(ByteBuffer buf, int idx) { + int off = offset(idx, SHIFT_LINK); + + return buf.getInt(off); + } + + /** {@inheritDoc} */ + @Override public short freeSpace(ByteBuffer buf, int idx) { + int off = offset(idx, SHIFT_LINK); + + return buf.getShort(off); + } + + /** {@inheritDoc} */ + @Override public FreeItem getLookupRow(BPlusTree<FreeItem, ?> tree, ByteBuffer buf, int idx) { + int off = offset(idx, SHIFT_LINK); + + return new FreeItem(buf.getShort(off), buf.getShort(off + 2), 0, 0); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/2f7a22c1/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 new file mode 100644 index 0000000..5496897 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/io/FreeLeafIO.java @@ -0,0 +1,70 @@ +/* + * 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.freelist.io; + +import java.nio.ByteBuffer; +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. + */ +public class FreeLeafIO extends BPlusLeafIO<FreeItem> implements FreeIO { + /** */ + public static final IOVersions<FreeLeafIO> VERSIONS = new IOVersions<>( + new FreeLeafIO(1) + ); + + /** + * @param ver Page format version. + */ + protected FreeLeafIO(int ver) { + super(T_FREE_LEAF, ver, 12); // freeSpace(2) + dispersion(2) + pageId(8) + } + + /** {@inheritDoc} */ + @Override public final void store(ByteBuffer buf, int idx, FreeItem row) { + int off = offset(idx); + + buf.putInt(off, row.dispersedFreeSpace()); + buf.putLong(off + 4, row.pageId()); + } + + /** {@inheritDoc} */ + @Override public int dispersedFreeSpace(ByteBuffer buf, int idx) { + int off = offset(idx); + + return buf.getInt(off); + } + + /** {@inheritDoc} */ + @Override public short freeSpace(ByteBuffer buf, int idx) { + int off = offset(idx); + + return buf.getShort(off); + } + + /** {@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()); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/2f7a22c1/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2RowStore.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2RowStore.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2RowStore.java index f545c24..2495237 100644 --- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2RowStore.java +++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2RowStore.java @@ -17,242 +17,62 @@ package org.apache.ignite.internal.processors.query.h2.database; -import java.nio.ByteBuffer; import org.apache.ignite.IgniteCheckedException; -import org.apache.ignite.IgniteException; -import org.apache.ignite.internal.pagemem.FullPageId; -import org.apache.ignite.internal.pagemem.Page; -import org.apache.ignite.internal.pagemem.PageIdAllocator; import org.apache.ignite.internal.pagemem.PageIdUtils; -import org.apache.ignite.internal.pagemem.PageMemory; import org.apache.ignite.internal.processors.cache.CacheObject; -import org.apache.ignite.internal.processors.cache.CacheObjectContext; import org.apache.ignite.internal.processors.cache.GridCacheContext; -import org.apache.ignite.internal.processors.query.h2.database.freelist.FreeList; -import org.apache.ignite.internal.processors.cache.database.tree.io.DataPageIO; -import org.apache.ignite.internal.processors.cache.database.tree.util.PageHandler; +import org.apache.ignite.internal.processors.cache.database.RowStore; import org.apache.ignite.internal.processors.cache.version.GridCacheVersion; +import org.apache.ignite.internal.processors.cache.database.freelist.FreeList; import org.apache.ignite.internal.processors.query.h2.opt.GridH2Row; import org.apache.ignite.internal.processors.query.h2.opt.GridH2RowDescriptor; -import static org.apache.ignite.internal.pagemem.PageIdUtils.dwordsOffset; -import static org.apache.ignite.internal.pagemem.PageIdUtils.linkFromDwordOffset; -import static org.apache.ignite.internal.pagemem.PageIdUtils.pageId; -import static org.apache.ignite.internal.processors.cache.database.tree.util.PageHandler.writePage; - /** * Data store for H2 rows. */ -public class H2RowStore { - /** */ - private final FreeList freeList; - - /** */ - private final PageMemory pageMem; - - /** */ - private final GridH2RowDescriptor rowDesc; - - /** */ - private final GridCacheContext<?,?> cctx; - - /** */ - private final CacheObjectContext coctx; - - /** */ - private volatile long lastDataPageId; - - /** */ - private final PageHandler<GridH2Row> writeRow = new PageHandler<GridH2Row>() { - @Override public int run(Page page, ByteBuffer buf, GridH2Row row, int ignore) throws IgniteCheckedException { - int entrySize = DataPageIO.getEntrySize(coctx, row.key, row.val); - - DataPageIO io = DataPageIO.VERSIONS.forPage(buf); - - int idx = io.addRow(coctx, buf, row.key, row.val, row.ver, entrySize); - - if (idx != -1) { - row.link = linkFromDwordOffset(page.id(), idx); - - assert row.link != 0; - } - - return idx; - } - }; - - /** */ - private final PageHandler<Void> removeRow = new PageHandler<Void>() { - @Override public int run(Page page, ByteBuffer buf, Void ignore, int itemId) throws IgniteCheckedException { - DataPageIO io = DataPageIO.VERSIONS.forPage(buf); - - assert DataPageIO.check(itemId): itemId; - - io.removeRow(buf, (byte)itemId); - - return 0; - } - }; - +public class H2RowStore extends RowStore<GridH2Row> { /** * @param rowDesc Row descriptor. * @param cctx Cache context. + * @param freeList Free list. */ public H2RowStore(GridH2RowDescriptor rowDesc, GridCacheContext<?,?> cctx, FreeList freeList) { - assert rowDesc != null; - assert cctx != null; - - this.rowDesc = rowDesc; - this.cctx = cctx; - this.freeList = freeList; - - coctx = cctx.cacheObjectContext(); - pageMem = cctx.shared().database().pageMemory(); - } - - /** - * @param pageId Page ID. - * @return Page. - * @throws IgniteCheckedException If failed. - */ - private Page page(long pageId) throws IgniteCheckedException { - return pageMem.page(new FullPageId(pageId, cctx.cacheId())); - } - - /** - * @param part Partition. - * @return Allocated page. - * @throws IgniteCheckedException if failed. - */ - private Page allocatePage(int part) throws IgniteCheckedException { - FullPageId fullPageId = pageMem.allocatePage(cctx.cacheId(), part, PageIdAllocator.FLAG_DATA); - - return pageMem.page(fullPageId); - } - - /** - * @param link Row link. - * @throws IgniteCheckedException If failed. - */ - public void removeRow(long link) throws IgniteCheckedException { - assert link != 0; - - try (Page page = page(pageId(link))) { - writePage(page, removeRow, null, dwordsOffset(link), 0); - } + super(cctx, new H2RowFactory(rowDesc), freeList); } - /** - * !!! This method must be invoked in read or write lock of referring index page. It is needed to - * !!! make sure that row at this link will be invisible, when the link will be removed from - * !!! from all the index pages, so that row can be safely erased from the data page. * - * @param link Link. - * @return Row. - * @throws IgniteCheckedException If failed. */ - public GridH2Row getRow(long link) throws IgniteCheckedException { - try (Page page = page(pageId(link))) { - ByteBuffer buf = page.getForRead(); - - try { - GridH2Row existing = rowDesc.cachedRow(link); - - if (existing != null) - return existing; - - DataPageIO io = DataPageIO.VERSIONS.forPage(buf); - - int dataOff = io.getDataOffset(buf, dwordsOffset(link)); - - buf.position(dataOff); - - // Skip entry size. - buf.getShort(); - - CacheObject key = coctx.processor().toCacheObject(coctx, buf); - CacheObject val = coctx.processor().toCacheObject(coctx, buf); - - int topVer = buf.getInt(); - int nodeOrderDrId = buf.getInt(); - long globalTime = buf.getLong(); - long order = buf.getLong(); - - GridCacheVersion ver = new GridCacheVersion(topVer, nodeOrderDrId, globalTime, order); - - GridH2Row row; - - try { - row = rowDesc.createRow(key, PageIdUtils.partId(link), val, ver, 0); - - row.link = link; - } - catch (IgniteCheckedException e) { - throw new IgniteException(e); - } - - assert row.ver != null; + static class H2RowFactory implements RowFactory<GridH2Row> { + /** */ + private final GridH2RowDescriptor rowDesc; - rowDesc.cache(row); + /** + * @param rowDesc Row descriptor. + */ + public H2RowFactory(GridH2RowDescriptor rowDesc) { + assert rowDesc != null; - return row; - } - finally { - page.releaseRead(); - } + this.rowDesc = rowDesc; } - } - - /** - * @param expLastDataPageId Expected last data page ID. - * @return Next data page ID. - */ - private synchronized long nextDataPage(long expLastDataPageId, int partId) throws IgniteCheckedException { - if (expLastDataPageId != lastDataPageId) - return lastDataPageId; - long pageId; - - try (Page page = allocatePage(partId)) { - pageId = page.id(); - - ByteBuffer buf = page.getForInitialWrite(); - - DataPageIO.VERSIONS.latest().initNewPage(buf, page.id()); + /** {@inheritDoc} */ + @Override public GridH2Row cachedRow(long link) { + return rowDesc.cachedRow(link); } - return lastDataPageId = pageId; - } - - /** - * @param row Row. - */ - public void addRow(GridH2Row row) throws IgniteCheckedException { - if (freeList == null) - writeRowData0(row); - else - freeList.writeRowData(row); - } - - /** - * @param row Row. - * @throws IgniteCheckedException If failed. - */ - private void writeRowData0(GridH2Row row) throws IgniteCheckedException { - assert row.link == 0; - - while (row.link == 0) { - long pageId = lastDataPageId; + /** {@inheritDoc} */ + @Override public GridH2Row createRow(CacheObject key, + CacheObject val, + GridCacheVersion ver, + long link, + long expirationTime) throws IgniteCheckedException { + GridH2Row row = rowDesc.createRow(key, PageIdUtils.partId(link), val, ver, 0); - if (pageId == 0) - pageId = nextDataPage(0, row.partId); + row.link = link; - try (Page page = page(pageId)) { - if (writePage(page, writeRow, row, -1, -1) >= 0) - return; // Successful write. - } + rowDesc.cache(row); - nextDataPage(pageId, row.partId); + return row; } } } http://git-wip-us.apache.org/repos/asf/ignite/blob/2f7a22c1/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/freelist/FreeItem.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/freelist/FreeItem.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/freelist/FreeItem.java deleted file mode 100644 index 71bb32e..0000000 --- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/freelist/FreeItem.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * 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.query.h2.database.freelist; - -import org.apache.ignite.internal.pagemem.FullPageId; - -/** - * Free list item. - */ -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) { - 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; - } - - /** - * @return Dispersed free space. - */ - public int dispersedFreeSpace() { - return disperse(freeSpace, dispersion); - } - - /** - * @return Free space in the page. - */ - 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/2f7a22c1/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/freelist/FreeList.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/freelist/FreeList.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/freelist/FreeList.java deleted file mode 100644 index 43b0dcc..0000000 --- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/freelist/FreeList.java +++ /dev/null @@ -1,196 +0,0 @@ -/* - * 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.query.h2.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.PageMemory; -import org.apache.ignite.internal.processors.cache.GridCacheContext; -import org.apache.ignite.internal.processors.cache.database.tree.io.DataPageIO; -import org.apache.ignite.internal.processors.cache.database.tree.util.PageHandler; -import org.apache.ignite.internal.processors.query.h2.opt.GridH2Row; -import org.apache.ignite.internal.util.future.GridFutureAdapter; -import org.apache.ignite.lang.IgniteBiTuple; -import org.jsr166.ConcurrentHashMap8; - -import static org.apache.ignite.internal.processors.cache.database.tree.util.PageHandler.writePage; - -/** - * Free data page list. - */ -public class FreeList { - /** */ - private final GridCacheContext<?,?> cctx; - - /** */ - private final PageMemory pageMem; - - /** */ - private final ConcurrentHashMap8<Integer,GridFutureAdapter<FreeTree>> trees = new ConcurrentHashMap8<>(); - - /** */ - private final PageHandler<GridH2Row> writeRow = new PageHandler<GridH2Row>() { - @Override public int run(Page page, ByteBuffer buf, GridH2Row row, int entrySize) - throws IgniteCheckedException { - DataPageIO io = DataPageIO.VERSIONS.forPage(buf); - - int idx = io.addRow(cctx.cacheObjectContext(), buf, row.key, row.val, row.ver, entrySize); - - assert idx >= 0; - - return io.getFreeSpace(buf); - } - }; - - /** - * @param cctx Cache context. - */ - public FreeList(GridCacheContext<?,?> cctx) { - assert cctx != null; - - this.cctx = cctx; - - pageMem = cctx.shared().database().pageMemory(); - - assert pageMem != null; - } - - /** - * @param tree Tree. - * @param neededSpace Needed free space. - * @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)); - - assert res == null || (res.pageId() != 0 && res.cacheId() == cctx.cacheId()): res; - - return res; - } - - /** - * @return Random dispersion value. - */ - private static short dispersion() { - return (short)ThreadLocalRandom.current().nextInt(Short.MIN_VALUE, Short.MAX_VALUE); - } - - /** - * @param part Partition. - * @return Tree. - * @throws IgniteCheckedException If failed. - */ - private FreeTree tree(Integer part) throws IgniteCheckedException { - assert part >= 0 && part < Short.MAX_VALUE: part; - - GridFutureAdapter<FreeTree> fut = trees.get(part); - - if (fut == null) { - fut = new GridFutureAdapter<>(); - - if (trees.putIfAbsent(part, fut) != null) - fut = trees.get(part); - else { - // Index name will be the same across restarts. - String idxName = part + "$$" + cctx.cacheId() + "_free"; - - IgniteBiTuple<FullPageId,Boolean> t = cctx.shared().database().meta() - .getOrAllocateForIndex(cctx.cacheId(), idxName); - - fut.onDone(new FreeTree(cctx.cacheId(), pageMem, t.get1(), t.get2())); - } - } - - return fut.get(); - } - - /** - * @param row Row. - * @throws IgniteCheckedException If failed. - */ - public void writeRowData(GridH2Row row) throws IgniteCheckedException { - assert row.link == 0; - - int entrySize = DataPageIO.getEntrySize(cctx.cacheObjectContext(), row.key, row.val); - - assert entrySize > 0 && entrySize < Short.MAX_VALUE: entrySize; - - FreeTree tree = tree(row.partId); - FreeItem item = take(tree, (short)entrySize); - - Page page = null; - int freeSpace = -1; - - try { - if (item == null) { - DataPageIO io = DataPageIO.VERSIONS.latest(); - - page = allocatePage(row.partId); - - 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; - } - } - } - } - - /** - * @param part Partition. - * @return Page. - * @throws IgniteCheckedException If failed. - */ - private Page allocatePage(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/2f7a22c1/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/freelist/FreeTree.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/freelist/FreeTree.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/freelist/FreeTree.java deleted file mode 100644 index 6d61bd7..0000000 --- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/freelist/FreeTree.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * 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.query.h2.database.freelist; - -import java.nio.ByteBuffer; -import org.apache.ignite.IgniteCheckedException; -import org.apache.ignite.internal.pagemem.FullPageId; -import org.apache.ignite.internal.pagemem.PageMemory; -import org.apache.ignite.internal.processors.cache.database.tree.BPlusTree; -import org.apache.ignite.internal.processors.cache.database.tree.io.BPlusIO; -import org.apache.ignite.internal.processors.cache.database.tree.io.BPlusInnerIO; -import org.apache.ignite.internal.processors.cache.database.tree.io.BPlusLeafIO; -import org.apache.ignite.internal.processors.cache.database.tree.io.PageIO; -import org.apache.ignite.internal.processors.query.h2.database.freelist.io.FreeIO; -import org.apache.ignite.internal.processors.query.h2.database.freelist.io.FreeInnerIO; -import org.apache.ignite.internal.processors.query.h2.database.freelist.io.FreeLeafIO; - -/** - * Data structure for data pages and their free spaces. - */ -public class FreeTree extends BPlusTree<FreeItem, FreeItem> { - /** - * @param cacheId Cache ID. - * @param pageMem Page memory. - * @param metaPageId Meta page ID. - * @param initNew Initialize new index. - * @throws IgniteCheckedException If failed. - */ - public FreeTree(int cacheId, PageMemory pageMem, FullPageId metaPageId, boolean initNew) - throws IgniteCheckedException { - super(cacheId, pageMem, metaPageId); - - assert pageMem != null; - - if (initNew) - initNew(); - } - - /** {@inheritDoc} */ - @Override protected BPlusIO<FreeItem> io(int type, int ver) { - if (type == PageIO.T_FREE_INNER) - return FreeInnerIO.VERSIONS.forVersion(ver); - - assert type == PageIO.T_FREE_LEAF: type; - - return FreeLeafIO.VERSIONS.forVersion(ver); - } - - /** {@inheritDoc} */ - @Override protected BPlusInnerIO<FreeItem> latestInnerIO() { - return FreeInnerIO.VERSIONS.latest(); - } - - /** {@inheritDoc} */ - @Override protected BPlusLeafIO<FreeItem> latestLeafIO() { - return FreeLeafIO.VERSIONS.latest(); - } - - /** {@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()); - - // 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()); - } - - /** {@inheritDoc} */ - @Override protected FreeItem getRow(BPlusIO<FreeItem> io, ByteBuffer buf, int idx) throws IgniteCheckedException { - assert io.isLeaf(); - - FreeItem row = io.getLookupRow(this, buf, idx); - - assert row.pageId() != 0; - assert row.cacheId() == cacheId; - - return row; - } -} http://git-wip-us.apache.org/repos/asf/ignite/blob/2f7a22c1/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/freelist/io/FreeIO.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/freelist/io/FreeIO.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/freelist/io/FreeIO.java deleted file mode 100644 index 5af351c..0000000 --- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/freelist/io/FreeIO.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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.query.h2.database.freelist.io; - -import java.nio.ByteBuffer; - -/** - * Common routines for free list pages. - */ -public interface FreeIO { - /** - * @param buf Buffer. - * @param idx Index. - * @return Dispersed free space. - */ - public int dispersedFreeSpace(ByteBuffer buf, int idx); - - /** - * @param buf Buffer. - * @param idx Index. - * @return Free space. - */ - public short freeSpace(ByteBuffer buf, int idx); -} http://git-wip-us.apache.org/repos/asf/ignite/blob/2f7a22c1/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/freelist/io/FreeInnerIO.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/freelist/io/FreeInnerIO.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/freelist/io/FreeInnerIO.java deleted file mode 100644 index b8a3872..0000000 --- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/freelist/io/FreeInnerIO.java +++ /dev/null @@ -1,67 +0,0 @@ -package org.apache.ignite.internal.processors.query.h2.database.freelist.io; - -import java.nio.ByteBuffer; -import org.apache.ignite.internal.processors.query.h2.database.freelist.FreeItem; -import org.apache.ignite.internal.processors.cache.database.tree.BPlusTree; -import org.apache.ignite.internal.processors.cache.database.tree.io.BPlusIO; -import org.apache.ignite.internal.processors.cache.database.tree.io.BPlusInnerIO; -import org.apache.ignite.internal.processors.cache.database.tree.io.IOVersions; - -/** - * Routines for free list inner pages. - */ -public class FreeInnerIO extends BPlusInnerIO<FreeItem> implements FreeIO { - /** */ - public static final IOVersions<FreeInnerIO> VERSIONS = new IOVersions<>( - new FreeInnerIO(1) - ); - - /** - * @param ver Page format version. - */ - protected FreeInnerIO(int ver) { - super(T_FREE_INNER, ver, false, 4); // freeSpace(2) + dispersion(2) - } - - /** {@inheritDoc} */ - @Override public void store(ByteBuffer buf, int idx, FreeItem row) { - store(buf, idx, row.dispersedFreeSpace()); - } - - /** {@inheritDoc} */ - @Override public void store(ByteBuffer dst, int dstIdx, BPlusIO<FreeItem> srcIo, ByteBuffer src, int srcIdx) { - store(dst, dstIdx, ((FreeIO)srcIo).dispersedFreeSpace(src, srcIdx)); - } - - /** - * @param buf Buffer. - * @param idx Index. - * @param dispersedFreeSpace Dispersed free space. - */ - private void store(ByteBuffer buf, int idx, int dispersedFreeSpace) { - int off = offset(idx, SHIFT_LINK); - - buf.putInt(off, dispersedFreeSpace); - } - - /** {@inheritDoc} */ - @Override public int dispersedFreeSpace(ByteBuffer buf, int idx) { - int off = offset(idx, SHIFT_LINK); - - return buf.getInt(off); - } - - /** {@inheritDoc} */ - @Override public short freeSpace(ByteBuffer buf, int idx) { - int off = offset(idx, SHIFT_LINK); - - return buf.getShort(off); - } - - /** {@inheritDoc} */ - @Override public FreeItem getLookupRow(BPlusTree<FreeItem, ?> tree, ByteBuffer buf, int idx) { - int off = offset(idx, SHIFT_LINK); - - return new FreeItem(buf.getShort(off), buf.getShort(off + 2), 0, 0); - } -} http://git-wip-us.apache.org/repos/asf/ignite/blob/2f7a22c1/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/freelist/io/FreeLeafIO.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/freelist/io/FreeLeafIO.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/freelist/io/FreeLeafIO.java deleted file mode 100644 index ee71f18..0000000 --- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/freelist/io/FreeLeafIO.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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.query.h2.database.freelist.io; - -import java.nio.ByteBuffer; -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.query.h2.database.freelist.FreeItem; - -/** - * Routines for free list leaf pages. - */ -public class FreeLeafIO extends BPlusLeafIO<FreeItem> implements FreeIO { - /** */ - public static final IOVersions<FreeLeafIO> VERSIONS = new IOVersions<>( - new FreeLeafIO(1) - ); - - /** - * @param ver Page format version. - */ - protected FreeLeafIO(int ver) { - super(T_FREE_LEAF, ver, 12); // freeSpace(2) + dispersion(2) + pageId(8) - } - - /** {@inheritDoc} */ - @Override public final void store(ByteBuffer buf, int idx, FreeItem row) { - int off = offset(idx); - - buf.putInt(off, row.dispersedFreeSpace()); - buf.putLong(off + 4, row.pageId()); - } - - /** {@inheritDoc} */ - @Override public int dispersedFreeSpace(ByteBuffer buf, int idx) { - int off = offset(idx); - - return buf.getInt(off); - } - - /** {@inheritDoc} */ - @Override public short freeSpace(ByteBuffer buf, int idx) { - int off = offset(idx); - - return buf.getShort(off); - } - - /** {@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()); - } -} http://git-wip-us.apache.org/repos/asf/ignite/blob/2f7a22c1/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Row.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Row.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Row.java index 52b9b5f..a84ad20 100644 --- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Row.java +++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Row.java @@ -19,13 +19,14 @@ package org.apache.ignite.internal.processors.query.h2.opt; import org.apache.ignite.internal.processors.cache.CacheObject; import org.apache.ignite.internal.processors.cache.version.GridCacheVersion; +import org.apache.ignite.internal.processors.cache.database.CacheDataRow; import org.h2.result.Row; import org.h2.value.Value; /** * Row with locking support needed for unique key conflicts resolution. */ -public class GridH2Row extends Row implements GridSearchRowPointer { +public class GridH2Row extends Row implements GridSearchRowPointer, CacheDataRow { /** */ public long link; // TODO remove @@ -62,4 +63,34 @@ public class GridH2Row extends Row implements GridSearchRowPointer { @Override public void decrementRefCount() { throw new IllegalStateException(); } + + /** {@inheritDoc} */ + @Override public CacheObject key() { + return key; + } + + /** {@inheritDoc} */ + @Override public CacheObject value() { + return val; + } + + /** {@inheritDoc} */ + @Override public GridCacheVersion version() { + return ver; + } + + /** {@inheritDoc} */ + @Override public int partition() { + return partId; + } + + /** {@inheritDoc} */ + @Override public long link() { + return link; + } + + /** {@inheritDoc} */ + @Override public void link(long link) { + this.link = link; + } } \ No newline at end of file
