Search in sources :

Example 6 with ICachedPage

use of org.apache.hyracks.storage.common.buffercache.ICachedPage in project asterixdb by apache.

the class BloomFilter method contains.

public boolean contains(ITupleReference tuple, long[] hashes) throws HyracksDataException {
    if (numPages == 0) {
        return false;
    }
    MurmurHash128Bit.hash3_x64_128(tuple, keyFields, SEED, hashes);
    for (int i = 0; i < numHashes; ++i) {
        long hash = Math.abs((hashes[0] + i * hashes[1]) % numBits);
        // we increment the page id by one, since the metadata page id of the filter is 0.
        ICachedPage page = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, (int) (hash / numBitsPerPage) + 1), false);
        page.acquireReadLatch();
        try {
            ByteBuffer buffer = page.getBuffer();
            // divide by 8
            int byteIndex = (int) (hash % numBitsPerPage) >> 3;
            byte b = buffer.get(byteIndex);
            // mod 8
            int bitIndex = (int) (hash % numBitsPerPage) & 0x07;
            if (!((b & (1L << bitIndex)) != 0)) {
                return false;
            }
        } finally {
            page.releaseReadLatch();
            bufferCache.unpin(page);
        }
    }
    return true;
}
Also used : ICachedPage(org.apache.hyracks.storage.common.buffercache.ICachedPage) ByteBuffer(java.nio.ByteBuffer)

Example 7 with ICachedPage

use of org.apache.hyracks.storage.common.buffercache.ICachedPage in project asterixdb by apache.

the class BTree method performOp.

