in hyracks-fullstack/hyracks/hyracks-storage-am-rtree/src/main/java/org/apache/hyracks/storage/am/rtree/impls/RTree.java [292:451]
private void insertTuple(ICachedPage node, int pageId, ITupleReference tuple, RTreeOpContext ctx, boolean isLeaf)
throws HyracksDataException {
boolean succeeded = false;
FrameOpSpaceStatus spaceStatus;
if (!isLeaf) {
spaceStatus = ctx.getInteriorFrame().hasSpaceInsert(tuple);
} else {
spaceStatus = ctx.getLeafFrame().hasSpaceInsert(tuple);
}
switch (spaceStatus) {
case SUFFICIENT_CONTIGUOUS_SPACE: {
try {
if (!isLeaf) {
ctx.getInteriorFrame().insert(tuple, -1);
} else {
ctx.getModificationCallback().found(null, tuple);
ctx.getLeafFrame().insert(tuple, -1);
}
succeeded = true;
} finally {
if (succeeded) {
ctx.getLSNUpdates().add(node);
ctx.getSplitKey().reset();
} else if (isLeaf) {
// In case of a crash, we un-latch the interior node
// inside updateParentForInsert.
node.releaseWriteLatch(true);
bufferCache.unpin(node);
}
}
break;
}
case SUFFICIENT_SPACE: {
try {
if (!isLeaf) {
ctx.getInteriorFrame().compact();
ctx.getInteriorFrame().insert(tuple, -1);
} else {
ctx.getLeafFrame().compact();
ctx.getModificationCallback().found(null, tuple);
ctx.getLeafFrame().insert(tuple, -1);
}
succeeded = true;
} finally {
if (succeeded) {
ctx.getLSNUpdates().add(node);
ctx.getSplitKey().reset();
} else if (isLeaf) {
// In case of a crash, we un-latch the interior node
// inside updateParentForInsert.
node.releaseWriteLatch(true);
bufferCache.unpin(node);
}
}
break;
}
case INSUFFICIENT_SPACE: {
int rightPageId = freePageManager.takePage(ctx.getMetaFrame());
ICachedPage rightNode =
bufferCache.pin(BufferedFileHandle.getDiskPageId(getFileId(), rightPageId), NEW);
rightNode.acquireWriteLatch();
try {
IRTreeFrame rightFrame;
if (!isLeaf) {
rightFrame = (IRTreeFrame) interiorFrameFactory.createFrame();
rightFrame.setPage(rightNode);
rightFrame.initBuffer(ctx.getInteriorFrame().getLevel());
rightFrame.setRightPage(ctx.getInteriorFrame().getRightPage());
ctx.getInteriorFrame().split(rightFrame, tuple, ctx.getSplitKey(), ctx, bufferCache);
ctx.getInteriorFrame().setRightPage(rightPageId);
} else {
rightFrame = (IRTreeFrame) leafFrameFactory.createFrame();
rightFrame.setPage(rightNode);
rightFrame.initBuffer((byte) 0);
rightFrame.setRightPage(ctx.getInteriorFrame().getRightPage());
ctx.getModificationCallback().found(null, tuple);
ctx.getLeafFrame().split(rightFrame, tuple, ctx.getSplitKey(), ctx, bufferCache);
ctx.getLeafFrame().setRightPage(rightPageId);
}
succeeded = true;
} finally {
if (succeeded) {
ctx.getNSNUpdates().add(rightNode);
ctx.getLSNUpdates().add(rightNode);
ctx.getNSNUpdates().add(node);
ctx.getLSNUpdates().add(node);
} else if (isLeaf) {
// In case of a crash, we un-latch the interior node
// inside updateParentForInsert.
node.releaseWriteLatch(true);
bufferCache.unpin(node);
rightNode.releaseWriteLatch(true);
bufferCache.unpin(rightNode);
} else {
rightNode.releaseWriteLatch(true);
bufferCache.unpin(rightNode);
}
}
ctx.getSplitKey().setPages(pageId, rightPageId);
if (pageId == rootPage) {
int newLeftId = freePageManager.takePage(ctx.getMetaFrame());
ICachedPage newLeftNode =
bufferCache.pin(BufferedFileHandle.getDiskPageId(getFileId(), newLeftId), NEW);
newLeftNode.acquireWriteLatch();
succeeded = false;
try {
// copy left child to new left child
System.arraycopy(node.getBuffer().array(), 0, newLeftNode.getBuffer().array(), 0,
newLeftNode.getBuffer().capacity());
// initialize new root (leftNode becomes new root)
ctx.getInteriorFrame().setPage(node);
ctx.getInteriorFrame().initBuffer((byte) (ctx.getInteriorFrame().getLevel() + 1));
ctx.getSplitKey().setLeftPage(newLeftId);
ctx.getInteriorFrame().insert(ctx.getSplitKey().getLeftTuple(), -1);
ctx.getInteriorFrame().insert(ctx.getSplitKey().getRightTuple(), -1);
succeeded = true;
} finally {
if (succeeded) {
ctx.getNSNUpdates().remove(ctx.getNSNUpdates().size() - 1);
ctx.getLSNUpdates().remove(ctx.getLSNUpdates().size() - 1);
ctx.getNSNUpdates().add(newLeftNode);
ctx.getLSNUpdates().add(newLeftNode);
ctx.getNSNUpdates().add(node);
ctx.getLSNUpdates().add(node);
ctx.getSplitKey().reset();
} else if (isLeaf) {
// In case of a crash, we un-latch the interior node
// inside updateParentForInsert.
node.releaseWriteLatch(true);
bufferCache.unpin(node);
rightNode.releaseWriteLatch(true);
bufferCache.unpin(rightNode);
newLeftNode.releaseWriteLatch(true);
bufferCache.unpin(newLeftNode);
} else {
rightNode.releaseWriteLatch(true);
bufferCache.unpin(rightNode);
newLeftNode.releaseWriteLatch(true);
bufferCache.unpin(newLeftNode);
}
}
}
break;
}
default: {
throw new IllegalStateException("NYI: " + spaceStatus);
}
}
}