use of org.apache.hyracks.storage.am.common.api.ITreeIndexFrame in project asterixdb by apache.
the class BTreeNSMInteriorFrame method split.
@Override
public void split(ITreeIndexFrame rightFrame, ITupleReference tuple, ISplitKey splitKey, IExtraPageBlockHelper extraPageBlockHelper, IBufferCache bufferCache) throws HyracksDataException {
ByteBuffer right = rightFrame.getBuffer();
int tupleCount = getTupleCount();
// Find split point, and determine into which frame the new tuple should be inserted into.
ITreeIndexFrame targetFrame = null;
frameTuple.resetByTupleIndex(this, tupleCount - 1);
int tuplesToLeft;
if (cmp.compare(tuple, frameTuple) > 0) {
// This is a special optimization case when the tuple to be inserted is the largest key on the page.
targetFrame = rightFrame;
tuplesToLeft = tupleCount;
} else {
int totalSize = 0;
int halfPageSize = (buf.capacity() - getPageHeaderSize()) / 2;
int i;
for (i = 0; i < tupleCount; ++i) {
frameTuple.resetByTupleIndex(this, i);
totalSize += tupleWriter.bytesRequired(frameTuple) + CHILD_PTR_SIZE + slotManager.getSlotSize();
if (totalSize >= halfPageSize) {
break;
}
}
if (cmp.compare(tuple, frameTuple) > 0) {
tuplesToLeft = i;
targetFrame = rightFrame;
} else {
tuplesToLeft = i + 1;
targetFrame = this;
}
int tuplesToRight = tupleCount - tuplesToLeft;
// Copy entire page.
System.arraycopy(buf.array(), 0, right.array(), 0, buf.capacity());
// On the right page we need to copy rightmost slots to left.
int src = rightFrame.getSlotManager().getSlotEndOff();
int dest = rightFrame.getSlotManager().getSlotEndOff() + tuplesToLeft * rightFrame.getSlotManager().getSlotSize();
int length = rightFrame.getSlotManager().getSlotSize() * tuplesToRight;
System.arraycopy(right.array(), src, right.array(), dest, length);
right.putInt(Constants.TUPLE_COUNT_OFFSET, tuplesToRight);
// On the left page, remove the highest key and make its child pointer
// the rightmost child pointer.
buf.putInt(Constants.TUPLE_COUNT_OFFSET, tuplesToLeft);
}
// Copy the split key to be inserted.
// We must do so because setting the new split key will overwrite the
// old split key, and we cannot insert the existing split key at this point.
ISplitKey savedSplitKey = splitKey.duplicate(tupleWriter.createTupleReference());
// Set split key to be highest value in left page.
int tupleOff = slotManager.getTupleOff(slotManager.getSlotEndOff());
frameTuple.resetByTupleOffset(buf.array(), tupleOff);
int splitKeySize = tupleWriter.bytesRequired(frameTuple, 0, cmp.getKeyFieldCount());
splitKey.initData(splitKeySize);
tupleWriter.writeTuple(frameTuple, splitKey.getBuffer(), 0);
splitKey.getTuple().resetByTupleOffset(splitKey.getBuffer().array(), 0);
int deleteTupleOff = slotManager.getTupleOff(slotManager.getSlotEndOff());
frameTuple.resetByTupleOffset(buf.array(), deleteTupleOff);
buf.putInt(RIGHT_LEAF_OFFSET, buf.getInt(getLeftChildPageOff(frameTuple)));
buf.putInt(Constants.TUPLE_COUNT_OFFSET, tuplesToLeft - 1);
// Compact both pages.
rightFrame.compact();
compact();
// Insert the saved split key.
int targetTupleIndex;
// it's safe to catch this exception since it will have been caught before reaching here
targetTupleIndex = ((BTreeNSMInteriorFrame) targetFrame).findInsertTupleIndex(savedSplitKey.getTuple());
targetFrame.insert(savedSplitKey.getTuple(), targetTupleIndex);
}
use of org.apache.hyracks.storage.am.common.api.ITreeIndexFrame in project asterixdb by apache.
the class BTreeUpdateSearchOperatorNodePushable method createCursor.
@Override
protected ITreeIndexCursor createCursor() {
ITreeIndex treeIndex = (ITreeIndex) index;
ITreeIndexFrame cursorFrame = treeIndex.getLeafFrameFactory().createFrame();
return new BTreeRangeSearchCursor((IBTreeLeafFrame) cursorFrame, true);
}
use of org.apache.hyracks.storage.am.common.api.ITreeIndexFrame in project asterixdb by apache.
the class TreeIndexDiskOrderScanOperatorNodePushable method initialize.
@Override
public void initialize() throws HyracksDataException {
treeIndexHelper.open();
ITreeIndex treeIndex = (ITreeIndex) treeIndexHelper.getIndexInstance();
try {
ITreeIndexFrame cursorFrame = treeIndex.getLeafFrameFactory().createFrame();
ITreeIndexCursor cursor = new TreeIndexDiskOrderScanCursor(cursorFrame);
LocalResource resource = treeIndexHelper.getResource();
ISearchOperationCallback searchCallback = searchCallbackFactory.createSearchOperationCallback(resource.getId(), ctx, null);
ITreeIndexAccessor indexAccessor = (ITreeIndexAccessor) treeIndex.createAccessor(NoOpOperationCallback.INSTANCE, searchCallback);
try {
writer.open();
indexAccessor.diskOrderScan(cursor);
int fieldCount = treeIndex.getFieldCount();
FrameTupleAppender appender = new FrameTupleAppender(new VSizeFrame(ctx));
ArrayTupleBuilder tb = new ArrayTupleBuilder(fieldCount);
DataOutput dos = tb.getDataOutput();
while (cursor.hasNext()) {
tb.reset();
cursor.next();
ITupleReference frameTuple = cursor.getTuple();
for (int i = 0; i < frameTuple.getFieldCount(); i++) {
dos.write(frameTuple.getFieldData(i), frameTuple.getFieldStart(i), frameTuple.getFieldLength(i));
tb.addFieldEndOffset();
}
FrameUtils.appendToWriter(writer, appender, tb.getFieldEndOffsets(), tb.getByteArray(), 0, tb.getSize());
}
appender.write(writer, true);
} catch (Throwable th) {
writer.fail();
throw new HyracksDataException(th);
} finally {
try {
cursor.close();
} catch (Exception cursorCloseException) {
throw new IllegalStateException(cursorCloseException);
} finally {
writer.close();
}
}
} catch (Throwable th) {
treeIndexHelper.close();
throw new HyracksDataException(th);
}
}
use of org.apache.hyracks.storage.am.common.api.ITreeIndexFrame in project asterixdb by apache.
the class BTreeFieldPrefixNSMLeafFrame method split.
@Override
public void split(ITreeIndexFrame rightFrame, ITupleReference tuple, ISplitKey splitKey, IExtraPageBlockHelper extraPageBlockHelper, IBufferCache bufferCache) throws HyracksDataException {
BTreeFieldPrefixNSMLeafFrame rf = (BTreeFieldPrefixNSMLeafFrame) rightFrame;
ByteBuffer right = rf.getBuffer();
int tupleCount = getTupleCount();
int prefixTupleCount = getPrefixTupleCount();
// Find split point, and determine into which frame the new tuple should
// be inserted into.
int tuplesToLeft;
int midSlotNum = tupleCount / 2;
ITreeIndexFrame targetFrame = null;
frameTuple.resetByTupleIndex(this, midSlotNum);
int comparison = cmp.compare(tuple, frameTuple);
if (comparison >= 0) {
tuplesToLeft = midSlotNum + (tupleCount % 2);
targetFrame = rf;
} else {
tuplesToLeft = midSlotNum;
targetFrame = this;
}
int tuplesToRight = tupleCount - tuplesToLeft;
// copy entire page
System.arraycopy(buf.array(), 0, right.array(), 0, buf.capacity());
// determine how many slots go on left and right page
int prefixesToLeft = prefixTupleCount;
for (int i = tuplesToLeft; i < tupleCount; i++) {
int tupleSlotOff = rf.slotManager.getTupleSlotOff(i);
int tupleSlot = right.getInt(tupleSlotOff);
int prefixSlotNum = rf.slotManager.decodeFirstSlotField(tupleSlot);
if (prefixSlotNum != FieldPrefixSlotManager.TUPLE_UNCOMPRESSED) {
prefixesToLeft = prefixSlotNum;
break;
}
}
// if we are splitting in the middle of a prefix both pages need to have the prefix slot and tuple
int boundaryTupleSlotOff = rf.slotManager.getTupleSlotOff(tuplesToLeft - 1);
int boundaryTupleSlot = buf.getInt(boundaryTupleSlotOff);
int boundaryPrefixSlotNum = rf.slotManager.decodeFirstSlotField(boundaryTupleSlot);
int prefixesToRight = prefixTupleCount - prefixesToLeft;
if (boundaryPrefixSlotNum == prefixesToLeft && boundaryPrefixSlotNum != FieldPrefixSlotManager.TUPLE_UNCOMPRESSED) {
// tuples on both pages share one prefix
prefixesToLeft++;
}
// move prefix tuples on right page to beginning of page and adjust prefix slots
if (prefixesToRight > 0 && prefixesToLeft > 0 && prefixTupleCount > 1) {
int freeSpace = rf.getOrigFreeSpaceOff();
int lastPrefixSlotNum = -1;
for (int i = tuplesToLeft; i < tupleCount; i++) {
int tupleSlotOff = rf.slotManager.getTupleSlotOff(i);
int tupleSlot = right.getInt(tupleSlotOff);
int prefixSlotNum = rf.slotManager.decodeFirstSlotField(tupleSlot);
if (prefixSlotNum != FieldPrefixSlotManager.TUPLE_UNCOMPRESSED) {
framePrefixTuple.resetByTupleIndex(this, prefixSlotNum);
int bytesWritten = 0;
if (lastPrefixSlotNum != prefixSlotNum) {
bytesWritten = tupleWriter.writeTuple(framePrefixTuple, right.array(), freeSpace);
int newPrefixSlot = rf.slotManager.encodeSlotFields(framePrefixTuple.getFieldCount(), freeSpace);
int prefixSlotOff = rf.slotManager.getPrefixSlotOff(prefixSlotNum);
right.putInt(prefixSlotOff, newPrefixSlot);
lastPrefixSlotNum = prefixSlotNum;
}
int tupleOff = rf.slotManager.decodeSecondSlotField(tupleSlot);
int newTupleSlot = rf.slotManager.encodeSlotFields(prefixSlotNum - (prefixTupleCount - prefixesToRight), tupleOff);
right.putInt(tupleSlotOff, newTupleSlot);
freeSpace += bytesWritten;
}
}
}
// move the modified prefix slots on the right page
int prefixSrc = rf.slotManager.getPrefixSlotEndOff();
int prefixDest = rf.slotManager.getPrefixSlotEndOff() + (prefixTupleCount - prefixesToRight) * rf.slotManager.getSlotSize();
int prefixLength = rf.slotManager.getSlotSize() * prefixesToRight;
System.arraycopy(right.array(), prefixSrc, right.array(), prefixDest, prefixLength);
// on right page we need to copy rightmost tuple slots to left
int src = rf.slotManager.getTupleSlotEndOff();
int dest = rf.slotManager.getTupleSlotEndOff() + tuplesToLeft * rf.slotManager.getSlotSize() + (prefixTupleCount - prefixesToRight) * rf.slotManager.getSlotSize();
int length = rf.slotManager.getSlotSize() * tuplesToRight;
System.arraycopy(right.array(), src, right.array(), dest, length);
right.putInt(ITreeIndexFrame.Constants.TUPLE_COUNT_OFFSET, tuplesToRight);
right.putInt(PREFIX_TUPLE_COUNT_OFFSET, prefixesToRight);
// on left page move slots to reflect possibly removed prefixes
src = slotManager.getTupleSlotEndOff() + tuplesToRight * slotManager.getSlotSize();
dest = slotManager.getTupleSlotEndOff() + tuplesToRight * slotManager.getSlotSize() + (prefixTupleCount - prefixesToLeft) * slotManager.getSlotSize();
length = slotManager.getSlotSize() * tuplesToLeft;
System.arraycopy(buf.array(), src, buf.array(), dest, length);
buf.putInt(ITreeIndexFrame.Constants.TUPLE_COUNT_OFFSET, tuplesToLeft);
buf.putInt(PREFIX_TUPLE_COUNT_OFFSET, prefixesToLeft);
// compact both pages
compact();
rightFrame.compact();
// insert last key
int targetTupleIndex;
// it's safe to catch this exception since it will have been caught before reaching here
targetTupleIndex = ((IBTreeLeafFrame) targetFrame).findInsertTupleIndex(tuple);
targetFrame.insert(tuple, targetTupleIndex);
// set split key to be highest value in left page
frameTuple.resetByTupleIndex(this, getTupleCount() - 1);
int splitKeySize = tupleWriter.bytesRequired(frameTuple, 0, cmp.getKeyFieldCount());
splitKey.initData(splitKeySize);
tupleWriter.writeTupleFields(frameTuple, 0, cmp.getKeyFieldCount(), splitKey.getBuffer().array(), 0);
splitKey.getTuple().resetByTupleOffset(splitKey.getBuffer().array(), 0);
}
use of org.apache.hyracks.storage.am.common.api.ITreeIndexFrame in project asterixdb by apache.
the class VirtualFreePageManager method init.
@Override
public void init(ITreeIndexFrameFactory interiorFrameFactory, ITreeIndexFrameFactory leafFrameFactory) throws HyracksDataException {
currentPageId.set(1);
ICachedPage page = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, 0), true);
page.acquireWriteLatch();
page.releaseWriteLatch(false);
bufferCache.unpin(page);
page = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, currentPageId.get()), true);
if (leafFrameFactory != null) {
page.acquireWriteLatch();
ITreeIndexFrame leafFrame = leafFrameFactory.createFrame();
leafFrame.setPage(page);
leafFrame.initBuffer((byte) 0);
page.releaseWriteLatch(true);
}
bufferCache.unpin(page);
}
Aggregations