private void performOp(int pageId, ICachedPage parent, boolean parentIsReadLatched, BTreeOpContext ctx) throws HyracksDataException {
    ICachedPage node = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, pageId), false);
    ctx.getInteriorFrame().setPage(node);
    // this check performs an unprotected read in the page
    // the following could happen: TODO fill out
    boolean unsafeIsLeaf = ctx.getInteriorFrame().isLeaf();
    boolean isReadLatched = acquireLatch(node, ctx, unsafeIsLeaf);
    boolean smFlag = ctx.getInteriorFrame().getSmFlag();
    // re-check leafness after latching
    boolean isLeaf = ctx.getInteriorFrame().isLeaf();
    // remember trail of pageLsns, to unwind recursion in case of an ongoing
    // structure modification
    ctx.getPageLsns().add(ctx.getInteriorFrame().getPageLsn());
    try {
        // Latch coupling: unlatch parent.
        if (parent != null) {
            if (parentIsReadLatched) {
                parent.releaseReadLatch();
            } else {
                parent.releaseWriteLatch(true);
            }
            bufferCache.unpin(parent);
        }
        if (!isLeaf || smFlag) {
            if (!smFlag) {
                // We use this loop to deal with possibly multiple operation
                // restarts due to ongoing structure modifications during
                // the descent.
                boolean repeatOp = true;
                while (repeatOp && ctx.getOpRestarts() < MAX_RESTARTS) {
                    int childPageId = ctx.getInteriorFrame().getChildPageId(ctx.getPred());
                    performOp(childPageId, node, isReadLatched, ctx);
                    node = null;
                    if (!ctx.getPageLsns().isEmpty()) {
                        if (ctx.getPageLsns().getLast() == FULL_RESTART_OP) {
                            break;
                        } else if (ctx.getPageLsns().getLast() == RESTART_OP) {
                            // Pop the restart op indicator.
                            ctx.getPageLsns().removeLast();
                            node = isConsistent(pageId, ctx);
                            if (node != null) {
                                isReadLatched = true;
                                // Descend the tree again.
                                continue;
                            } else {
                                // Pop pageLsn of this page (version seen by this op during descent).
                                ctx.getPageLsns().removeLast();
                                // This node is not consistent set the restart indicator for upper level.
                                ctx.getPageLsns().add(RESTART_OP);
                                break;
                            }
                        }
                    }
                    switch(ctx.getOperation()) {
                        case INSERT:
                        case UPSERT:
                        case UPDATE:
                            {
                                // Is there a propagated split key?
                                if (ctx.getSplitKey().getBuffer() != null) {
                                    ICachedPage interiorNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, pageId), false);
                                    interiorNode.acquireWriteLatch();
                                    try {
                                        // Insert or update op. Both can cause split keys to propagate upwards.
                                        insertInterior(interiorNode, pageId, ctx.getSplitKey().getTuple(), ctx);
                                    } finally {
                                        interiorNode.releaseWriteLatch(true);
                                        bufferCache.unpin(interiorNode);
                                    }
                                } else {
                                    unsetSmPages(ctx);
                                }
                                break;
                            }
                        case DELETE:
                            {
                                if (ctx.getSplitKey().getBuffer() != null) {
                                    throw new HyracksDataException("Split key was propagated during delete. Delete allows empty leaf pages.");
                                }
                                break;
                            }
                        default:
                            {
                                // Do nothing for Search and DiskOrderScan.
                                break;
                            }
                    }
                    // Operation completed.
                    repeatOp = false;
                }
            // end while
            } else {
                // smFlag
                ctx.setOpRestarts(ctx.getOpRestarts() + 1);
                if (isReadLatched) {
                    node.releaseReadLatch();
                } else {
                    node.releaseWriteLatch(true);
                }
                bufferCache.unpin(node);
                // TODO: this should be an instant duration lock, how to do
                // this in java?
                // instead we just immediately release the lock. this is
                // inefficient but still correct and will not cause
                // latch-deadlock
                treeLatch.readLock().lock();
                treeLatch.readLock().unlock();
                // unwind recursion and restart operation, find lowest page
                // with a pageLsn as seen by this operation during descent
                // pop current page lsn
                ctx.getPageLsns().removeLast();
                // put special value on the stack to inform caller of
                // restart
                ctx.getPageLsns().add(RESTART_OP);
            }
        } else {
            // isLeaf and !smFlag
            // We may have to restart an op to avoid latch deadlock.
            boolean restartOp = false;
            ctx.getLeafFrame().setPage(node);
            switch(ctx.getOperation()) {
                case INSERT:
                    {
                        int targetTupleIndex = ctx.getLeafFrame().findInsertTupleIndex(ctx.getPred().getLowKey());
                        restartOp = insertLeaf(ctx.getPred().getLowKey(), targetTupleIndex, pageId, ctx);
                        break;
                    }
                case UPSERT:
                    {
                        int targetTupleIndex = ctx.getLeafFrame().findUpsertTupleIndex(ctx.getPred().getLowKey());
                        restartOp = upsertLeaf(ctx.getPred().getLowKey(), targetTupleIndex, pageId, ctx);
                        break;
                    }
                case UPDATE:
                    {
                        int oldTupleIndex = ctx.getLeafFrame().findUpdateTupleIndex(ctx.getPred().getLowKey());
                        restartOp = updateLeaf(ctx.getPred().getLowKey(), oldTupleIndex, pageId, ctx);
                        break;
                    }
                case DELETE:
                    {
                        restartOp = deleteLeaf(node, pageId, ctx.getPred().getLowKey(), ctx);
                        break;
                    }
                case SEARCH:
                    {
                        ctx.getCursorInitialState().setSearchOperationCallback(ctx.getSearchCallback());
                        ctx.getCursorInitialState().setOriginialKeyComparator(ctx.getCmp());
                        ctx.getCursorInitialState().setPage(node);
                        ctx.getCursorInitialState().setPageId(pageId);
                        ctx.getCursor().open(ctx.getCursorInitialState(), ctx.getPred());
                        break;
                    }
            }
            if (ctx.getOperation() != IndexOperation.SEARCH) {
                node.releaseWriteLatch(true);
                bufferCache.unpin(node);
            }
            if (restartOp) {
                // Wait for the SMO to persistFrontiers before restarting.
                treeLatch.readLock().lock();
                treeLatch.readLock().unlock();
                ctx.getPageLsns().removeLast();
                ctx.getPageLsns().add(FULL_RESTART_OP);
            }
        }
    } catch (HyracksDataException e) {
        if (!ctx.isExceptionHandled()) {
            if (node != null) {
                if (isReadLatched) {
                    node.releaseReadLatch();
                } else {
                    node.releaseWriteLatch(true);
                }
                bufferCache.unpin(node);
                ctx.setExceptionHandled(true);
            }
        }
        throw e;
    } catch (Exception e) {
        if (node != null) {
            if (isReadLatched) {
                node.releaseReadLatch();
            } else {
                node.releaseWriteLatch(true);
            }
            bufferCache.unpin(node);
        }
        HyracksDataException wrappedException = HyracksDataException.create(e);
        ctx.setExceptionHandled(true);
        throw wrappedException;
    }
}
Also used : ICachedPage(org.apache.hyracks.storage.common.buffercache.ICachedPage) HyracksDataException(org.apache.hyracks.api.exceptions.HyracksDataException) HyracksDataException(org.apache.hyracks.api.exceptions.HyracksDataException)

