Search in sources :

Example 71 with PageCursor

use of org.neo4j.io.pagecache.PageCursor in project neo4j by neo4j.

the class MuninnPageCacheTest method mustUnblockPageFaultersWhenEvictionGetsException.

@Test(timeout = SEMI_LONG_TIMEOUT_MILLIS)
public void mustUnblockPageFaultersWhenEvictionGetsException() throws Exception {
    writeInitialDataTo(file("a"));
    FileSystemAbstraction fs = new DelegatingFileSystemAbstraction(this.fs) {

        @Override
        public StoreChannel open(File fileName, String mode) throws IOException {
            return new DelegatingStoreChannel(super.open(fileName, mode)) {

                @Override
                public void writeAll(ByteBuffer src, long position) throws IOException {
                    throw new IOException("uh-oh...");
                }
            };
        }
    };
    MuninnPageCache pageCache = createPageCache(fs, 2, 8, PageCacheTracer.NULL, DefaultPageCursorTracerSupplier.INSTANCE);
    final PagedFile pagedFile = pageCache.map(file("a"), 8);
    // all writes.
    try (PageCursor cursor = pagedFile.io(0, PF_SHARED_WRITE_LOCK)) {
        for (int i = 0; i < 1000; i++) {
            assertTrue(cursor.next());
        }
        fail("Expected an exception at this point");
    } catch (IOException ignore) {
    // Good.
    }
}
Also used : DelegatingFileSystemAbstraction(org.neo4j.graphdb.mockfs.DelegatingFileSystemAbstraction) FileSystemAbstraction(org.neo4j.io.fs.FileSystemAbstraction) PagedFile(org.neo4j.io.pagecache.PagedFile) DelegatingStoreChannel(org.neo4j.graphdb.mockfs.DelegatingStoreChannel) IOException(java.io.IOException) DelegatingFileSystemAbstraction(org.neo4j.graphdb.mockfs.DelegatingFileSystemAbstraction) PagedFile(org.neo4j.io.pagecache.PagedFile) File(java.io.File) ByteBuffer(java.nio.ByteBuffer) PageCursor(org.neo4j.io.pagecache.PageCursor) PageCacheTest(org.neo4j.io.pagecache.PageCacheTest) Test(org.junit.Test)

Example 72 with PageCursor

use of org.neo4j.io.pagecache.PageCursor in project neo4j by neo4j.

the class GBPTree method writeState.

private void writeState(PagedFile pagedFile, Header.Writer headerWriter) throws IOException {
    Pair<TreeState, TreeState> states = readStatePages(pagedFile);
    TreeState oldestState = TreeStatePair.selectOldestOrInvalid(states);
    long pageToOverwrite = oldestState.pageId();
    Root root = this.root;
    try (PageCursor cursor = pagedFile.io(pageToOverwrite, PagedFile.PF_SHARED_WRITE_LOCK)) {
        PageCursorUtil.goTo(cursor, "state page", pageToOverwrite);
        TreeState.write(cursor, stableGeneration(generation), unstableGeneration(generation), root.id(), root.generation(), freeList.lastId(), freeList.writePageId(), freeList.readPageId(), freeList.writePos(), freeList.readPos());
        writerHeader(pagedFile, headerWriter, other(states, oldestState), cursor);
        checkOutOfBounds(cursor);
    }
}
Also used : PageCursor(org.neo4j.io.pagecache.PageCursor)

Example 73 with PageCursor

use of org.neo4j.io.pagecache.PageCursor in project neo4j by neo4j.

the class InternalTreeLogic method updateLeftmostChildInRightSibling.

private void updateLeftmostChildInRightSibling(PageCursor cursor, long childPointer, long stableGeneration, long unstableGeneration) throws IOException {
    long rightSibling = bTreeNode.rightSibling(cursor, stableGeneration, unstableGeneration);
    // Left sibling is not allowed to be NO_NODE here because that means there is a child node with no parent
    PointerChecking.checkPointer(rightSibling, false);
    try (PageCursor rightSiblingCursor = cursor.openLinkedCursor(rightSibling)) {
        bTreeNode.goTo(rightSiblingCursor, "right sibling", rightSibling);
        bTreeNode.setChildAt(rightSiblingCursor, childPointer, 0, stableGeneration, unstableGeneration);
    }
}
Also used : PageCursor(org.neo4j.io.pagecache.PageCursor)

Example 74 with PageCursor

use of org.neo4j.io.pagecache.PageCursor in project neo4j by neo4j.

the class InternalTreeLogic method underflowInLeaf.

