From 859b1b6497a85d20f12e580b9134f70a5c8f8d0a Mon Sep 17 00:00:00 2001 From: Anton Persson Date: Mon, 11 Dec 2017 15:22:09 +0100 Subject: [PATCH] TreeNodeDynamicSize impl part 5 - leafUnderflow Use total available space to determine underflow in leaf --- .../internal/gbptree/InternalTreeLogic.java | 2 +- .../index/internal/gbptree/TreeNode.java | 2 +- .../internal/gbptree/TreeNodeDynamicSize.java | 27 ++++++++++++++----- .../internal/gbptree/TreeNodeFixedSize.java | 2 +- 4 files changed, 24 insertions(+), 9 deletions(-) diff --git a/community/index/src/main/java/org/neo4j/index/internal/gbptree/InternalTreeLogic.java b/community/index/src/main/java/org/neo4j/index/internal/gbptree/InternalTreeLogic.java index 1f62edfb06982..92b7f5c0277e7 100644 --- a/community/index/src/main/java/org/neo4j/index/internal/gbptree/InternalTreeLogic.java +++ b/community/index/src/main/java/org/neo4j/index/internal/gbptree/InternalTreeLogic.java @@ -1019,7 +1019,7 @@ private boolean removeFromLeaf( PageCursor cursor, StructurePropagation str stableGeneration, unstableGeneration ); keyCount = simplyRemoveFromLeaf( cursor, into, keyCount, pos ); - if ( bTreeNode.leafUnderflow( keyCount ) ) + if ( bTreeNode.leafUnderflow( cursor, keyCount ) ) { // Underflow underflowInLeaf( cursor, structurePropagation, keyCount, stableGeneration, unstableGeneration ); diff --git a/community/index/src/main/java/org/neo4j/index/internal/gbptree/TreeNode.java b/community/index/src/main/java/org/neo4j/index/internal/gbptree/TreeNode.java index a8cb1748b0f5a..e281b34a134db 100644 --- a/community/index/src/main/java/org/neo4j/index/internal/gbptree/TreeNode.java +++ b/community/index/src/main/java/org/neo4j/index/internal/gbptree/TreeNode.java @@ -334,7 +334,7 @@ static void goTo( PageCursor cursor, String messageOnError, long nodeId ) */ abstract void defragmentLeaf( PageCursor cursor ); - abstract boolean leafUnderflow( int keyCount ); + abstract boolean leafUnderflow( PageCursor cursor, int keyCount ); abstract boolean canRebalanceLeaves( int leftKeyCount, int rightKeyCount ); diff --git a/community/index/src/main/java/org/neo4j/index/internal/gbptree/TreeNodeDynamicSize.java b/community/index/src/main/java/org/neo4j/index/internal/gbptree/TreeNodeDynamicSize.java index d9c0bdb4b865c..f4e1db6b64094 100644 --- a/community/index/src/main/java/org/neo4j/index/internal/gbptree/TreeNodeDynamicSize.java +++ b/community/index/src/main/java/org/neo4j/index/internal/gbptree/TreeNodeDynamicSize.java @@ -282,10 +282,8 @@ boolean internalOverflow( int currentKeyCount ) Overflow leafOverflow( PageCursor cursor, int currentKeyCount, KEY newKey, VALUE newValue ) { // How much space do we have? - int allocOffset = getAllocOffset( cursor ); int deadSpace = getDeadSpace( cursor ); - int endOfOffsetArray = keyPosOffsetLeaf( currentKeyCount ); - int allocSpace = allocOffset - endOfOffsetArray; + int allocSpace = getAllocSpace( cursor, currentKeyCount ); // How much space do we need? int keySize = layout.keySize( newKey ); @@ -402,9 +400,14 @@ void defragmentLeaf( PageCursor cursor ) } @Override - boolean leafUnderflow( int keyCount ) + boolean leafUnderflow( PageCursor cursor, int keyCount ) { - throw new UnsupportedOperationException( "Implement me" ); + int halfSpace = halfSpace(); + int allocSpace = getAllocSpace( cursor, keyCount ); + int deadSpace = getDeadSpace( cursor ); + int availableSpace = allocSpace + deadSpace; + + return availableSpace > halfSpace; } @Override @@ -468,6 +471,13 @@ void doSplitLeaf( PageCursor leftCursor, int leftKeyCount, PageCursor rightCurso TreeNode.setKeyCount( rightCursor, rightKeyCount ); } + private int getAllocSpace( PageCursor cursor, int keyCount ) + { + int allocOffset = getAllocOffset( cursor ); + int endOfOffsetArray = keyPosOffsetLeaf( keyCount ); + return allocOffset - endOfOffsetArray; + } + private void recordDeadAndAlive( PageCursor cursor, PrimitiveIntStack deadKeysOffset, PrimitiveIntStack aliveKeysOffset ) { int currentOffset = getAllocOffset( cursor ); @@ -529,7 +539,7 @@ private int transferRawKeyValue( PageCursor fromCursor, int fromPos, PageCursor private int middle( PageCursor leftCursor, int insertPos, KEY newKey, VALUE newValue ) { - int halfSpace = (pageSize - HEADER_LENGTH_DYNAMIC) / 2; + int halfSpace = halfSpace(); int middle = 0; int currentPos = 0; int middleSpace = 0; @@ -562,6 +572,11 @@ private int middle( PageCursor leftCursor, int insertPos, KEY newKey, VALUE newV return middle; } + private int halfSpace() + { + return (pageSize - HEADER_LENGTH_DYNAMIC) / 2; + } + private int totalSpaceOfKeyValue( KEY key, VALUE value ) { return bytesKeyOffset() + bytesKeySize() + bytesValueSize() + layout.keySize( key ) + layout.valueSize( value ); diff --git a/community/index/src/main/java/org/neo4j/index/internal/gbptree/TreeNodeFixedSize.java b/community/index/src/main/java/org/neo4j/index/internal/gbptree/TreeNodeFixedSize.java index eb722c7b5679b..2dac519b3d3ed 100644 --- a/community/index/src/main/java/org/neo4j/index/internal/gbptree/TreeNodeFixedSize.java +++ b/community/index/src/main/java/org/neo4j/index/internal/gbptree/TreeNodeFixedSize.java @@ -273,7 +273,7 @@ void defragmentLeaf( PageCursor cursor ) } @Override - boolean leafUnderflow( int keyCount ) + boolean leafUnderflow( PageCursor cursor, int keyCount ) { return keyCount < (leafMaxKeyCount() + 1) / 2; }