Skip to content

Commit

Permalink
Merge TreeNode operations on key and child
Browse files Browse the repository at this point in the history
  • Loading branch information
burqen committed Jan 16, 2018
1 parent 51a1d0d commit 0bcfdb3
Show file tree
Hide file tree
Showing 10 changed files with 176 additions and 275 deletions.
Expand Up @@ -51,7 +51,6 @@
import static org.neo4j.index.internal.gbptree.Header.replace; import static org.neo4j.index.internal.gbptree.Header.replace;
import static org.neo4j.index.internal.gbptree.PageCursorUtil.checkOutOfBounds; import static org.neo4j.index.internal.gbptree.PageCursorUtil.checkOutOfBounds;
import static org.neo4j.index.internal.gbptree.PointerChecking.assertNoSuccessor; import static org.neo4j.index.internal.gbptree.PointerChecking.assertNoSuccessor;
import static org.neo4j.index.internal.gbptree.TreeNode.Type.INTERNAL;


/** /**
* A generation-aware B+tree (GB+Tree) implementation directly atop a {@link PageCache} with no caching in between. * A generation-aware B+tree (GB+Tree) implementation directly atop a {@link PageCache} with no caching in between.
Expand Down Expand Up @@ -1192,12 +1191,11 @@ public void merge( KEY key, VALUE value, ValueMerger<KEY,VALUE> valueMerger ) th
PageCursorUtil.goTo( cursor, "new root", newRootId ); PageCursorUtil.goTo( cursor, "new root", newRootId );


TreeNode.initializeInternal( cursor, stableGeneration, unstableGeneration ); TreeNode.initializeInternal( cursor, stableGeneration, unstableGeneration );
bTreeNode.insertKeyAt( cursor, structurePropagation.rightKey, 0, 0, INTERNAL );
TreeNode.setKeyCount( cursor, 1 );
bTreeNode.setChildAt( cursor, structurePropagation.midChild, 0, bTreeNode.setChildAt( cursor, structurePropagation.midChild, 0,
stableGeneration, unstableGeneration ); stableGeneration, unstableGeneration );
bTreeNode.setChildAt( cursor, structurePropagation.rightChild, 1, bTreeNode.insertKeyAndRightChildAt( cursor, structurePropagation.rightKey, structurePropagation.rightChild, 0, 0,
stableGeneration, unstableGeneration ); stableGeneration, unstableGeneration );
TreeNode.setKeyCount( cursor, 1 );
setRoot( newRootId ); setRoot( newRootId );
} }
else if ( structurePropagation.hasMidChildUpdate ) else if ( structurePropagation.hasMidChildUpdate )
Expand Down
Expand Up @@ -429,12 +429,7 @@ private void insertInInternal( PageCursor cursor, StructurePropagation<KEY> stru


// No overflow // No overflow
int pos = positionOf( search( cursor, INTERNAL, primKey, readKey, keyCount ) ); int pos = positionOf( search( cursor, INTERNAL, primKey, readKey, keyCount ) );

bTreeNode.insertKeyAndRightChildAt( cursor, primKey, rightChild, pos, keyCount, stableGeneration, unstableGeneration );
bTreeNode.insertKeyAt( cursor, primKey, pos, keyCount, INTERNAL );
// NOTE pos+1 since we never insert a new child before child(0) because its key is really
// the one from the parent.
bTreeNode.insertChildAt( cursor, rightChild, pos + 1, keyCount, stableGeneration, unstableGeneration );

// Increase key count // Increase key count
TreeNode.setKeyCount( cursor, keyCount + 1 ); TreeNode.setKeyCount( cursor, keyCount + 1 );
} }
Expand Down Expand Up @@ -877,7 +872,7 @@ private void replaceKeyByBubbleRightmostFromSubtree( PageCursor cursor,
createSuccessorIfNeeded( cursor, structurePropagation, UPDATE_MID_CHILD, createSuccessorIfNeeded( cursor, structurePropagation, UPDATE_MID_CHILD,
stableGeneration, unstableGeneration); stableGeneration, unstableGeneration);
int keyCount = TreeNode.keyCount( cursor ); int keyCount = TreeNode.keyCount( cursor );
simplyRemoveFromInternal( cursor, keyCount, subtreePosition, subtreePosition ); simplyRemoveFromInternal( cursor, keyCount, subtreePosition, true );
} }
} }


Expand Down Expand Up @@ -925,7 +920,7 @@ private boolean bubbleRightmostKeyRecursive( PageCursor cursor, StructurePropaga
// Create new version of node, save rightmost key in structurePropagation, remove rightmost key and child // Create new version of node, save rightmost key in structurePropagation, remove rightmost key and child
createSuccessorIfNeeded( cursor, structurePropagation, UPDATE_MID_CHILD, stableGeneration, unstableGeneration ); createSuccessorIfNeeded( cursor, structurePropagation, UPDATE_MID_CHILD, stableGeneration, unstableGeneration );
bTreeNode.keyAt( cursor, structurePropagation.bubbleKey, keyCount - 1, INTERNAL ); bTreeNode.keyAt( cursor, structurePropagation.bubbleKey, keyCount - 1, INTERNAL );
simplyRemoveFromInternal( cursor, keyCount, keyCount - 1, keyCount ); simplyRemoveFromInternal( cursor, keyCount, keyCount - 1, false );


return true; return true;
} }
Expand All @@ -935,11 +930,17 @@ private boolean bubbleRightmostKeyRecursive( PageCursor cursor, StructurePropaga
} }
} }


private int simplyRemoveFromInternal( PageCursor cursor, int keyCount, int keyPos, int childPos ) private int simplyRemoveFromInternal( PageCursor cursor, int keyCount, int keyPos, boolean leftChild )
{ {
// Remove key and child // Remove key and child
bTreeNode.removeKeyAt( cursor, keyPos, keyCount, INTERNAL ); if ( leftChild )
bTreeNode.removeChildAt( cursor, childPos, keyCount ); {
bTreeNode.removeKeyAndLeftChildAt( cursor, keyPos, keyCount );
}
else
{
bTreeNode.removeKeyAndRightChildAt( cursor, keyPos, keyCount );
}


// Decrease key count // Decrease key count
int newKeyCount = keyCount - 1; int newKeyCount = keyCount - 1;
Expand Down
Expand Up @@ -220,9 +220,8 @@ long pointerGeneration( PageCursor cursor, long readResult )


abstract KEY keyAt( PageCursor cursor, KEY into, int pos, Type type ); abstract KEY keyAt( PageCursor cursor, KEY into, int pos, Type type );


// Insert key without associated value. abstract void insertKeyAndRightChildAt( PageCursor cursor, KEY key, long child, int pos, int keyCount,
// Useful for internal nodes and testing. long stableGeneration, long unstableGeneration );
abstract void insertKeyAt( PageCursor cursor, KEY key, int pos, int keyCount, Type type );


abstract void insertKeyValueAt( PageCursor cursor, KEY key, VALUE value, int pos, int keyCount ); abstract void insertKeyValueAt( PageCursor cursor, KEY key, VALUE value, int pos, int keyCount );


Expand All @@ -232,6 +231,10 @@ long pointerGeneration( PageCursor cursor, long readResult )


abstract void removeKeyValueAt( PageCursor cursor, int pos, int keyCount ); abstract void removeKeyValueAt( PageCursor cursor, int pos, int keyCount );


abstract void removeKeyAndRightChildAt( PageCursor cursor, int keyPos, int keyCount );

abstract void removeKeyAndLeftChildAt( PageCursor cursor, int keyPos, int keyCount );

abstract void setKeyAt( PageCursor cursor, KEY key, int pos, Type type ); abstract void setKeyAt( PageCursor cursor, KEY key, int pos, Type type );


abstract VALUE valueAt( PageCursor cursor, VALUE value, int pos ); abstract VALUE valueAt( PageCursor cursor, VALUE value, int pos );
Expand All @@ -240,11 +243,6 @@ long pointerGeneration( PageCursor cursor, long readResult )


abstract long childAt( PageCursor cursor, int pos, long stableGeneration, long unstableGeneration ); abstract long childAt( PageCursor cursor, int pos, long stableGeneration, long unstableGeneration );


abstract void insertChildAt( PageCursor cursor, long child, int pos, int keyCount,
long stableGeneration, long unstableGeneration );

abstract void removeChildAt( PageCursor cursor, int pos, int keyCount );

abstract void setChildAt( PageCursor cursor, long child, int pos, long stableGeneration, long unstableGeneration ); abstract void setChildAt( PageCursor cursor, long child, int pos, long stableGeneration, long unstableGeneration );


static void writeChild( PageCursor cursor, long child, long stableGeneration, long unstableGeneration ) static void writeChild( PageCursor cursor, long child, long stableGeneration, long unstableGeneration )
Expand Down
Expand Up @@ -35,7 +35,8 @@ KEY keyAt( PageCursor cursor, KEY into, int pos, Type type )
} }


@Override @Override
void insertKeyAt( PageCursor cursor, KEY key, int pos, int keyCount, Type type ) void insertKeyAndRightChildAt( PageCursor cursor, KEY key, long child, int pos, int keyCount, long stableGeneration,
long unstableGeneration )
{ {
throw new UnsupportedOperationException( "Implement me" ); throw new UnsupportedOperationException( "Implement me" );
} }
Expand All @@ -59,37 +60,37 @@ void removeKeyValueAt( PageCursor cursor, int pos, int keyCount )
} }


@Override @Override
void setKeyAt( PageCursor cursor, KEY key, int pos, Type type ) void removeKeyAndRightChildAt( PageCursor cursor, int keyPos, int keyCount )
{ {
throw new UnsupportedOperationException( "Implement me" ); throw new UnsupportedOperationException( "Implement me" );
} }


@Override @Override
VALUE valueAt( PageCursor cursor, VALUE value, int pos ) void removeKeyAndLeftChildAt( PageCursor cursor, int keyPos, int keyCount )
{ {
throw new UnsupportedOperationException( "Implement me" ); throw new UnsupportedOperationException( "Implement me" );
} }


@Override @Override
void setValueAt( PageCursor cursor, VALUE value, int pos ) void setKeyAt( PageCursor cursor, KEY key, int pos, Type type )
{ {
throw new UnsupportedOperationException( "Implement me" ); throw new UnsupportedOperationException( "Implement me" );
} }


@Override @Override
long childAt( PageCursor cursor, int pos, long stableGeneration, long unstableGeneration ) VALUE valueAt( PageCursor cursor, VALUE value, int pos )
{ {
throw new UnsupportedOperationException( "Implement me" ); throw new UnsupportedOperationException( "Implement me" );
} }


@Override @Override
void insertChildAt( PageCursor cursor, long child, int pos, int keyCount, long stableGeneration, long unstableGeneration ) void setValueAt( PageCursor cursor, VALUE value, int pos )
{ {
throw new UnsupportedOperationException( "Implement me" ); throw new UnsupportedOperationException( "Implement me" );
} }


@Override @Override
void removeChildAt( PageCursor cursor, int pos, int keyCount ) long childAt( PageCursor cursor, int pos, long stableGeneration, long unstableGeneration )
{ {
throw new UnsupportedOperationException( "Implement me" ); throw new UnsupportedOperationException( "Implement me" );
} }
Expand Down
Expand Up @@ -71,20 +71,25 @@ KEY keyAt( PageCursor cursor, KEY into, int pos, Type type )
return into; return into;
} }


// Insert key without associated value. private void insertKeyAt( PageCursor cursor, KEY key, int pos, int keyCount )
// Useful for internal nodes and testing.
@Override
void insertKeyAt( PageCursor cursor, KEY key, int pos, int keyCount, Type type )
{ {
insertKeySlotsAt( cursor, pos, 1, keyCount ); insertKeySlotsAt( cursor, pos, 1, keyCount );
cursor.setOffset( keyOffset( pos ) ); cursor.setOffset( keyOffset( pos ) );
layout.writeKey( cursor, key ); layout.writeKey( cursor, key );
} }


@Override
void insertKeyAndRightChildAt( PageCursor cursor, KEY key, long child, int pos, int keyCount, long stableGeneration,
long unstableGeneration )
{
insertKeyAt( cursor, key, pos, keyCount );
insertChildAt( cursor, child, pos + 1, keyCount, stableGeneration, unstableGeneration );
}

@Override @Override
void insertKeyValueAt( PageCursor cursor, KEY key, VALUE value, int pos, int keyCount ) void insertKeyValueAt( PageCursor cursor, KEY key, VALUE value, int pos, int keyCount )
{ {
insertKeyAt( cursor, key, pos, keyCount, Type.LEAF ); insertKeyAt( cursor, key, pos, keyCount );
insertValueAt( cursor, value, pos, keyCount ); insertValueAt( cursor, value, pos, keyCount );
} }


Expand All @@ -103,6 +108,20 @@ void removeKeyValueAt( PageCursor cursor, int pos, int keyCount )
removeValueAt( cursor, pos, keyCount ); removeValueAt( cursor, pos, keyCount );
} }


@Override
void removeKeyAndLeftChildAt( PageCursor cursor, int keyPos, int keyCount )
{
removeKeyAt( cursor, keyPos, keyCount, INTERNAL );
removeChildAt( cursor, keyPos, keyCount );
}

@Override
void removeKeyAndRightChildAt( PageCursor cursor, int keyPos, int keyCount )
{
removeKeyAt( cursor, keyPos, keyCount, INTERNAL );
removeChildAt( cursor, keyPos + 1, keyCount );
}

@Override @Override
void setKeyAt( PageCursor cursor, KEY key, int pos, Type type ) void setKeyAt( PageCursor cursor, KEY key, int pos, Type type )
{ {
Expand Down Expand Up @@ -132,16 +151,14 @@ long childAt( PageCursor cursor, int pos, long stableGeneration, long unstableGe
return read( cursor, stableGeneration, unstableGeneration, pos ); return read( cursor, stableGeneration, unstableGeneration, pos );
} }


@Override private void insertChildAt( PageCursor cursor, long child, int pos, int keyCount,
void insertChildAt( PageCursor cursor, long child, int pos, int keyCount,
long stableGeneration, long unstableGeneration ) long stableGeneration, long unstableGeneration )
{ {
insertChildSlotsAt( cursor, pos, 1, keyCount ); insertChildSlotsAt( cursor, pos, 1, keyCount );
setChildAt( cursor, child, pos, stableGeneration, unstableGeneration ); setChildAt( cursor, child, pos, stableGeneration, unstableGeneration );
} }


@Override private void removeChildAt( PageCursor cursor, int pos, int keyCount )
void removeChildAt( PageCursor cursor, int pos, int keyCount )
{ {
removeSlotAt( cursor, pos, keyCount + 1, childOffset( 0 ), childSize() ); removeSlotAt( cursor, pos, keyCount + 1, childOffset( 0 ), childSize() );
} }
Expand Down Expand Up @@ -320,7 +337,7 @@ void doSplitInternal( PageCursor leftCursor, int leftKeyCount, PageCursor rightC


leftCursor.copyTo( keyOffset( middlePos ), rightCursor, keyOffset( 0 ), rightKeyCount * keySize() ); leftCursor.copyTo( keyOffset( middlePos ), rightCursor, keyOffset( 0 ), rightKeyCount * keySize() );
leftCursor.copyTo( childOffset( middlePos ), rightCursor, childOffset( 0 ), (rightKeyCount + 1) * childSize() ); leftCursor.copyTo( childOffset( middlePos ), rightCursor, childOffset( 0 ), (rightKeyCount + 1) * childSize() );
insertKeyAt( leftCursor, newKey, insertPos, middlePos - 1, INTERNAL ); insertKeyAt( leftCursor, newKey, insertPos, middlePos - 1 );
insertChildAt( leftCursor, newRightChild, insertPos + 1, middlePos - 1, stableGeneration, unstableGeneration ); insertChildAt( leftCursor, newRightChild, insertPos + 1, middlePos - 1, stableGeneration, unstableGeneration );
} }
else else
Expand Down Expand Up @@ -353,7 +370,7 @@ void doSplitInternal( PageCursor leftCursor, int leftKeyCount, PageCursor rightC
// ... insert // ... insert
if ( countBeforePos >= 0 ) if ( countBeforePos >= 0 )
{ {
insertKeyAt( rightCursor, newKey, countBeforePos, countBeforePos, INTERNAL ); insertKeyAt( rightCursor, newKey, countBeforePos, countBeforePos );
} }
// ... second copy // ... second copy
int countAfterPos = leftKeyCount - insertPos; int countAfterPos = leftKeyCount - insertPos;
Expand Down
Expand Up @@ -32,7 +32,6 @@
import static org.neo4j.index.internal.gbptree.ConsistencyChecker.assertNoCrashOrBrokenPointerInGSPP; import static org.neo4j.index.internal.gbptree.ConsistencyChecker.assertNoCrashOrBrokenPointerInGSPP;
import static org.neo4j.index.internal.gbptree.GenerationSafePointer.MIN_GENERATION; import static org.neo4j.index.internal.gbptree.GenerationSafePointer.MIN_GENERATION;
import static org.neo4j.index.internal.gbptree.PageCursorUtil.goTo; import static org.neo4j.index.internal.gbptree.PageCursorUtil.goTo;
import static org.neo4j.index.internal.gbptree.TreeNode.Type.INTERNAL;


public class ConsistencyCheckerTest public class ConsistencyCheckerTest
{ {
Expand Down Expand Up @@ -101,11 +100,10 @@ public void shouldDetectUnusedPages() throws Exception
goTo( cursor, "new root", goTo( cursor, "new root",
idProvider.acquireNewId( stableGeneration, unstableGeneration ) ); idProvider.acquireNewId( stableGeneration, unstableGeneration ) );
TreeNode.initializeInternal( cursor, stableGeneration, unstableGeneration ); TreeNode.initializeInternal( cursor, stableGeneration, unstableGeneration );
node.insertKeyAt( cursor, structure.rightKey, 0, 0, INTERNAL );
TreeNode.setKeyCount( cursor, 1 );
node.setChildAt( cursor, structure.midChild, 0, stableGeneration, unstableGeneration ); node.setChildAt( cursor, structure.midChild, 0, stableGeneration, unstableGeneration );
node.setChildAt( cursor, structure.rightChild, 1, node.insertKeyAndRightChildAt( cursor, structure.rightKey, structure.rightChild, 0, 0,
stableGeneration, unstableGeneration ); stableGeneration, unstableGeneration );
TreeNode.setKeyCount( cursor, 1 );
logic.initialize( cursor ); logic.initialize( cursor );
} }
if ( structure.hasMidChildUpdate ) if ( structure.hasMidChildUpdate )
Expand Down
Expand Up @@ -1546,10 +1546,9 @@ private void newRootFromSplit( StructurePropagation<MutableLong> split ) throws
long rootId = id.acquireNewId( stableGeneration, unstableGeneration ); long rootId = id.acquireNewId( stableGeneration, unstableGeneration );
goTo( cursor, rootId ); goTo( cursor, rootId );
TreeNode.initializeInternal( cursor, stableGeneration, unstableGeneration ); TreeNode.initializeInternal( cursor, stableGeneration, unstableGeneration );
node.insertKeyAt( cursor, split.rightKey, 0, 0, INTERNAL );
TreeNode.setKeyCount( cursor, 1 );
node.setChildAt( cursor, split.midChild, 0, stableGeneration, unstableGeneration ); node.setChildAt( cursor, split.midChild, 0, stableGeneration, unstableGeneration );
node.setChildAt( cursor, split.rightChild, 1, stableGeneration, unstableGeneration ); node.insertKeyAndRightChildAt( cursor, split.rightKey, split.rightChild, 0, 0, stableGeneration, unstableGeneration );
TreeNode.setKeyCount( cursor, 1 );
split.hasRightKeyInsert = false; split.hasRightKeyInsert = false;
updateRoot(); updateRoot();
} }
Expand Down
Expand Up @@ -47,6 +47,7 @@ public class KeySearchTest
private final MutableLong readKey = layout.newKey(); private final MutableLong readKey = layout.newKey();
private final MutableLong searchKey = layout.newKey(); private final MutableLong searchKey = layout.newKey();
private final MutableLong insertKey = layout.newKey(); private final MutableLong insertKey = layout.newKey();
private final MutableLong dummyValue = layout.newValue();


@Rule @Rule
public final RandomRule random = new RandomRule(); public final RandomRule random = new RandomRule();
Expand Down Expand Up @@ -460,7 +461,7 @@ public void shouldSearchAndFindOnRandomData() throws Exception
{ {
keys[i] = currentKey; keys[i] = currentKey;
key.setValue( currentKey ); key.setValue( currentKey );
node.insertKeyAt( cursor, key, i, i, LEAF ); node.insertKeyValueAt( cursor, key, dummyValue, i, i );
currentKey += random.nextInt( 100 ) + 10; currentKey += random.nextInt( 100 ) + 10;
} }
TreeNode.setKeyCount( cursor, keyCount ); TreeNode.setKeyCount( cursor, keyCount );
Expand Down Expand Up @@ -512,8 +513,15 @@ private void appendKey( long key )
{ {
insertKey.setValue( key ); insertKey.setValue( key );
int keyCount = TreeNode.keyCount( cursor ); int keyCount = TreeNode.keyCount( cursor );
TreeNode.Type type = TreeNode.isInternal( cursor ) ? INTERNAL : LEAF; if ( TreeNode.isInternal( cursor ) )
node.insertKeyAt( cursor, insertKey, keyCount, keyCount, type ); {
long dummyChild = 10;
node.insertKeyAndRightChildAt( cursor, insertKey, dummyChild, keyCount, keyCount, STABLE_GENERATION, UNSTABLE_GENERATION );
}
else
{
node.insertKeyValueAt( cursor, insertKey, dummyValue, keyCount, keyCount );
}
TreeNode.setKeyCount( cursor, keyCount + 1 ); TreeNode.setKeyCount( cursor, keyCount + 1 );
} }


Expand All @@ -531,7 +539,7 @@ private void fullLeafWithUniqueKeys()
for ( int i = 0; i < KEY_COUNT; i++ ) for ( int i = 0; i < KEY_COUNT; i++ )
{ {
key.setValue( key( i ) ); key.setValue( key( i ) );
node.insertKeyAt( cursor, key, i, i, LEAF ); node.insertKeyValueAt( cursor, key, dummyValue, i, i );
} }
TreeNode.setKeyCount( cursor, KEY_COUNT ); TreeNode.setKeyCount( cursor, KEY_COUNT );
} }
Expand Down

0 comments on commit 0bcfdb3

Please sign in to comment.