blob: 92909caeef59631c9b8fd8c8aa532de45e19f89e [file] [log] [blame]
/*
* 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.internal.processors.cache.database.tree.util.PageHandler;
import org.apache.ignite.internal.util.GridUnsafe;
/**
* Abstract IO routines for B+Tree inner pages.
*/
public abstract class BPlusInnerIO<L> extends BPlusIO<L> {
/** */
private static final int SHIFT_LEFT = ITEMS_OFF;
/** */
private static final int SHIFT_LINK = SHIFT_LEFT + 8;
/** */
private final int SHIFT_RIGHT = SHIFT_LINK + itemSize;
/**
* @param type Page type.
* @param ver Page format version.
* @param canGetRow If we can get full row from this page.
* @param itemSize Single item size on page.
*/
protected BPlusInnerIO(int type, int ver, boolean canGetRow, int itemSize) {
super(type, ver, false, canGetRow, itemSize);
}
/** {@inheritDoc} */
@Override public int getMaxCount(ByteBuffer buf) {
// The structure of the page is the following:
// |ITEMS_OFF|w|A|x|B|y|C|z|
// where capital letters are data items, lowercase letters are 8 byte page references.
return (buf.capacity() - ITEMS_OFF - 8) / (itemSize + 8);
}
/**
* @param buf Buffer.
* @param idx Index.
* @return Page ID.
*/
public final long getLeft(ByteBuffer buf, int idx) {
return buf.getLong(offset(idx, SHIFT_LEFT));
}
public final long getLeft(long buf, int idx) {
return GridUnsafe.getLong(buf, offset(idx, SHIFT_LEFT));
}
/**
* @param buf Buffer.
* @param idx Index.
* @param pageId Page ID.
*/
public final void setLeft(ByteBuffer buf, int idx, long pageId) {
buf.putLong(offset(idx, SHIFT_LEFT), pageId);
assert pageId == getLeft(buf, idx);
}
/**
* @param buf Buffer.
* @param idx Index.
* @return Page ID.
*/
public final long getRight(ByteBuffer buf, int idx) {
return buf.getLong(offset(idx, SHIFT_RIGHT));
}
public final long getRight(long buf, int idx) {
return GridUnsafe.getLong(buf, offset(idx, SHIFT_RIGHT));
}
/**
* @param buf Buffer.
* @param idx Index.
* @param pageId Page ID.
*/
public final void setRight(ByteBuffer buf, int idx, long pageId) {
buf.putLong(offset(idx, SHIFT_RIGHT), pageId);
assert pageId == getRight(buf, idx);
}
/** {@inheritDoc} */
@Override public final void copyItems(ByteBuffer src, ByteBuffer dst, int srcIdx, int dstIdx, int cnt,
boolean cpLeft) throws IgniteCheckedException {
assert srcIdx != dstIdx || src != dst;
cnt *= itemSize + 8; // From items to bytes.
if (dstIdx > srcIdx) {
PageHandler.copyMemory(src, dst, offset(srcIdx), offset(dstIdx), cnt);
if (cpLeft)
dst.putLong(offset(dstIdx, SHIFT_LEFT), src.getLong(offset(srcIdx, SHIFT_LEFT)));
}
else {
if (cpLeft)
dst.putLong(offset(dstIdx, SHIFT_LEFT), src.getLong(offset(srcIdx, SHIFT_LEFT)));
PageHandler.copyMemory(src, dst, offset(srcIdx), offset(dstIdx), cnt);
}
}
/**
* @param idx Index of element.
* @param shift It can be either link itself or left or right page ID.
* @return Offset from byte buffer begin in bytes.
*/
private int offset(int idx, int shift) {
return shift + (8 + itemSize) * idx;
}
/** {@inheritDoc} */
@Override protected final int offset(int idx) {
return offset(idx, SHIFT_LINK);
}
// Methods for B+Tree logic.
/** {@inheritDoc} */
@Override public void insert(
ByteBuffer buf,
int idx,
L row,
byte[] rowBytes,
long rightId
) throws IgniteCheckedException {
super.insert(buf, idx, row, rowBytes, rightId);
// Setup reference to the right page on split.
setRight(buf, idx, rightId);
}
/**
* @param newRootBuf New root buffer.
* @param newRootId New root ID.
* @param leftChildId Left child ID.
* @param row Moved up row.
* @param rightChildId Right child ID.
* @throws IgniteCheckedException If failed.
*/
public void initNewRoot(
ByteBuffer newRootBuf,
long newRootId,
long leftChildId,
L row,
byte[] rowBytes,
long rightChildId
) throws IgniteCheckedException {
initNewPage(newRootBuf, newRootId);
setCount(newRootBuf, 1);
setLeft(newRootBuf, 0, leftChildId);
store(newRootBuf, 0, row, rowBytes);
setRight(newRootBuf, 0, rightChildId);
}
}