private void insertTuple()

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);
            }
        }
    }