private void underflowInLeaf(PageCursor cursor, StructurePropagation<KEY> structurePropagation, int keyCount, long stableGeneration, long unstableGeneration) throws IOException {
    long leftSibling = bTreeNode.leftSibling(cursor, stableGeneration, unstableGeneration);
    PointerChecking.checkPointer(leftSibling, true);
    long rightSibling = bTreeNode.rightSibling(cursor, stableGeneration, unstableGeneration);
    PointerChecking.checkPointer(rightSibling, true);
    if (TreeNode.isNode(leftSibling)) {
        // Go to left sibling and read stuff
        try (PageCursor leftSiblingCursor = cursor.openLinkedCursor(GenerationSafePointerPair.pointer(leftSibling))) {
            leftSiblingCursor.next();
            int leftSiblingKeyCount = bTreeNode.keyCount(leftSiblingCursor);
            if (keyCount + leftSiblingKeyCount >= bTreeNode.leafMaxKeyCount()) {
                createSuccessorIfNeeded(leftSiblingCursor, structurePropagation, StructurePropagation.UPDATE_LEFT_CHILD, stableGeneration, unstableGeneration);
                rebalanceLeaf(cursor, leftSiblingCursor, structurePropagation, keyCount, leftSiblingKeyCount);
            } else {
                // No need to create new unstable version of left sibling.
                // Parent pointer will be updated later.
                mergeFromLeftSiblingLeaf(cursor, leftSiblingCursor, structurePropagation, keyCount, leftSiblingKeyCount, stableGeneration, unstableGeneration);
            }
        }
    } else if (TreeNode.isNode(rightSibling)) {
        try (PageCursor rightSiblingCursor = cursor.openLinkedCursor(GenerationSafePointerPair.pointer(rightSibling))) {
            rightSiblingCursor.next();
            int rightSiblingKeyCount = bTreeNode.keyCount(rightSiblingCursor);
            if (keyCount + rightSiblingKeyCount <= bTreeNode.leafMaxKeyCount()) {
                createSuccessorIfNeeded(rightSiblingCursor, structurePropagation, UPDATE_RIGHT_CHILD, stableGeneration, unstableGeneration);
                mergeToRightSiblingLeaf(cursor, rightSiblingCursor, structurePropagation, keyCount, rightSiblingKeyCount, stableGeneration, unstableGeneration);
            }
        }
    }
}
Also used : PageCursor(org.neo4j.io.pagecache.PageCursor)

Example 75 with PageCursor

use of org.neo4j.io.pagecache.PageCursor in project neo4j by neo4j.

the class InternalTreeLogic method splitInternal.

/**
     * Leaves cursor at same page as when called. No guarantees on offset.
     * <p>
     * Split in internal node caused by an insertion of rightKey and newRightChild
     *
     * @param cursor {@link PageCursor} pinned to page containing internal node, full node.
     * @param structurePropagation {@link StructurePropagation} used to report structure changes between tree levels.
     * @param newKey new key to be inserted together with newRightChild, causing the split
     * @param newRightChild new child to be inserted to the right of newKey
     * @param keyCount key count for fullNode
     * @throws IOException on cursor failure
     */
