Skip to content

Commit

Permalink
GBPTree - Rebalance support: Rename fields in StructurePropagation
Browse files Browse the repository at this point in the history
  • Loading branch information
burqen committed Feb 14, 2017
1 parent ea041ee commit a8eb7bc
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 95 deletions.
Expand Up @@ -795,7 +795,7 @@ private class SingleWriter implements Writer<KEY,VALUE>


SingleWriter( InternalTreeLogic<KEY,VALUE> treeLogic ) SingleWriter( InternalTreeLogic<KEY,VALUE> treeLogic )
{ {
this.structurePropagation = new StructurePropagation<>( layout.newKey() ); this.structurePropagation = new StructurePropagation<>( layout.newKey(), layout.newKey() );
this.treeLogic = treeLogic; this.treeLogic = treeLogic;
} }


Expand All @@ -819,22 +819,24 @@ public void merge( KEY key, VALUE value, ValueMerger<VALUE> valueMerger ) throws
treeLogic.insert( cursor, structurePropagation, key, value, valueMerger, treeLogic.insert( cursor, structurePropagation, key, value, valueMerger,
stableGeneration, unstableGeneration ); stableGeneration, unstableGeneration );


if ( structurePropagation.hasSplit ) if ( structurePropagation.hasRightKeyInsert )
{ {
// New root // New root
long newRootId = freeList.acquireNewId( stableGeneration, unstableGeneration ); long newRootId = freeList.acquireNewId( stableGeneration, unstableGeneration );
PageCursorUtil.goTo( cursor, "new root", newRootId ); PageCursorUtil.goTo( cursor, "new root", newRootId );


bTreeNode.initializeInternal( cursor, stableGeneration, unstableGeneration ); bTreeNode.initializeInternal( cursor, stableGeneration, unstableGeneration );
bTreeNode.insertKeyAt( cursor, structurePropagation.primKey, 0, 0 ); bTreeNode.insertKeyAt( cursor, structurePropagation.rightKey, 0, 0 );
bTreeNode.setKeyCount( cursor, 1 ); bTreeNode.setKeyCount( cursor, 1 );
bTreeNode.setChildAt( cursor, structurePropagation.left, 0, stableGeneration, unstableGeneration ); bTreeNode.setChildAt( cursor, structurePropagation.midChild, 0,
bTreeNode.setChildAt( cursor, structurePropagation.right, 1, stableGeneration, unstableGeneration ); stableGeneration, unstableGeneration );
bTreeNode.setChildAt( cursor, structurePropagation.rightChild, 1,
stableGeneration, unstableGeneration );
setRoot( newRootId ); setRoot( newRootId );
} }
else if ( structurePropagation.hasNewGen ) else if ( structurePropagation.hasMidChildUpdate )
{ {
setRoot( structurePropagation.left ); setRoot( structurePropagation.midChild );
} }
structurePropagation.clear(); structurePropagation.clear();


