Search in sources :

Example 1 with IRTreeFrame

use of org.apache.hyracks.storage.am.rtree.api.IRTreeFrame in project asterixdb by apache.

the class RStarTreePolicy method split.

@Override
public void split(ITreeIndexFrame leftFrame, ByteBuffer buf, ITreeIndexFrame rightFrame, ISlotManager slotManager, ITreeIndexTupleReference frameTuple, ITupleReference tuple, ISplitKey splitKey) throws HyracksDataException {
    RTreeSplitKey rTreeSplitKey = ((RTreeSplitKey) splitKey);
    RTreeTypeAwareTupleWriter rTreeTupleWriterleftRTreeFrame = ((RTreeTypeAwareTupleWriter) tupleWriter);
    RTreeTypeAwareTupleWriter rTreeTupleWriterRightFrame = ((RTreeTypeAwareTupleWriter) rightFrame.getTupleWriter());
    RTreeNSMFrame leftRTreeFrame = ((RTreeNSMFrame) leftFrame);
    // calculations are based on the R*-tree paper
    int m = (int) Math.floor((leftRTreeFrame.getTupleCount() + 1) * splitFactor);
    int splitDistribution = leftRTreeFrame.getTupleCount() - (2 * m) + 2;
    // to calculate the minimum margin in order to pick the split axis
    double minMargin = Double.MAX_VALUE;
    int splitAxis = 0, sortOrder = 0;
    int maxFieldPos = keyValueProviders.length / 2;
    for (int i = 0; i < maxFieldPos; i++) {
        int j = maxFieldPos + i;
        for (int k = 0; k < leftRTreeFrame.getTupleCount(); ++k) {
            frameTuple.resetByTupleIndex(leftRTreeFrame, k);
            double LowerKey = keyValueProviders[i].getValue(frameTuple.getFieldData(i), frameTuple.getFieldStart(i));
            double UpperKey = keyValueProviders[j].getValue(frameTuple.getFieldData(j), frameTuple.getFieldStart(j));
            tupleEntries1.add(k, LowerKey);
            tupleEntries2.add(k, UpperKey);
        }
        double LowerKey = keyValueProviders[i].getValue(tuple.getFieldData(i), tuple.getFieldStart(i));
        double UpperKey = keyValueProviders[j].getValue(tuple.getFieldData(j), tuple.getFieldStart(j));
        tupleEntries1.add(-1, LowerKey);
        tupleEntries2.add(-1, UpperKey);
        tupleEntries1.sort(EntriesOrder.ASCENDING, leftRTreeFrame.getTupleCount() + 1);
        tupleEntries2.sort(EntriesOrder.ASCENDING, leftRTreeFrame.getTupleCount() + 1);
        double lowerMargin = 0.0, upperMargin = 0.0;
        // generate distribution
        for (int k = 1; k <= splitDistribution; ++k) {
            int d = m - 1 + k;
            generateDist(leftRTreeFrame, frameTuple, tuple, tupleEntries1, rec[0], 0, d);
            generateDist(leftRTreeFrame, frameTuple, tuple, tupleEntries2, rec[1], 0, d);
            generateDist(leftRTreeFrame, frameTuple, tuple, tupleEntries1, rec[2], d, leftRTreeFrame.getTupleCount() + 1);
            generateDist(leftRTreeFrame, frameTuple, tuple, tupleEntries2, rec[3], d, leftRTreeFrame.getTupleCount() + 1);
            // calculate the margin of the distributions
            lowerMargin += rec[0].margin() + rec[2].margin();
            upperMargin += rec[1].margin() + rec[3].margin();
        }
        double margin = Math.min(lowerMargin, upperMargin);
        // store minimum margin as split axis
        if (margin < minMargin) {
            minMargin = margin;
            splitAxis = i;
            sortOrder = (lowerMargin < upperMargin) ? 0 : 2;
        }
        tupleEntries1.clear();
        tupleEntries2.clear();
    }
    for (int i = 0; i < leftRTreeFrame.getTupleCount(); ++i) {
        frameTuple.resetByTupleIndex(leftRTreeFrame, i);
        double key = keyValueProviders[splitAxis + sortOrder].getValue(frameTuple.getFieldData(splitAxis + sortOrder), frameTuple.getFieldStart(splitAxis + sortOrder));
        tupleEntries1.add(i, key);
    }
    double key = keyValueProviders[splitAxis + sortOrder].getValue(tuple.getFieldData(splitAxis + sortOrder), tuple.getFieldStart(splitAxis + sortOrder));
    tupleEntries1.add(-1, key);
    tupleEntries1.sort(EntriesOrder.ASCENDING, leftRTreeFrame.getTupleCount() + 1);
    double minArea = Double.MAX_VALUE;
    double minOverlap = Double.MAX_VALUE;
    int splitPoint = 0;
    for (int i = 1; i <= splitDistribution; ++i) {
        int d = m - 1 + i;
        generateDist(leftRTreeFrame, frameTuple, tuple, tupleEntries1, rec[0], 0, d);
        generateDist(leftRTreeFrame, frameTuple, tuple, tupleEntries1, rec[2], d, leftRTreeFrame.getTupleCount() + 1);
        double overlap = rec[0].overlappedArea(rec[2]);
        if (overlap < minOverlap) {
            splitPoint = d;
            minOverlap = overlap;
            minArea = rec[0].area() + rec[2].area();
        } else if (overlap == minOverlap) {
            double area = rec[0].area() + rec[2].area();
            if (area < minArea) {
                splitPoint = d;
                minArea = area;
            }
        }
    }
    int startIndex, endIndex;
    if (splitPoint < (leftRTreeFrame.getTupleCount() + 1) / 2) {
        startIndex = 0;
        endIndex = splitPoint;
    } else {
        startIndex = splitPoint;
        endIndex = (leftRTreeFrame.getTupleCount() + 1);
    }
    boolean insertedNewTupleInRightFrame = false;
    int totalBytes = 0, numOfDeletedTuples = 0;
    for (int i = startIndex; i < endIndex; i++) {
        if (tupleEntries1.get(i).getTupleIndex() != -1) {
            frameTuple.resetByTupleIndex(leftRTreeFrame, tupleEntries1.get(i).getTupleIndex());
            rightFrame.insert(frameTuple, -1);
            ((UnorderedSlotManager) slotManager).modifySlot(slotManager.getSlotOff(tupleEntries1.get(i).getTupleIndex()), -1);
            totalBytes += leftRTreeFrame.getTupleSize(frameTuple);
            numOfDeletedTuples++;
        } else {
            insertedNewTupleInRightFrame = true;
        }
    }
    ((UnorderedSlotManager) slotManager).deleteEmptySlots();
    // maintain space information
    buf.putInt(totalFreeSpaceOff, buf.getInt(totalFreeSpaceOff) + totalBytes + (slotManager.getSlotSize() * numOfDeletedTuples));
    // compact both pages
    rightFrame.compact();
    leftRTreeFrame.compact();
    // size, thus it must fit in either pages.
    if (insertedNewTupleInRightFrame) {
        if (rightFrame.hasSpaceInsert(tuple) == FrameOpSpaceStatus.SUFFICIENT_CONTIGUOUS_SPACE) {
            rightFrame.insert(tuple, -1);
        } else {
            leftRTreeFrame.insert(tuple, -1);
        }
    } else if (leftRTreeFrame.hasSpaceInsert(tuple) == FrameOpSpaceStatus.SUFFICIENT_CONTIGUOUS_SPACE) {
        leftRTreeFrame.insert(tuple, -1);
    } else {
        rightFrame.insert(tuple, -1);
    }
    int tupleOff = slotManager.getTupleOff(slotManager.getSlotEndOff());
    frameTuple.resetByTupleOffset(buf.array(), tupleOff);
    int splitKeySize = tupleWriter.bytesRequired(frameTuple, 0, keyValueProviders.length);
    splitKey.initData(splitKeySize);
    leftRTreeFrame.adjustMBR();
    rTreeTupleWriterleftRTreeFrame.writeTupleFields(leftRTreeFrame.getMBRTuples(), 0, rTreeSplitKey.getLeftPageBuffer(), 0);
    rTreeSplitKey.getLeftTuple().resetByTupleOffset(rTreeSplitKey.getLeftPageBuffer().array(), 0);
    ((IRTreeFrame) rightFrame).adjustMBR();
    rTreeTupleWriterRightFrame.writeTupleFields(((RTreeNSMFrame) rightFrame).getMBRTuples(), 0, rTreeSplitKey.getRightPageBuffer(), 0);
    rTreeSplitKey.getRightTuple().resetByTupleOffset(rTreeSplitKey.getRightPageBuffer().array(), 0);
    tupleEntries1.clear();
    tupleEntries2.clear();
}
Also used : IRTreeFrame(org.apache.hyracks.storage.am.rtree.api.IRTreeFrame) RTreeSplitKey(org.apache.hyracks.storage.am.rtree.impls.RTreeSplitKey) RTreeTypeAwareTupleWriter(org.apache.hyracks.storage.am.rtree.tuples.RTreeTypeAwareTupleWriter) UnorderedSlotManager(org.apache.hyracks.storage.am.rtree.impls.UnorderedSlotManager)

