From 5aad59c6cc54570b2d4f68f73e9bdea4ac7098e0 Mon Sep 17 00:00:00 2001 From: Anton Persson Date: Thu, 9 Mar 2017 13:28:12 +0100 Subject: [PATCH] Improved TreePrinter Added possibility to - print individual node - also print tree state --- .../neo4j/index/internal/gbptree/GBPTree.java | 6 +- .../index/internal/gbptree/TreePrinter.java | 64 ++++++++++++++----- .../internal/gbptree/GBPTreeRecoveryTest.java | 2 +- .../gbptree/InternalTreeLogicTest.java | 2 +- 4 files changed, 54 insertions(+), 20 deletions(-) diff --git a/community/index/src/main/java/org/neo4j/index/internal/gbptree/GBPTree.java b/community/index/src/main/java/org/neo4j/index/internal/gbptree/GBPTree.java index 31dd76a0bc33..80225b9efe77 100644 --- a/community/index/src/main/java/org/neo4j/index/internal/gbptree/GBPTree.java +++ b/community/index/src/main/java/org/neo4j/index/internal/gbptree/GBPTree.java @@ -738,16 +738,16 @@ public void prepareForRecovery() throws IOException void printTree() throws IOException { - printTree( true, true ); + printTree( true, true, true ); } // Utility method - void printTree( boolean printValues, boolean printPosition ) throws IOException + void printTree( boolean printValues, boolean printPosition, boolean printState ) throws IOException { try ( PageCursor cursor = openRootCursor( PagedFile.PF_SHARED_READ_LOCK ) ) { new TreePrinter<>( bTreeNode, layout, stableGeneration( generation ), unstableGeneration( generation ) ) - .printTree( cursor, System.out, printValues, printPosition ); + .printTree( cursor, System.out, printValues, printPosition, printState ); } } diff --git a/community/index/src/main/java/org/neo4j/index/internal/gbptree/TreePrinter.java b/community/index/src/main/java/org/neo4j/index/internal/gbptree/TreePrinter.java index 6c286f51fd69..287820ed775a 100644 --- a/community/index/src/main/java/org/neo4j/index/internal/gbptree/TreePrinter.java +++ b/community/index/src/main/java/org/neo4j/index/internal/gbptree/TreePrinter.java @@ -19,11 +19,14 @@ */ package org.neo4j.index.internal.gbptree; +import org.apache.commons.lang3.tuple.Pair; + import java.io.IOException; import java.io.PrintStream; import org.neo4j.io.pagecache.PageCursor; +import static java.lang.String.format; import static org.neo4j.index.internal.gbptree.ConsistencyChecker.assertOnTreeNode; import static org.neo4j.index.internal.gbptree.GenSafePointerPair.pointer; @@ -53,10 +56,21 @@ class TreePrinter * @param cursor {@link PageCursor} placed at root of tree or sub-tree. * @param out target to print tree at. * @param printPosition whether or not to include positional (slot number) information. + * @param printState * @throws IOException on page cache access error. */ - void printTree( PageCursor cursor, PrintStream out, boolean printValues, boolean printPosition ) throws IOException + void printTree( PageCursor cursor, PrintStream out, boolean printValues, boolean printPosition, boolean printState ) + throws IOException { + if ( printState ) + { + long currentPage = cursor.getCurrentPageId(); + Pair statePair = TreeStatePair.readStatePages( + cursor, IdSpace.STATE_PAGE_A, IdSpace.STATE_PAGE_B ); + node.goTo( cursor, "back to tree node from reading state", currentPage ); + out.println( "StateA: " + statePair.getLeft() ); + out.println( "StateB: " + statePair.getRight() ); + } assertOnTreeNode( cursor ); // Traverse the tree @@ -77,10 +91,38 @@ void printTree( PageCursor cursor, PrintStream out, boolean printValues, boolean while ( goToLeftmostChild( cursor ) ); } - private void printTreeNode( PageCursor cursor, int keyCount, boolean isLeaf, PrintStream out, boolean printValues, - boolean printPosition ) throws IOException + void printTreeNode( PageCursor cursor, PrintStream out, boolean printValues, boolean printPosition, + boolean printHeader ) throws IOException { - out.print( "{" + cursor.getCurrentPageId() + "} " ); + boolean isLeaf; + int keyCount; + do + { + isLeaf = TreeNode.isLeaf( cursor ); + keyCount = node.keyCount( cursor ); + if ( keyCount < 0 || (keyCount > node.internalMaxKeyCount() && keyCount > node.leafMaxKeyCount()) ) + { + cursor.setCursorException( "Unexpected keyCount " + keyCount ); + } + } while ( cursor.shouldRetry() ); + + if ( printHeader ) + { + //[TYPE][GEN][KEYCOUNT] ([RIGHTSIBLING][LEFTSIBLING][NEWGEN])) + long generation = -1; + do + { + generation = node.gen( cursor ); + + } while ( cursor.shouldRetry() ); + String treeNodeType = isLeaf ? "leaf" : "internal"; + out.print( format( "{%d,%s,gen=%d,keyCount=%d}", + cursor.getCurrentPageId(), treeNodeType, generation, keyCount ) ); + } + else + { + out.print( "{" + cursor.getCurrentPageId() + "} " ); + } KEY key = layout.newKey(); VALUE value = layout.newValue(); for ( int i = 0; i < keyCount; i++ ) @@ -161,26 +203,18 @@ private boolean goToLeftmostChild( PageCursor cursor ) throws IOException private void printLevel( PageCursor cursor, PrintStream out, boolean printValues, boolean printPosition ) throws IOException { - int keyCount; long rightSibling = -1; - boolean isLeaf; do { + + printTreeNode( cursor, out, printValues, printPosition, false ); + do { - isLeaf = TreeNode.isLeaf( cursor ); - keyCount = node.keyCount( cursor ); - if ( keyCount < 0 || (keyCount > node.internalMaxKeyCount() && keyCount > node.leafMaxKeyCount()) ) - { - cursor.setCursorException( "Unexpected keyCount " + keyCount ); - continue; - } rightSibling = node.rightSibling( cursor, stableGeneration, unstableGeneration ); } while ( cursor.shouldRetry() ); - printTreeNode( cursor, keyCount, isLeaf, out, printValues, printPosition ); - if ( TreeNode.isNode( rightSibling ) ) { node.goTo( cursor, "right sibling", rightSibling ); diff --git a/community/index/src/test/java/org/neo4j/index/internal/gbptree/GBPTreeRecoveryTest.java b/community/index/src/test/java/org/neo4j/index/internal/gbptree/GBPTreeRecoveryTest.java index c8db492f4837..2f11094a7cd5 100644 --- a/community/index/src/test/java/org/neo4j/index/internal/gbptree/GBPTreeRecoveryTest.java +++ b/community/index/src/test/java/org/neo4j/index/internal/gbptree/GBPTreeRecoveryTest.java @@ -174,7 +174,7 @@ private void doShouldRecoverFromAnything( boolean replayRecoveryExactlyFromCheck } else { - recoveryActions = recoveryActions( load, random.nextInt( lastCheckPointIndex ) ); + recoveryActions = recoveryActions( load, random.nextInt( lastCheckPointIndex + 1) ); } // first crashing during recovery diff --git a/community/index/src/test/java/org/neo4j/index/internal/gbptree/InternalTreeLogicTest.java b/community/index/src/test/java/org/neo4j/index/internal/gbptree/InternalTreeLogicTest.java index 70ac7be7dcf2..3845d1eba3ca 100644 --- a/community/index/src/test/java/org/neo4j/index/internal/gbptree/InternalTreeLogicTest.java +++ b/community/index/src/test/java/org/neo4j/index/internal/gbptree/InternalTreeLogicTest.java @@ -1487,7 +1487,7 @@ private void printTree() throws IOException { long currentPageId = cursor.getCurrentPageId(); cursor.next( rootId ); - new TreePrinter<>( node, layout, stableGen, unstableGen ).printTree( cursor, System.out, true, true ); + new TreePrinter<>( node, layout, stableGen, unstableGen ).printTree( cursor, System.out, true, true, true ); cursor.next( currentPageId ); }