Expand All @@ -852,9 +854,9 @@ public VALUE remove( KEY key ) throws IOException
{ {
VALUE result = treeLogic.remove( cursor, structurePropagation, key, layout.newValue(), VALUE result = treeLogic.remove( cursor, structurePropagation, key, layout.newValue(),
stableGeneration, unstableGeneration ); stableGeneration, unstableGeneration );
if ( structurePropagation.hasNewGen ) if ( structurePropagation.hasMidChildUpdate )
{ {
setRoot( structurePropagation.left ); setRoot( structurePropagation.midChild );
} }
structurePropagation.clear(); structurePropagation.clear();


Expand Down
Expand Up @@ -77,7 +77,7 @@ class InternalTreeLogic<KEY,VALUE>
private final IdProvider idProvider; private final IdProvider idProvider;
private final TreeNode<KEY,VALUE> bTreeNode; private final TreeNode<KEY,VALUE> bTreeNode;
private final Layout<KEY,VALUE> layout; private final Layout<KEY,VALUE> layout;
private final KEY primKeyPlaceHolder; private final KEY newKeyPlaceHolder;
private final KEY readKey; private final KEY readKey;
private final VALUE readValue; private final VALUE readValue;


Expand Down Expand Up @@ -153,7 +153,7 @@ boolean covers( KEY key )
this.idProvider = idProvider; this.idProvider = idProvider;
this.bTreeNode = bTreeNode; this.bTreeNode = bTreeNode;
this.layout = layout; this.layout = layout;
this.primKeyPlaceHolder = layout.newKey(); this.newKeyPlaceHolder = layout.newKey();
this.readKey = layout.newKey(); this.readKey = layout.newKey();
this.readValue = layout.newValue(); this.readValue = layout.newValue();


Expand Down Expand Up @@ -348,7 +348,7 @@ void insert( PageCursor cursor, StructurePropagation<KEY> structurePropagation,


insertInLeaf( cursor, structurePropagation, key, value, valueMerger, stableGeneration, unstableGeneration ); insertInLeaf( cursor, structurePropagation, key, value, valueMerger, stableGeneration, unstableGeneration );


while ( structurePropagation.hasNewGen || structurePropagation.hasSplit ) while ( structurePropagation.hasMidChildUpdate || structurePropagation.hasRightKeyInsert )
{ {
int pos = levels[currentLevel].childPos; int pos = levels[currentLevel].childPos;
if ( !popLevel( cursor ) ) if ( !popLevel( cursor ) )
Expand All @@ -357,16 +357,18 @@ void insert( PageCursor cursor, StructurePropagation<KEY> structurePropagation,
break; break;
} }


if ( structurePropagation.hasNewGen ) if ( structurePropagation.hasMidChildUpdate )
{ {
structurePropagation.hasNewGen = false; structurePropagation.hasMidChildUpdate = false;
bTreeNode.setChildAt( cursor, structurePropagation.left, pos, stableGeneration, unstableGeneration ); bTreeNode.setChildAt(
cursor, structurePropagation.midChild, pos, stableGeneration, unstableGeneration );
} }
if ( structurePropagation.hasSplit ) if ( structurePropagation.hasRightKeyInsert )
{ {
structurePropagation.hasSplit = false; structurePropagation.hasRightKeyInsert = false;
insertInInternal( cursor, structurePropagation, bTreeNode.keyCount( cursor ), structurePropagation.primKey, insertInInternal( cursor, structurePropagation, bTreeNode.keyCount( cursor ),
structurePropagation.right, stableGeneration, unstableGeneration ); structurePropagation.rightKey, structurePropagation.rightChild,
stableGeneration, unstableGeneration );
} }
} }
} }
Expand Down Expand Up @@ -428,25 +430,25 @@ private void insertInInternal( PageCursor cursor, StructurePropagation<KEY> stru
} }


// Overflow // Overflow
// We will overwrite primKey in structurePropagation, so copy it over to a place holder // We will overwrite rightKey in structurePropagation, so copy it over to a place holder
layout.copyKey( structurePropagation.primKey, primKeyPlaceHolder ); layout.copyKey( structurePropagation.rightKey, newKeyPlaceHolder );
splitInternal( cursor, structurePropagation, primKeyPlaceHolder, rightChild, keyCount, splitInternal( cursor, structurePropagation, newKeyPlaceHolder, rightChild, keyCount,
stableGeneration, unstableGeneration ); stableGeneration, unstableGeneration );
} }