Example 2 with IRTreeFrame

use of org.apache.hyracks.storage.am.rtree.api.IRTreeFrame in project asterixdb by apache.

the class RTreePolicy method split.

@Override
public void split(ITreeIndexFrame leftFrame, ByteBuffer buf, ITreeIndexFrame rightFrame, ISlotManager slotManager, ITreeIndexTupleReference frameTuple, ITupleReference tuple, ISplitKey splitKey) throws HyracksDataException {
    RTreeSplitKey rTreeSplitKey = ((RTreeSplitKey) splitKey);
    RTreeTypeAwareTupleWriter rTreeTupleWriterLeftFrame = ((RTreeTypeAwareTupleWriter) tupleWriter);
    RTreeTypeAwareTupleWriter rTreeTupleWriterRightFrame = ((RTreeTypeAwareTupleWriter) rightFrame.getTupleWriter());
    RTreeNSMFrame leftRTreeFrame = ((RTreeNSMFrame) leftFrame);
    double separation = Double.NEGATIVE_INFINITY;
    int seed1 = 0, seed2 = 0;
    int maxFieldPos = keyValueProviders.length / 2;
    for (int i = 0; i < maxFieldPos; i++) {
        int j = maxFieldPos + i;
        frameTuple.resetByTupleIndex(leftRTreeFrame, 0);
        double leastLowerValue = keyValueProviders[i].getValue(frameTuple.getFieldData(i), frameTuple.getFieldStart(i));
        double greatestUpperValue = keyValueProviders[j].getValue(frameTuple.getFieldData(j), frameTuple.getFieldStart(j));
        double leastUpperValue = leastLowerValue;
        double greatestLowerValue = greatestUpperValue;
        int leastUpperIndex = 0;
        int greatestLowerIndex = 0;
        double width;
        int tupleCount = leftRTreeFrame.getTupleCount();
        for (int k = 1; k < tupleCount; ++k) {
            frameTuple.resetByTupleIndex(leftRTreeFrame, k);
            double lowerValue = keyValueProviders[i].getValue(frameTuple.getFieldData(i), frameTuple.getFieldStart(i));
            if (lowerValue > greatestLowerValue) {
                greatestLowerIndex = k;
                cmpFrameTuple.resetByTupleIndex(leftRTreeFrame, k);
                greatestLowerValue = keyValueProviders[i].getValue(cmpFrameTuple.getFieldData(i), cmpFrameTuple.getFieldStart(i));
            }
            double higherValue = keyValueProviders[j].getValue(frameTuple.getFieldData(j), frameTuple.getFieldStart(j));
            if (higherValue < leastUpperValue) {
                leastUpperIndex = k;
                cmpFrameTuple.resetByTupleIndex(leftRTreeFrame, k);
                leastUpperValue = keyValueProviders[j].getValue(cmpFrameTuple.getFieldData(j), cmpFrameTuple.getFieldStart(j));
            }
            leastLowerValue = Math.min(lowerValue, leastLowerValue);
            greatestUpperValue = Math.max(higherValue, greatestUpperValue);
        }
        width = greatestUpperValue - leastLowerValue;
        if (width <= 0) {
            width = 1;
        }
        double f = (greatestLowerValue - leastUpperValue) / width;
        if (f > separation) {
            seed1 = leastUpperIndex;
            seed2 = greatestLowerIndex;
            separation = f;
        }
    }
    if (seed1 == seed2) {
        if (seed1 == 0) {
            seed2 = 1;
        } else {
            --seed2;
        }
    }
    int totalBytes = 0, numOfDeletedTuples = 0;
    frameTuple.resetByTupleIndex(leftRTreeFrame, seed1);
    rec[0].set(frameTuple, keyValueProviders);
    rightFrame.insert(frameTuple, -1);
    ((UnorderedSlotManager) slotManager).modifySlot(slotManager.getSlotOff(seed1), -1);
    totalBytes += leftRTreeFrame.getTupleSize(frameTuple);
    numOfDeletedTuples++;
    frameTuple.resetByTupleIndex(leftRTreeFrame, seed2);
    rec[1].set(frameTuple, keyValueProviders);
    int remainingTuplestoBeInsertedInRightFrame;
    for (int k = 0; k < leftRTreeFrame.getTupleCount(); ++k) {
        remainingTuplestoBeInsertedInRightFrame = leftRTreeFrame.getTupleCount() / 2 - rightFrame.getTupleCount();
        if (remainingTuplestoBeInsertedInRightFrame == 0) {
            break;
        }
        if (k != seed1 && k != seed2) {
            frameTuple.resetByTupleIndex(leftRTreeFrame, k);
            if (rec[0].enlargedArea(frameTuple, keyValueProviders) < rec[1].enlargedArea(frameTuple, keyValueProviders) || leftRTreeFrame.getTupleCount() - k <= remainingTuplestoBeInsertedInRightFrame) {
                rightFrame.insert(frameTuple, -1);
                rec[0].enlarge(frameTuple, keyValueProviders);
                ((UnorderedSlotManager) slotManager).modifySlot(slotManager.getSlotOff(k), -1);
                totalBytes += leftRTreeFrame.getTupleSize(frameTuple);
                numOfDeletedTuples++;
            } else {
                rec[1].enlarge(frameTuple, keyValueProviders);
            }
        }
    }
    ((UnorderedSlotManager) slotManager).deleteEmptySlots();
    // maintain space information
    buf.putInt(totalFreeSpaceOff, buf.getInt(totalFreeSpaceOff) + totalBytes + (slotManager.getSlotSize() * numOfDeletedTuples));
    // compact both pages
    rightFrame.compact();
    leftRTreeFrame.compact();
    // size, thus it must fit in either pages.
    if (rec[0].enlargedArea(tuple, keyValueProviders) < rec[1].enlargedArea(tuple, keyValueProviders)) {
        if (rightFrame.hasSpaceInsert(tuple) == FrameOpSpaceStatus.SUFFICIENT_CONTIGUOUS_SPACE) {
            rightFrame.insert(tuple, -1);
        } else {
            leftRTreeFrame.insert(tuple, -1);
        }
    } else if (leftRTreeFrame.hasSpaceInsert(tuple) == FrameOpSpaceStatus.SUFFICIENT_CONTIGUOUS_SPACE) {
        leftRTreeFrame.insert(tuple, -1);
    } else {
        rightFrame.insert(tuple, -1);
    }
    int tupleOff = slotManager.getTupleOff(slotManager.getSlotEndOff());
    frameTuple.resetByTupleOffset(buf.array(), tupleOff);
    int splitKeySize = tupleWriter.bytesRequired(frameTuple, 0, keyValueProviders.length);
    splitKey.initData(splitKeySize);
    leftRTreeFrame.adjustMBR();
    rTreeTupleWriterLeftFrame.writeTupleFields(leftRTreeFrame.getMBRTuples(), 0, rTreeSplitKey.getLeftPageBuffer(), 0);
    rTreeSplitKey.getLeftTuple().resetByTupleOffset(rTreeSplitKey.getLeftPageBuffer().array(), 0);
    ((IRTreeFrame) rightFrame).adjustMBR();
    rTreeTupleWriterRightFrame.writeTupleFields(((RTreeNSMFrame) rightFrame).getMBRTuples(), 0, rTreeSplitKey.getRightPageBuffer(), 0);
    rTreeSplitKey.getRightTuple().resetByTupleOffset(rTreeSplitKey.getRightPageBuffer().array(), 0);
}
Also used : IRTreeFrame(org.apache.hyracks.storage.am.rtree.api.IRTreeFrame) RTreeSplitKey(org.apache.hyracks.storage.am.rtree.impls.RTreeSplitKey) RTreeTypeAwareTupleWriter(org.apache.hyracks.storage.am.rtree.tuples.RTreeTypeAwareTupleWriter) UnorderedSlotManager(org.apache.hyracks.storage.am.rtree.impls.UnorderedSlotManager)

Example 3 with IRTreeFrame

use of org.apache.hyracks.storage.am.rtree.api.IRTreeFrame 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);
            }
    }
}
Also used : ICachedPage(org.apache.hyracks.storage.common.buffercache.ICachedPage) IRTreeFrame(org.apache.hyracks.storage.am.rtree.api.IRTreeFrame) FrameOpSpaceStatus(org.apache.hyracks.storage.am.common.frames.FrameOpSpaceStatus)

Aggregations

IRTreeFrame (org.apache.hyracks.storage.am.rtree.api.IRTreeFrame)3 RTreeSplitKey (org.apache.hyracks.storage.am.rtree.impls.RTreeSplitKey)2 UnorderedSlotManager (org.apache.hyracks.storage.am.rtree.impls.UnorderedSlotManager)2 RTreeTypeAwareTupleWriter (org.apache.hyracks.storage.am.rtree.tuples.RTreeTypeAwareTupleWriter)2 FrameOpSpaceStatus (org.apache.hyracks.storage.am.common.frames.FrameOpSpaceStatus)1 ICachedPage (org.apache.hyracks.storage.common.buffercache.ICachedPage)1