http://git-wip-us.apache.org/repos/asf/ignite/blob/cbfed9cf/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/BPlusIOLeaf.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/BPlusIOLeaf.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/BPlusIOLeaf.java new file mode 100644 index 0000000..0aaa3b8 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/BPlusIOLeaf.java @@ -0,0 +1,84 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.cache.database.tree.io; + +import java.nio.ByteBuffer; + +/** + * Abstract IO routines for B+Tree leaf pages. + */ +public abstract class BPlusIOLeaf<L> extends BPlusIO<L> { + /** */ + protected static final int ITEM_SIZE = 8; + + /** + * @param ver Page format version. + */ + protected BPlusIOLeaf(int ver) { + super(ver); + } + + /** {@inheritDoc} */ + @Override public boolean isLeaf() { + return true; + } + + /** {@inheritDoc} */ + @Override public int getMaxCount(ByteBuffer buf) { + return (buf.capacity() - ITEMS_OFF) >>> 3; // divide by ITEM_SIZE + } + +// /** {@inheritDoc} */ +// @Override public long getLink(ByteBuffer buf, int idx) { +// assert idx < getCount(buf): idx; +// +// return buf.getLong(offset(idx)); +// } +// +// /** {@inheritDoc} */ +// @Override public void setLink(ByteBuffer buf, int idx, long link) { +// buf.putLong(offset(idx), link); +// +// assert getLink(buf, idx) == link; +// } + + /** {@inheritDoc} */ + @Override public void copyItems(ByteBuffer src, ByteBuffer dst, int srcIdx, int dstIdx, int cnt, + boolean cpLeft) { + assert srcIdx != dstIdx || src != dst; + + if (dstIdx > srcIdx) { + for (int i = cnt - 1; i >= 0; i--) + dst.putLong(offset(dstIdx + i), src.getLong(offset(srcIdx + i))); + } + else { + for (int i = 0; i < cnt; i++) + dst.putLong(offset(dstIdx + i), src.getLong(offset(srcIdx + i))); + } + } + + /** + * @param idx Index of item. + * @return Offset. + */ + protected static int offset(int idx) { + assert idx >= 0: idx; + + return ITEMS_OFF + idx * ITEM_SIZE; + } +}
http://git-wip-us.apache.org/repos/asf/ignite/blob/cbfed9cf/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/BPlusIOMeta.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/BPlusIOMeta.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/BPlusIOMeta.java new file mode 100644 index 0000000..f5d31ad --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/BPlusIOMeta.java @@ -0,0 +1,117 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.cache.database.tree.io; + +import java.nio.ByteBuffer; + +/** + * IO routines for B+Tree meta pages. + */ +public class BPlusIOMeta extends PageIO { + /** */ + public static final IORegistry<BPlusIOMeta> VERSIONS = new IORegistry<>( + new BPlusIOMeta(1) + ); + + /** */ + private static final int LVLS_OFF = COMMON_HEADER_END; + + /** */ + private static final int REFS_OFF = LVLS_OFF + 1; + + /** + * @param ver Page format version. + */ + protected BPlusIOMeta(int ver) { + super(ver); + } + + /** {@inheritDoc} */ + @Override public int getType() { + return T_BPLUS_META; + } + + /** {@inheritDoc} */ + @Override public void initNewPage(ByteBuffer buf, long pageId) { + super.initNewPage(buf, pageId); + + setLevelsCount(buf, 0); + } + + /** + * @param buf Buffer. + * @return Number of levels in this tree. + */ + public int getLevelsCount(ByteBuffer buf) { + return buf.get(LVLS_OFF); + } + + /** + * @param buf Buffer. + * @param lvls Number of levels in this tree. + */ + public void setLevelsCount(ByteBuffer buf, int lvls) { + assert lvls >= 0 && lvls < 30; + + buf.put(LVLS_OFF, (byte)lvls); + + assert getLevelsCount(buf) == lvls; + } + + /** + * @param lvl Level. + * @return Offset for page reference. + */ + private static int offset(int lvl) { + return lvl * 8 + REFS_OFF; + } + + /** + * @param buf Buffer. + * @param lvl Level. + * @return Page reference at that level. + */ + public long getLeftmostPageId(ByteBuffer buf, int lvl) { + return buf.getLong(offset(lvl)); + } + + /** + * @param buf Buffer. + * @param lvl Level. + * @param pageId Page ID. + */ + public void setLeftmostPageId(ByteBuffer buf, int lvl, long pageId) { + assert lvl >= 0 && lvl < getLevelsCount(buf); + + buf.putLong(offset(lvl), pageId); + + assert getLeftmostPageId(buf, lvl) == pageId; + } + + /** + * @param buf Buffer. + * @return Root level. + */ + public int getRootLevel(ByteBuffer buf) { + int lvls = getLevelsCount(buf); // The highest level page is root. + + assert lvls > 0 : lvls; + + return lvls - 1; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/cbfed9cf/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/DataPageIO.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/DataPageIO.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/DataPageIO.java new file mode 100644 index 0000000..ffa5fc1 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/DataPageIO.java @@ -0,0 +1,268 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.cache.database.tree.io; + +import java.nio.ByteBuffer; +import org.apache.ignite.IgniteCheckedException; +import org.apache.ignite.IgniteException; +import org.apache.ignite.internal.processors.cache.CacheObject; +import org.apache.ignite.internal.processors.cache.CacheObjectContext; +import org.apache.ignite.internal.processors.cache.version.GridCacheVersion; + +/** + * Data pages IO. + */ +public class DataPageIO extends PageIO { + /** */ + public static final IORegistry<DataPageIO> VERSIONS = new IORegistry<>( + new DataPageIO(1) + ); + + /** */ + private static final int OCCUPIED_SIZE_OFF = COMMON_HEADER_END; + + /** */ + private static final int ALL_CNT_OFF = OCCUPIED_SIZE_OFF + 2; + + /** */ + private static final int LIVE_CNT_OFF = ALL_CNT_OFF + 2; + + /** */ + private static final int ITEMS_OFF = LIVE_CNT_OFF + 2; + + /** */ + private static final int ITEM_SIZE = 2; + + /** + * @param ver Page format version. + */ + protected DataPageIO(int ver) { + super(ver); + } + + /** {@inheritDoc} */ + @Override public int getType() { + return T_DATA; + } + + /** {@inheritDoc} */ + @Override public void initNewPage(ByteBuffer buf, long pageId) { + super.initNewPage(buf, pageId); + + setAllCount(buf, 0); + setLiveCount(buf, 0); + setOccupiedSize(buf, 0); + } + + public int getOccupiedSize(ByteBuffer buf) { + return buf.getShort(OCCUPIED_SIZE_OFF) & 0xFFFF; + } + + public void setOccupiedSize(ByteBuffer buf, int size) { + buf.putShort(OCCUPIED_SIZE_OFF, (short)size); + + assert getOccupiedSize(buf) == size; + } + + public int getAllCount(ByteBuffer buf) { + return buf.getShort(ALL_CNT_OFF) & 0xFFFF; + } + + public void setAllCount(ByteBuffer buf, int cnt) { + buf.putShort(ALL_CNT_OFF, (short)cnt); + + assert cnt == getAllCount(buf); + } + + public int getLiveCount(ByteBuffer buf) { + return buf.getShort(LIVE_CNT_OFF) & 0xFFFF; + } + + public void setLiveCount(ByteBuffer buf, int cnt) { + buf.putShort(LIVE_CNT_OFF, (short)cnt); + + assert cnt == getLiveCount(buf); + } + + public boolean canAddEntry(ByteBuffer buf, int entrySize) { + int free = buf.capacity() - ITEMS_OFF - getOccupiedSize(buf); + + if (free < entrySize) + return false; + + free -= (getAllCount(buf) - getLiveCount(buf)) * ITEM_SIZE; + + return free >= entrySize; + } + + /** + * @param keySize Key size. + * @param valSize Value size. + * @return Entry size including item. + */ + private static int entrySize(int keySize, int valSize) { + return ITEM_SIZE + 2/*key+val len*/ + keySize + valSize + 24/*ver*/; + } + + /** + * @param idx Index of item. + * @return Offset in bytes. + */ + private static int offset(int idx) { + return ITEMS_OFF + idx * ITEM_SIZE; + } + + /** + * @param buf Buffer. + * @param idx Index of item. + * @return Data offset in bytes. + */ + public int getDataOffset(ByteBuffer buf, int idx) { + return buf.getShort(offset(idx)) & 0xFFFF; + } + + /** + * @param buf Buffer. + * @param idx Index of item. + * @param dataOff Data offset in bytes. + */ + private void setDataOffset(ByteBuffer buf, int idx, int dataOff) { + buf.putShort(offset(idx), (short)dataOff); + + assert dataOff == getDataOffset(buf, idx); + } + + /** + * Make a window for data entry. + * + * @param buf Buffer. + * @param idx Index of the new item. + * @param allCnt All count. + * @param entrySize Entry size. + * @return Data offset for the new entry. + */ + public int makeWindow(ByteBuffer buf, int idx, int allCnt, int entrySize) { + if (idx == allCnt) { // Adding to the end of items. + int off = offset(idx); + int lastDataOff = allCnt == 0 ? buf.capacity() : getDataOffset(buf, allCnt - 1); + + if (lastDataOff - off < entrySize) // TODO try to defragment + return -1; + + return lastDataOff - entrySize + ITEM_SIZE; + } + else { + //TODO defragment page with respect to idx and entrySize (if idx is not last, the window must be not first) + throw new UnsupportedOperationException(); + } + } + + public int addRow( + CacheObjectContext coctx, + ByteBuffer buf, + CacheObject key, + CacheObject val, + GridCacheVersion ver) throws IgniteCheckedException + { + int keyLen = key.valueBytesLength(coctx); + int valLen = val.valueBytesLength(coctx); + int entrySize = entrySize(keyLen, valLen); + + if (entrySize >= buf.capacity() - ITEMS_OFF) + throw new IgniteException("Too big entry: " + keyLen + " " + valLen); + + if (!canAddEntry(buf, entrySize)) + return -1; + + int liveCnt = getLiveCount(buf); + int allCnt = getAllCount(buf); + int idx = 0; + + if (allCnt == liveCnt) + idx = allCnt; // Allocate new idx at allCnt if all are alive. + else { + // Lookup for a free parking lot. + while (idx < allCnt) { + if (getDataOffset(buf, idx) == 0) + break; + + idx++; + } + } + + int dataOff = makeWindow(buf, idx, allCnt, entrySize); + + if (dataOff == -1) + return -1; + + // Write data. + writeRowDataInPlace(coctx, buf, dataOff, keyLen + valLen, key, val, ver); + // Write item. + setDataOffset(buf, idx, dataOff); + + // Update header. + setOccupiedSize(buf, getOccupiedSize(buf) + entrySize); + setAllCount(buf, allCnt + 1); + setLiveCount(buf, liveCnt + 1); + + return idx; + } + + /** + * @param buf Buffer. + * @param dataOff Data offset. + * @param key Key. + * @param val Value. + * @param ver Version. + */ + public void writeRowDataInPlace( + CacheObjectContext coctx, + ByteBuffer buf, + int dataOff, + int keyValLen, + CacheObject key, + CacheObject val, + GridCacheVersion ver + ) throws IgniteCheckedException { + try { + buf.position(dataOff); + + buf.putShort((short)keyValLen); + + boolean written = key.putValue(buf, coctx); + + assert written; + + written = val.putValue(buf, coctx); + + assert written; + + buf.putInt(ver.topologyVersion()); + buf.putInt(ver.nodeOrderAndDrIdRaw()); + buf.putLong(ver.globalTime()); + buf.putLong(ver.order()); + } + finally { + buf.position(0); + } + } + + public int getKeyValueSize(ByteBuffer buf, int idx) { + return buf.getShort(getDataOffset(buf, idx)) & 0xFFFF; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/cbfed9cf/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/IORegistry.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/IORegistry.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/IORegistry.java new file mode 100644 index 0000000..c95a45d --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/IORegistry.java @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.cache.database.tree.io; + +import java.nio.ByteBuffer; + +/** + * Registry for IO versions. + */ +public final class IORegistry<V extends PageIO> { + /** */ + private final V[] vers; + + /** + * @param vers Versions. + */ + @SafeVarargs + public IORegistry(V... vers) { + assert vers != null; + assert vers.length > 0; + + this.vers = vers; + + assert checkVersions(); + } + + /** + * @return {@code true} If versions are correct. + */ + private boolean checkVersions() { + for (int i = 0; i < vers.length; i++) { + if (vers[i].getVersion() != i + 1) + return false; + } + + return true; + } + + /** + * @return Latest IO version. + */ + public V latest() { + return forVersion(vers.length); + } + + /** + * @param ver Version. + * @return IO. + */ + public V forVersion(int ver) { + return vers[ver - 1]; + } + + /** + * @param buf Buffer. + * @return IO. + */ + public V forPage(ByteBuffer buf) { + int ver = PageIO.getVersion(buf); + + V res = forVersion(ver); + + assert res.getType() == PageIO.getType(buf); + + return res; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/cbfed9cf/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/PageIO.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/PageIO.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/PageIO.java new file mode 100644 index 0000000..001d5cc --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/io/PageIO.java @@ -0,0 +1,166 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.cache.database.tree.io; + +import java.nio.ByteBuffer; + +/** + * Base format for all the page types. + */ +public abstract class PageIO { + /** */ + private static final int TYPE_OFF = 0; + + /** */ + private static final int VER_OFF = TYPE_OFF + 2; + + /** */ + private static final int PAGE_ID_OFF = VER_OFF + 2; + + /** */ + private static final int CRC_OFF = PAGE_ID_OFF + 8; + + /** */ + public static final int COMMON_HEADER_END = 32; // type(2) + ver(2) + pageId(8) + crc(4) + reserved(16) + + /* All the page types. */ + + /** */ + public static final short T_DATA = 1; + + /** */ + public static final short T_BPLUS_META = 2; + + /** */ + public static final short T_H2_REF_LEAF = 3; + + /** */ + public static final short T_H2_REF_INNER = 4; + + /** */ + private final int ver; + + /** + * @param ver Page format version. + */ + protected PageIO(int ver) { + assert ver > 0 && ver < 65535: ver; + + this.ver = ver; + } + + + + /** + * @return Page type. + */ + public static int getType(ByteBuffer buf) { + return buf.getShort(TYPE_OFF) & 0xFFFF; + } + + /** + * @param buf Buffer. + * @param type Type. + */ + public static void setType(ByteBuffer buf, int type) { + assert type >= T_DATA && type <= T_H2_REF_INNER : type; + + buf.putShort(TYPE_OFF, (short)type); + + assert getType(buf) == type; + } + + /** + * @param buf Buffer. + * @return Version. + */ + public static int getVersion(ByteBuffer buf) { + return buf.getShort(VER_OFF) & 0xFFFF; + } + + /** + * @param buf Buffer. + * @param ver Version. + */ + public static void setVersion(ByteBuffer buf, int ver) { + buf.putShort(VER_OFF, (short)ver); + + assert getVersion(buf) == ver; + } + + /** + * @param buf Buffer. + * @return Page ID. + */ + public static long getPageId(ByteBuffer buf) { + return buf.getLong(PAGE_ID_OFF); + } + + /** + * @param buf Buffer. + * @param pageId Page ID. + */ + public static void setPageId(ByteBuffer buf, long pageId) { + buf.putLong(PAGE_ID_OFF, pageId); + + assert getPageId(buf) == pageId; + } + + /** + * @param buf Buffer. + * @return Checksum. + */ + public static int getCrc(ByteBuffer buf) { + return buf.getInt(CRC_OFF); + } + + /** + * @param buf Buffer. + * @param crc Checksum. + */ + public static void setCrc(ByteBuffer buf, int crc) { + buf.putInt(CRC_OFF, crc); + } + + /** + * @return Type. + */ + public abstract int getType(); + + /** + * @return Version. + */ + public final int getVersion() { + return ver; + } + + /** + * @param buf Buffer. + * @param pageId Page ID. + */ + public void initNewPage(ByteBuffer buf, long pageId) { + setType(buf, getType()); + setVersion(buf, getVersion()); + setPageId(buf, pageId); + } + + /** {@inheritDoc} */ + @Override public String toString() { + return getClass().getSimpleName() + "[ver=" + getVersion() + "]"; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/cbfed9cf/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/util/PageHandler.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/util/PageHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/util/PageHandler.java new file mode 100644 index 0000000..3d1b4e4 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/util/PageHandler.java @@ -0,0 +1,111 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.cache.database.tree.util; + +import java.nio.ByteBuffer; +import org.apache.ignite.IgniteCheckedException; +import org.apache.ignite.internal.pagemem.Page; + +/** + * Page handler. Can do {@link #readPage(Page, PageHandler, Object, int, int)} + * and {@link #writePage(Page, PageHandler, Object, int, int)} operations. + */ +public abstract class PageHandler<X> { + /** + * @param page Page. + * @param buf Page buffer. + * @param arg Argument. + * @param intArg Argument of type {@code int}. + * @return Result. + * @throws IgniteCheckedException If failed. + */ + public abstract int run(Page page, ByteBuffer buf, X arg, int intArg) throws IgniteCheckedException; + + /** + * @param page Page. + * @param arg Argument. + * @param intArg Argument of type {@code int}. + * @return {@code true} If release. + */ + public boolean releaseAfterWrite(Page page, X arg, int intArg) { + return true; + } + + /** + * @param page Page. + * @param h Handler. + * @param arg Argument. + * @param intArg Argument of type {@code int}. + * @param dfltRes Default result in case of page invalidation. + * @return Handler result. + * @throws IgniteCheckedException If failed. + */ + public static <X> int readPage(Page page, PageHandler<X> h, X arg, int intArg, int dfltRes) + throws IgniteCheckedException { + if (page == null) + return dfltRes; + + ByteBuffer buf = page.getForRead(); + + if (buf == null) + return dfltRes; + + try { + return h.run(page, buf, arg, intArg); + } + finally { + page.releaseRead(); + } + } + + /** + * @param page Page. + * @param h Handler. + * @param arg Argument. + * @param intArg Argument of type {@code int}. + * @param dfltRes Default result in case of page invalidation. + * @return Handler result. + * @throws IgniteCheckedException If failed. + */ + public static <X> int writePage(Page page, PageHandler<X> h, X arg, int intArg, int dfltRes) + throws IgniteCheckedException { + if (page == null) + return dfltRes; + + int res; + + boolean ok = false; + + ByteBuffer buf = page.getForWrite(); + + if (buf == null) + return dfltRes; + + try { + res = h.run(page, buf, arg, intArg); + + ok = true; + } + finally { + if (h.releaseAfterWrite(page, arg, intArg)) + page.releaseWrite(ok); + } + + return res; + } +}