/** /**
* Leaves cursor at same page as when called. No guarantees on offset. * Leaves cursor at same page as when called. No guarantees on offset.
* <p> * <p>
* Split in internal node caused by an insertion of primKey and newRightChild * 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 cursor {@link PageCursor} pinned to page containing internal node, full node.
* @param structurePropagation {@link StructurePropagation} used to report structure changes between tree levels. * @param structurePropagation {@link StructurePropagation} used to report structure changes between tree levels.
* @param primKey primary key to be inserted, causing the split * @param newKey new key to be inserted together with newRightChild, causing the split
* @param newRightChild right child of primKey * @param newRightChild new child to be inserted to the right of newKey
* @param keyCount key count for fullNode * @param keyCount key count for fullNode
* @throws IOException on cursor failure * @throws IOException on cursor failure
*/ */
private void splitInternal( PageCursor cursor, StructurePropagation<KEY> structurePropagation, KEY primKey, private void splitInternal( PageCursor cursor, StructurePropagation<KEY> structurePropagation, KEY newKey,
long newRightChild, int keyCount, long stableGeneration, long unstableGeneration ) throws IOException long newRightChild, int keyCount, long stableGeneration, long unstableGeneration ) throws IOException
{ {
long current = cursor.getCurrentPageId(); long current = cursor.getCurrentPageId();
Expand All @@ -455,22 +457,22 @@ private void splitInternal( PageCursor cursor, StructurePropagation<KEY> structu
long newRight = idProvider.acquireNewId( stableGeneration, unstableGeneration ); long newRight = idProvider.acquireNewId( stableGeneration, unstableGeneration );


// Find position to insert new key // Find position to insert new key
int pos = positionOf( search( cursor, primKey, readKey, keyCount ) ); int pos = positionOf( search( cursor, newKey, readKey, keyCount ) );


int keyCountAfterInsert = keyCount + 1; int keyCountAfterInsert = keyCount + 1;
int middlePos = middle( keyCountAfterInsert ); int middlePos = middle( keyCountAfterInsert );


// Update structurePropagation // Update structurePropagation
structurePropagation.hasSplit = true; structurePropagation.hasRightKeyInsert = true;
structurePropagation.left = current; structurePropagation.midChild = current;
structurePropagation.right = newRight; structurePropagation.rightChild = newRight;
if ( middlePos == pos ) if ( middlePos == pos )
{ {
layout.copyKey( primKey, structurePropagation.primKey ); layout.copyKey( newKey, structurePropagation.rightKey );
} }
else else
{ {
bTreeNode.keyAt( cursor, structurePropagation.primKey, pos < middlePos ? middlePos - 1 : middlePos ); bTreeNode.keyAt( cursor, structurePropagation.rightKey, pos < middlePos ? middlePos - 1 : middlePos );
} }


// Update new right // Update new right
Expand Down Expand Up @@ -528,7 +530,7 @@ private void splitInternal( PageCursor cursor, StructurePropagation<KEY> structu
// ... insert // ... insert
if ( countBeforePos >= 0 ) if ( countBeforePos >= 0 )
{ {
bTreeNode.insertKeyAt( rightCursor, primKey, countBeforePos, countBeforePos ); bTreeNode.insertKeyAt( rightCursor, newKey, countBeforePos, countBeforePos );
} }
// ... second copy // ... second copy
int countAfterPos = keyCount - pos; int countAfterPos = keyCount - pos;
Expand Down Expand Up @@ -573,7 +575,7 @@ private void splitInternal( PageCursor cursor, StructurePropagation<KEY> structu
bTreeNode.setKeyCount( cursor, middlePos ); bTreeNode.setKeyCount( cursor, middlePos );
if ( pos < middlePos ) if ( pos < middlePos )
{ {
bTreeNode.insertKeyAt( cursor, primKey, pos, middlePos - 1 ); bTreeNode.insertKeyAt( cursor, newKey, pos, middlePos - 1 );
bTreeNode.insertChildAt( cursor, newRightChild, pos + 1, middlePos - 1, bTreeNode.insertChildAt( cursor, newRightChild, pos + 1, middlePos - 1,
stableGeneration, unstableGeneration ); stableGeneration, unstableGeneration );
} }
Expand Down Expand Up @@ -720,17 +722,17 @@ private void splitLeaf( PageCursor cursor, StructurePropagation<KEY> structurePr
// We now have everything we need to start working on newRight // We now have everything we need to start working on newRight
// and everything that needs to be updated in left has been so. // and everything that needs to be updated in left has been so.


structurePropagation.hasSplit = true; structurePropagation.hasRightKeyInsert = true;
structurePropagation.left = current; structurePropagation.midChild = current;
structurePropagation.right = newRight; structurePropagation.rightChild = newRight;


if ( middlePos == pos ) if ( middlePos == pos )
{ {
layout.copyKey( newKey, structurePropagation.primKey ); layout.copyKey( newKey, structurePropagation.rightKey );
} }
else else
{ {
bTreeNode.keyAt( cursor, structurePropagation.primKey, pos < middlePos ? middlePos - 1 : middlePos ); bTreeNode.keyAt( cursor, structurePropagation.rightKey, pos < middlePos ? middlePos - 1 : middlePos );
} }


// Update new right // Update new right
Expand Down Expand Up @@ -839,7 +841,7 @@ VALUE remove( PageCursor cursor, StructurePropagation<KEY> structurePropagation,
return null; return null;
} }


while ( structurePropagation.hasNewGen ) while ( structurePropagation.hasMidChildUpdate )
{ {
int pos = levels[currentLevel].childPos; int pos = levels[currentLevel].childPos;
if ( !popLevel( cursor ) ) if ( !popLevel( cursor ) )
Expand All @@ -848,10 +850,11 @@ VALUE remove( PageCursor cursor, StructurePropagation<KEY> structurePropagation,
break; break;
} }


if ( structurePropagation.hasNewGen ) if ( structurePropagation.hasMidChildUpdate )
{ {
structurePropagation.hasNewGen = false; structurePropagation.hasMidChildUpdate = false;
bTreeNode.setChildAt( cursor, structurePropagation.left, pos, stableGeneration, unstableGeneration ); bTreeNode.setChildAt( cursor, structurePropagation.midChild, pos,
stableGeneration, unstableGeneration );
} }
} }


Expand Down Expand Up @@ -974,8 +977,8 @@ private void createUnstableVersionIfNeeded( PageCursor cursor, StructurePropagat
bTreeNode.goTo( cursor, "new gen", newGenId ); bTreeNode.goTo( cursor, "new gen", newGenId );


// Propagate structure change // Propagate structure change
structurePropagation.hasNewGen = true; structurePropagation.hasMidChildUpdate = true;
structurePropagation.left = newGenId; structurePropagation.midChild = newGenId;


idProvider.releaseId( stableGeneration, unstableGeneration, oldGenId ); idProvider.releaseId( stableGeneration, unstableGeneration, oldGenId );
} }
Expand Down
Expand Up @@ -22,28 +22,67 @@
/** /**
* Means of communicating information about splits, caused by insertion, from lower levels of the tree up to parent * Means of communicating information about splits, caused by insertion, from lower levels of the tree up to parent
* and potentially all the way up to the root. * and potentially all the way up to the root.
* <ul>
* <li> {@link #midChild} - new version of the child that was traversed to/through while traversing down the tree.
* <li> {@link #leftChild} - new version of left sibling to {@link #midChild}.
* <li> {@link #rightChild} - new right sibling to {@link #midChild} (not new version, completely new right sibling).
* <li> {@link #leftKey} - if position of {@link #midChild} pointer in node is {@code n} then {@link #leftKey} should
* replace key at position {@code n-1}. If {@code n==0} then {@link #leftKey} does not fit here and must be passed
* along one level further up the tree.
* <li> {@link #rightKey} - new key to be inserted at position {@code n} (if position of {@link #midChild} is
* {@code n}) together with {@link #rightChild}.
* </ul>
* If position of {@link #midChild} {@code n > 0}.
* <pre>
* Current level-> [...,leftKey,rightKey,...]
* ╱ │ ╲
* leftChild midChild rightChild
* ╱ │ ╲
* v v v
* Child nodes-> [...] <───> [...] <────> [...]
* </pre>
* If position of {@link #midChild} {@code n == 0}.
* <pre>
* *
* Parent node-> [...,leftKey,...]
* ┌────────┘ └────────┐
* v v
* Current level-> [...] <───────────> [rightKey,...]
* │ │ ╲
* leftChild midChild rightChild
* │ │ ╲
* v v v
* Child nodes-> [...] <───────> [...] <───> [...]
*
* </pre>
* @param <KEY> type of key. * @param <KEY> type of key.
*/ */
class StructurePropagation<KEY> class StructurePropagation<KEY>
{ {
boolean hasNewGen; boolean hasLeftChildUpdate;
boolean hasSplit; boolean hasMidChildUpdate;
final KEY primKey; boolean hasRightKeyInsert;
long left; boolean hasLeftKeyReplace;
long right; final KEY leftKey;
final KEY rightKey;
long leftChild;
long midChild;
long rightChild;


StructurePropagation( KEY primKey ) StructurePropagation( KEY leftKey, KEY rightKey )
{ {
this.primKey = primKey; this.leftKey = leftKey;
this.rightKey = rightKey;
} }


/** /**
* Clear booleans indicating change has occurred. * Clear booleans indicating change has occurred.
*/ */
void clear() void clear()
{ {
hasNewGen = false; hasLeftChildUpdate = false;
hasSplit = false; hasMidChildUpdate = false;
hasRightKeyInsert = false;
hasLeftKeyReplace = false;
} }
} }
Expand Up @@ -88,7 +88,7 @@ public void shouldDetectUnusedPages() throws Exception
cursor.next( idProvider.acquireNewId( stableGeneration, unstableGeneration ) ); cursor.next( idProvider.acquireNewId( stableGeneration, unstableGeneration ) );
node.initializeLeaf( cursor, stableGeneration, unstableGeneration ); node.initializeLeaf( cursor, stableGeneration, unstableGeneration );
logic.initialize( cursor ); logic.initialize( cursor );
StructurePropagation<MutableLong> structure = new StructurePropagation<>( layout.newKey() ); StructurePropagation<MutableLong> structure = new StructurePropagation<>( layout.newKey(), layout.newKey() );
MutableLong key = layout.newKey(); MutableLong key = layout.newKey();
for ( int g = 0, k = 0; g < 3; g++ ) for ( int g = 0, k = 0; g < 3; g++ )
{ {
Expand All @@ -97,17 +97,19 @@ public void shouldDetectUnusedPages() throws Exception
key.setValue( k ); key.setValue( k );
logic.insert( cursor, structure, key, key, ValueMergers.overwrite(), logic.insert( cursor, structure, key, key, ValueMergers.overwrite(),
stableGeneration, unstableGeneration ); stableGeneration, unstableGeneration );
if ( structure.hasSplit ) if ( structure.hasRightKeyInsert )
{ {
goTo( cursor, "new root", idProvider.acquireNewId( stableGeneration, unstableGeneration ) ); goTo( cursor, "new root",
idProvider.acquireNewId( stableGeneration, unstableGeneration ) );
node.initializeInternal( cursor, stableGeneration, unstableGeneration ); node.initializeInternal( cursor, stableGeneration, unstableGeneration );
node.insertKeyAt( cursor, structure.primKey, 0, 0 ); node.insertKeyAt( cursor, structure.rightKey, 0, 0 );
node.setKeyCount( cursor, 1 ); node.setKeyCount( cursor, 1 );
node.setChildAt( cursor, structure.left, 0, stableGeneration, unstableGeneration ); node.setChildAt( cursor, structure.midChild, 0, stableGeneration, unstableGeneration );
node.setChildAt( cursor, structure.right, 1, stableGeneration, unstableGeneration ); node.setChildAt( cursor, structure.rightChild, 1,
stableGeneration, unstableGeneration );
logic.initialize( cursor ); logic.initialize( cursor );
} }
if ( structure.hasNewGen ) if ( structure.hasMidChildUpdate )
{ {
logic.initialize( cursor ); logic.initialize( cursor );
} }
Expand Down

0 comments on commit a8eb7bc

Please sign in to comment.