Example 8 with ICachedPage

use of org.apache.hyracks.storage.common.buffercache.ICachedPage in project asterixdb by apache.

the class BTree method validate.

private void validate(BTreeOpContext ctx, int pageId) throws HyracksDataException {
    ICachedPage page = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, pageId), false);
    ctx.getInteriorFrame().setPage(page);
    PageValidationInfo currentPvi = ctx.getValidationInfos().peekFirst();
    boolean isLeaf = ctx.getInteriorFrame().isLeaf();
    if (isLeaf) {
        ctx.getLeafFrame().setPage(page);
        ctx.getLeafFrame().validate(currentPvi);
    } else {
        PageValidationInfo nextPvi = ctx.createPageValidationInfo(currentPvi);
        List<Integer> children = ((BTreeNSMInteriorFrame) ctx.getInteriorFrame()).getChildren(ctx.getCmp());
        ctx.getInteriorFrame().validate(currentPvi);
        for (int i = 0; i < children.size(); i++) {
            ctx.getInteriorFrame().setPage(page);
            if (children.size() == 1) {
                // There is a single child pointer with no keys, so propagate both low and high ranges
                nextPvi.propagateLowRangeKey(currentPvi);
                nextPvi.propagateHighRangeKey(currentPvi);
            } else if (i == 0) {
                // There is more than one child pointer and this is the left-most child pointer, so:
                //      1) propagate the low range key from the parent
                //      2) adjust the high range key
                nextPvi.propagateLowRangeKey(currentPvi);
                ctx.getInteriorFrameTuple().resetByTupleIndex(ctx.getInteriorFrame(), i);
                nextPvi.adjustHighRangeKey(ctx.getInteriorFrameTuple());
            } else if (i == children.size() - 1) {
                // There is more than one child pointer and this is the right-most child pointer, so:
                //      1) propagate the high range key from the parent
                //      2) adjust the low range key
                nextPvi.propagateHighRangeKey(currentPvi);
                ctx.getInteriorFrameTuple().resetByTupleIndex(ctx.getInteriorFrame(), i - 1);
                nextPvi.adjustLowRangeKey(ctx.getInteriorFrameTuple());
            } else {
                // There is more than one child pointer and this pointer is not the left/right-most pointer, so:
                //      1) adjust the low range key
                //      2) adjust the high range key
                ctx.getInteriorFrameTuple().resetByTupleIndex(ctx.getInteriorFrame(), i - 1);
                nextPvi.adjustLowRangeKey(ctx.getInteriorFrameTuple());
                ctx.getInteriorFrameTuple().resetByTupleIndex(ctx.getInteriorFrame(), i);
                nextPvi.adjustHighRangeKey(ctx.getInteriorFrameTuple());
            }
            ctx.getValidationInfos().addFirst(nextPvi);
            validate(ctx, children.get(i));
        }
    }
    bufferCache.unpin(page);
    ctx.getValidationInfos().removeFirst();
}
Also used : ICachedPage(org.apache.hyracks.storage.common.buffercache.ICachedPage) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) BTreeNSMInteriorFrame(org.apache.hyracks.storage.am.btree.frames.BTreeNSMInteriorFrame) PageValidationInfo(org.apache.hyracks.storage.am.btree.impls.BTreeOpContext.PageValidationInfo)

Example 9 with ICachedPage

use of org.apache.hyracks.storage.common.buffercache.ICachedPage in project asterixdb by apache.

the class BTree method createNewRoot.