private void splitInternal(PageCursor cursor, StructurePropagation<KEY> structurePropagation, KEY newKey, long newRightChild, int keyCount, long stableGeneration, long unstableGeneration) throws IOException {
    long current = cursor.getCurrentPageId();
    long oldRight = bTreeNode.rightSibling(cursor, stableGeneration, unstableGeneration);
    PointerChecking.checkPointer(oldRight, true);
    long newRight = idProvider.acquireNewId(stableGeneration, unstableGeneration);
    // Find position to insert new key
    int pos = positionOf(search(cursor, newKey, readKey, keyCount));
    int keyCountAfterInsert = keyCount + 1;
    int middlePos = middle(keyCountAfterInsert);
    // Update structurePropagation
    structurePropagation.hasRightKeyInsert = true;
    structurePropagation.midChild = current;
    structurePropagation.rightChild = newRight;
    if (middlePos == pos) {
        layout.copyKey(newKey, structurePropagation.rightKey);
    } else {
        bTreeNode.keyAt(cursor, structurePropagation.rightKey, pos < middlePos ? middlePos - 1 : middlePos);
    }
    // Update new right
    try (PageCursor rightCursor = cursor.openLinkedCursor(newRight)) {
        bTreeNode.goTo(rightCursor, "new right sibling in split", newRight);
        bTreeNode.initializeInternal(rightCursor, stableGeneration, unstableGeneration);
        bTreeNode.setRightSibling(rightCursor, oldRight, stableGeneration, unstableGeneration);
        bTreeNode.setLeftSibling(rightCursor, current, stableGeneration, unstableGeneration);
        // -1 because don't keep prim key in internal
        int rightKeyCount = keyCountAfterInsert - middlePos - 1;
        if (pos < middlePos) {
            //                         v-------v       copy
            // before key    _,_,_,_,_,_,_,_,_,_
            // before child -,-,-,-,-,-,-,-,-,-,-
            // insert key    _,_,X,_,_,_,_,_,_,_,_
            // insert child -,-,-,x,-,-,-,-,-,-,-,-
            // middle key              ^
            // children
            cursor.copyTo(bTreeNode.keyOffset(middlePos), rightCursor, bTreeNode.keyOffset(0), rightKeyCount * bTreeNode.keySize());
            cursor.copyTo(bTreeNode.childOffset(middlePos), rightCursor, bTreeNode.childOffset(0), (rightKeyCount + 1) * bTreeNode.childSize());
        } else {
            // pos > middlePos
            //                         v-v          first copy
            //                             v-v-v    second copy
            // before key    _,_,_,_,_,_,_,_,_,_
            // before child -,-,-,-,-,-,-,-,-,-,-
            // insert key    _,_,_,_,_,_,_,X,_,_,_
            // insert child -,-,-,-,-,-,-,-,x,-,-,-
            // middle key              ^
            // pos == middlePos
            //                                      first copy
            //                         v-v-v-v-v    second copy
            // before key    _,_,_,_,_,_,_,_,_,_
            // before child -,-,-,-,-,-,-,-,-,-,-
            // insert key    _,_,_,_,_,X,_,_,_,_,_
            // insert child -,-,-,-,-,-,x,-,-,-,-,-
            // middle key              ^
            // Keys
            int countBeforePos = pos - (middlePos + 1);
            // ... first copy
            if (countBeforePos > 0) {
                cursor.copyTo(bTreeNode.keyOffset(middlePos + 1), rightCursor, bTreeNode.keyOffset(0), countBeforePos * bTreeNode.keySize());
            }
            // ... insert
            if (countBeforePos >= 0) {
                bTreeNode.insertKeyAt(rightCursor, newKey, countBeforePos, countBeforePos);
            }
            // ... second copy
            int countAfterPos = keyCount - pos;
            if (countAfterPos > 0) {
                cursor.copyTo(bTreeNode.keyOffset(pos), rightCursor, bTreeNode.keyOffset(countBeforePos + 1), countAfterPos * bTreeNode.keySize());
            }
            // Children
            countBeforePos = pos - middlePos;
            // ... first copy
            if (countBeforePos > 0) {
                // first copy
                cursor.copyTo(bTreeNode.childOffset(middlePos + 1), rightCursor, bTreeNode.childOffset(0), countBeforePos * bTreeNode.childSize());
            }
            // ... insert
            bTreeNode.insertChildAt(rightCursor, newRightChild, countBeforePos, countBeforePos, stableGeneration, unstableGeneration);
            // ... second copy
            if (countAfterPos > 0) {
                cursor.copyTo(bTreeNode.childOffset(pos + 1), rightCursor, bTreeNode.childOffset(countBeforePos + 1), countAfterPos * bTreeNode.childSize());
            }
        }
        bTreeNode.setKeyCount(rightCursor, rightKeyCount);
    }
    // Update old right with new left sibling (newRight)
    if (TreeNode.isNode(oldRight)) {
        bTreeNode.goTo(cursor, "old right sibling", oldRight);
        bTreeNode.setLeftSibling(cursor, newRight, stableGeneration, unstableGeneration);
    }
    // Update left node
    // Move cursor back to left
    bTreeNode.goTo(cursor, "left", current);
    bTreeNode.setKeyCount(cursor, middlePos);
    if (pos < middlePos) {
        bTreeNode.insertKeyAt(cursor, newKey, pos, middlePos - 1);
        bTreeNode.insertChildAt(cursor, newRightChild, pos + 1, middlePos - 1, stableGeneration, unstableGeneration);
    }
    bTreeNode.setRightSibling(cursor, newRight, stableGeneration, unstableGeneration);
}
Also used : PageCursor(org.neo4j.io.pagecache.PageCursor)

Aggregations

PageCursor (org.neo4j.io.pagecache.PageCursor)184 Test (org.junit.Test)124 StubPageCursor (org.neo4j.io.pagecache.StubPageCursor)106 PagedFile (org.neo4j.io.pagecache.PagedFile)19 IOException (java.io.IOException)12 File (java.io.File)8 CursorException (org.neo4j.io.pagecache.CursorException)6 PageCacheTest (org.neo4j.io.pagecache.PageCacheTest)6 CompositePageCursor (org.neo4j.io.pagecache.impl.CompositePageCursor)6 DelegatingPageCursor (org.neo4j.io.pagecache.impl.DelegatingPageCursor)6 ByteBuffer (java.nio.ByteBuffer)5 DelegatingStoreChannel (org.neo4j.graphdb.mockfs.DelegatingStoreChannel)5 StoreChannel (org.neo4j.io.fs.StoreChannel)4 DelegatingPagedFile (org.neo4j.io.pagecache.DelegatingPagedFile)4 ConfigurablePageCursorTracerSupplier (org.neo4j.io.pagecache.tracing.ConfigurablePageCursorTracerSupplier)4 RecordingPageCacheTracer (org.neo4j.io.pagecache.tracing.recording.RecordingPageCacheTracer)4 Evict (org.neo4j.io.pagecache.tracing.recording.RecordingPageCacheTracer.Evict)4 RecordingPageCursorTracer (org.neo4j.io.pagecache.tracing.recording.RecordingPageCursorTracer)4 Fault (org.neo4j.io.pagecache.tracing.recording.RecordingPageCursorTracer.Fault)4 AtomicLong (java.util.concurrent.atomic.AtomicLong)3