use of org.apache.hyracks.storage.am.common.frames.FrameOpSpaceStatus in project asterixdb by apache.
the class RTree method insertTuple.
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(fileId, rightPageId), true);
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(fileId, newLeftId), true);
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);
}
}
}
use of org.apache.hyracks.storage.am.common.frames.FrameOpSpaceStatus in project asterixdb by apache.
the class BTreeNSMLeafFrame method hasSpaceUpdate.
@Override
public FrameOpSpaceStatus hasSpaceUpdate(ITupleReference newTuple, int oldTupleIndex) {
frameTuple.resetByTupleIndex(this, oldTupleIndex);
int oldTupleBytes = frameTuple.getTupleSize();
int newTupleBytes = tupleWriter.bytesRequired(newTuple);
FrameOpSpaceStatus status = hasSpaceUpdate(oldTupleBytes, newTupleBytes);
if (status == FrameOpSpaceStatus.INSUFFICIENT_SPACE && (getLargeFlag() || getTupleCount() == 1) && isLargeTuple(newTupleBytes)) {
return FrameOpSpaceStatus.EXPAND;
}
return status;
}
use of org.apache.hyracks.storage.am.common.frames.FrameOpSpaceStatus in project asterixdb by apache.
the class BTree method updateLeaf.
private boolean updateLeaf(ITupleReference tuple, int oldTupleIndex, int pageId, BTreeOpContext ctx) throws Exception {
FrameOpSpaceStatus spaceStatus = ctx.getLeafFrame().hasSpaceUpdate(tuple, oldTupleIndex);
ITupleReference beforeTuple = ctx.getLeafFrame().getMatchingKeyTuple(tuple, oldTupleIndex);
boolean restartOp = false;
switch(spaceStatus) {
case SUFFICIENT_INPLACE_SPACE:
{
ctx.getModificationCallback().found(beforeTuple, tuple);
ctx.getLeafFrame().update(tuple, oldTupleIndex, true);
ctx.getSplitKey().reset();
break;
}
case EXPAND:
{
// TODO: avoid repeated calculation of tuple size
// TODO: in-place update on expand
// Delete the old tuple, compact the frame, and insert the new tuple.
ctx.getModificationCallback().found(beforeTuple, tuple);
ctx.getLeafFrame().delete(tuple, oldTupleIndex);
ctx.getLeafFrame().compact();
ctx.getLeafFrame().ensureCapacity(bufferCache, tuple, ctx);
int targetTupleIndex = ctx.getLeafFrame().findInsertTupleIndex(tuple);
ctx.getLeafFrame().insert(tuple, targetTupleIndex);
ctx.getSplitKey().reset();
break;
}
case SUFFICIENT_CONTIGUOUS_SPACE:
{
ctx.getModificationCallback().found(beforeTuple, tuple);
ctx.getLeafFrame().update(tuple, oldTupleIndex, false);
ctx.getSplitKey().reset();
break;
}
case SUFFICIENT_SPACE:
{
// Delete the old tuple, compact the frame, and insert the new tuple.
ctx.getModificationCallback().found(beforeTuple, tuple);
ctx.getLeafFrame().delete(tuple, oldTupleIndex);
ctx.getLeafFrame().compact();
int targetTupleIndex = ctx.getLeafFrame().findInsertTupleIndex(tuple);
ctx.getLeafFrame().insert(tuple, targetTupleIndex);
ctx.getSplitKey().reset();
break;
}
case INSUFFICIENT_SPACE:
{
restartOp = performLeafSplit(pageId, tuple, ctx, oldTupleIndex);
break;
}
default:
{
throw new IllegalStateException("NYI: " + spaceStatus);
}
}
return restartOp;
}
use of org.apache.hyracks.storage.am.common.frames.FrameOpSpaceStatus in project asterixdb by apache.
the class BTree method insertLeaf.
private boolean insertLeaf(ITupleReference tuple, int targetTupleIndex, int pageId, BTreeOpContext ctx) throws Exception {
boolean restartOp = false;
FrameOpSpaceStatus spaceStatus = ctx.getLeafFrame().hasSpaceInsert(tuple);
switch(spaceStatus) {
case EXPAND:
{
// TODO: avoid repeated calculation of tuple size
ctx.getLeafFrame().ensureCapacity(bufferCache, tuple, ctx);
}
// fall-through
case SUFFICIENT_CONTIGUOUS_SPACE:
{
ctx.getModificationCallback().found(null, tuple);
ctx.getLeafFrame().insert(tuple, targetTupleIndex);
ctx.getSplitKey().reset();
break;
}
case SUFFICIENT_SPACE:
{
int finalIndex = ctx.getLeafFrame().compact() ? ctx.getLeafFrame().findInsertTupleIndex(tuple) : targetTupleIndex;
ctx.getModificationCallback().found(null, tuple);
ctx.getLeafFrame().insert(tuple, finalIndex);
ctx.getSplitKey().reset();
break;
}
case INSUFFICIENT_SPACE:
{
// Try compressing the page first and see if there is space available.
if (ctx.getLeafFrame().compress() && ctx.getLeafFrame().hasSpaceInsert(tuple) == FrameOpSpaceStatus.SUFFICIENT_CONTIGUOUS_SPACE) {
ctx.getModificationCallback().found(null, tuple);
ctx.getLeafFrame().insert(tuple, ctx.getLeafFrame().findInsertTupleIndex(tuple));
ctx.getSplitKey().reset();
} else {
restartOp = performLeafSplit(pageId, tuple, ctx, -1);
}
break;
}
default:
{
throw new IllegalStateException("NYI: " + spaceStatus);
}
}
return restartOp;
}
use of org.apache.hyracks.storage.am.common.frames.FrameOpSpaceStatus in project asterixdb by apache.
the class BTree method insertInterior.
private void insertInterior(ICachedPage node, int pageId, ITupleReference tuple, BTreeOpContext ctx) throws Exception {
ctx.getInteriorFrame().setPage(node);
int targetTupleIndex = ctx.getInteriorFrame().findInsertTupleIndex(tuple);
FrameOpSpaceStatus spaceStatus = ctx.getInteriorFrame().hasSpaceInsert(tuple);
switch(spaceStatus) {
case INSUFFICIENT_SPACE:
{
int rightPageId = freePageManager.takePage(ctx.getMetaFrame());
ICachedPage rightNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, rightPageId), true);
rightNode.acquireWriteLatch();
try {
IBTreeFrame rightFrame = ctx.createInteriorFrame();
rightFrame.setPage(rightNode);
rightFrame.initBuffer(ctx.getInteriorFrame().getLevel());
rightFrame.setMultiComparator(ctx.getCmp());
// instead of creating a new split key, use the existing
// splitKey
ctx.getInteriorFrame().split(rightFrame, ctx.getSplitKey().getTuple(), ctx.getSplitKey(), ctx, bufferCache);
ctx.getSmPages().add(pageId);
ctx.getSmPages().add(rightPageId);
ctx.getInteriorFrame().setSmFlag(true);
rightFrame.setSmFlag(true);
rightFrame.setPageLsn(rightFrame.getPageLsn() + 1);
ctx.getInteriorFrame().setPageLsn(ctx.getInteriorFrame().getPageLsn() + 1);
ctx.getSplitKey().setPages(pageId, rightPageId);
} finally {
rightNode.releaseWriteLatch(true);
bufferCache.unpin(rightNode);
}
break;
}
case SUFFICIENT_CONTIGUOUS_SPACE:
{
ctx.getInteriorFrame().insert(tuple, targetTupleIndex);
ctx.getSplitKey().reset();
break;
}
case SUFFICIENT_SPACE:
{
boolean slotsChanged = ctx.getInteriorFrame().compact();
if (slotsChanged) {
targetTupleIndex = ctx.getInteriorFrame().findInsertTupleIndex(tuple);
}
ctx.getInteriorFrame().insert(tuple, targetTupleIndex);
ctx.getSplitKey().reset();
break;
}
case TOO_LARGE:
{
int tupleSize = ctx.getInteriorFrame().getBytesRequiredToWriteTuple(tuple);
throw HyracksDataException.create(ErrorCode.RECORD_IS_TOO_LARGE, tupleSize, maxTupleSize);
}
default:
{
throw new IllegalStateException("NYI: " + spaceStatus);
}
}
}
Aggregations