private void createNewRoot(BTreeOpContext ctx) throws HyracksDataException {
    // Make sure the root is always in the same page.
    ICachedPage leftNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, ctx.getSplitKey().getLeftPage()), false);
    leftNode.acquireWriteLatch();
    try {
        int newLeftId = freePageManager.takePage(ctx.getMetaFrame());
        ICachedPage newLeftNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, newLeftId), true);
        newLeftNode.acquireWriteLatch();
        try {
            boolean largePage = false;
            if (leftNode.getBuffer().capacity() > newLeftNode.getBuffer().capacity()) {
                bufferCache.resizePage(newLeftNode, leftNode.getBuffer().capacity() / bufferCache.getPageSize(), ctx);
                largePage = true;
            }
            // Copy left child to new left child.
            System.arraycopy(leftNode.getBuffer().array(), 0, newLeftNode.getBuffer().array(), 0, newLeftNode.getBuffer().capacity());
            ctx.getInteriorFrame().setPage(newLeftNode);
            ctx.getInteriorFrame().setSmFlag(false);
            // Remember LSN to set it in the root.
            long leftNodeLSN = ctx.getInteriorFrame().getPageLsn();
            // Initialize new root (leftNode becomes new root).
            if (largePage) {
                bufferCache.resizePage(leftNode, 1, ctx);
                ctx.getInteriorFrame().setPage(leftNode);
                ctx.getInteriorFrame().setLargeFlag(false);
            } else {
                ctx.getInteriorFrame().setPage(leftNode);
                ctx.getInteriorFrame().setLargeFlag(false);
            }
            ctx.getInteriorFrame().initBuffer((byte) (ctx.getInteriorFrame().getLevel() + 1));
            // Copy over LSN.
            ctx.getInteriorFrame().setPageLsn(leftNodeLSN);
            // Will be cleared later in unsetSmPages.
            ctx.getInteriorFrame().setSmFlag(true);
            ctx.getSplitKey().setLeftPage(newLeftId);
            int targetTupleIndex = ctx.getInteriorFrame().findInsertTupleIndex(ctx.getSplitKey().getTuple());
            int tupleSize = ctx.getInteriorFrame().getBytesRequiredToWriteTuple(ctx.getSplitKey().getTuple());
            if (tupleSize > maxTupleSize) {
                throw HyracksDataException.create(ErrorCode.RECORD_IS_TOO_LARGE, tupleSize, maxTupleSize);
            }
            ctx.getInteriorFrame().insert(ctx.getSplitKey().getTuple(), targetTupleIndex);
        } finally {
            newLeftNode.releaseWriteLatch(true);
            bufferCache.unpin(newLeftNode);
        }
    } finally {
        leftNode.releaseWriteLatch(true);
        bufferCache.unpin(leftNode);
    }
}
Also used : ICachedPage(org.apache.hyracks.storage.common.buffercache.ICachedPage)

Example 10 with ICachedPage

use of org.apache.hyracks.storage.common.buffercache.ICachedPage in project asterixdb by apache.

the class BTreeCountingSearchCursor method fetchNextLeafPage.

private void fetchNextLeafPage(int nextLeafPage) throws HyracksDataException {
    do {
        ICachedPage nextLeaf = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, nextLeafPage), false);
        if (exclusiveLatchNodes) {
            nextLeaf.acquireWriteLatch();
            page.releaseWriteLatch(isPageDirty);
        } else {
            nextLeaf.acquireReadLatch();
            page.releaseReadLatch();
        }
        bufferCache.unpin(page);
        page = nextLeaf;
        isPageDirty = false;
        frame.setPage(page);
        nextLeafPage = frame.getNextLeaf();
    } while (frame.getTupleCount() == 0 && nextLeafPage > 0);
}
Also used : ICachedPage(org.apache.hyracks.storage.common.buffercache.ICachedPage)

Aggregations

ICachedPage (org.apache.hyracks.storage.common.buffercache.ICachedPage)51 HyracksDataException (org.apache.hyracks.api.exceptions.HyracksDataException)13 ITreeIndexMetadataFrame (org.apache.hyracks.storage.am.common.api.ITreeIndexMetadataFrame)7 IBufferCache (org.apache.hyracks.storage.common.buffercache.IBufferCache)5 IFileMapProvider (org.apache.hyracks.storage.common.file.IFileMapProvider)4 FileReference (org.apache.hyracks.api.io.FileReference)3 Test (org.junit.Test)3 ByteBuffer (java.nio.ByteBuffer)2 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)2 IIOManager (org.apache.hyracks.api.io.IIOManager)2 ITupleReference (org.apache.hyracks.dataflow.common.data.accessors.ITupleReference)2 BTreeNSMInteriorFrame (org.apache.hyracks.storage.am.btree.frames.BTreeNSMInteriorFrame)2 ITreeIndexFrame (org.apache.hyracks.storage.am.common.api.ITreeIndexFrame)2 FrameOpSpaceStatus (org.apache.hyracks.storage.am.common.frames.FrameOpSpaceStatus)2 TreeIndexDiskOrderScanCursor (org.apache.hyracks.storage.am.common.impls.TreeIndexDiskOrderScanCursor)2 MultiComparator (org.apache.hyracks.storage.common.MultiComparator)2 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 Random (java.util.Random)1 IHyracksTaskContext (org.apache.hyracks.api.context.IHyracksTaskContext)1