Skip to content

Commit

Permalink
Further preparation in Layout for dynamic size
Browse files Browse the repository at this point in the history
- layout.keySize take key
- layout.readKey take keySize
- TreeNode.insertSlotAt and removeSlotAt move to parent (TreeNode)
  • Loading branch information
burqen committed Jan 16, 2018
1 parent 0bcfdb3 commit 48b1607
Show file tree
Hide file tree
Showing 7 changed files with 72 additions and 49 deletions.
Expand Up @@ -40,6 +40,8 @@
*/ */
public interface Layout<KEY, VALUE> extends Comparator<KEY> public interface Layout<KEY, VALUE> extends Comparator<KEY>
{ {
int FIXED_SIZE_KEY = 0;

/** /**
* @return new key instance. * @return new key instance.
*/ */
Expand All @@ -60,9 +62,10 @@ public interface Layout<KEY, VALUE> extends Comparator<KEY>
VALUE newValue(); VALUE newValue();


/** /**
* @return size, in bytes, of a key. * @param key for which to give size.
* @return size, in bytes, of given key.
*/ */
int keySize(); int keySize( KEY key );


/** /**
* @return size, in bytes, of a value. * @return size, in bytes, of a value.
Expand All @@ -87,11 +90,11 @@ public interface Layout<KEY, VALUE> extends Comparator<KEY>


/** /**
* Reads key contents at {@code cursor} at its current offset into {@code key}. * Reads key contents at {@code cursor} at its current offset into {@code key}.
* * @param cursor {@link PageCursor} to read from, at current offset.
* @param cursor {@link PageCursor} to read from, at current offset.
* @param into key instances to read into. * @param into key instances to read into.
* @param keySize
*/ */
void readKey( PageCursor cursor, KEY into ); void readKey( PageCursor cursor, KEY into, int keySize );


/** /**
* Reads value contents at {@code cursor} at its current offset into {@code value}. * Reads value contents at {@code cursor} at its current offset into {@code value}.
Expand Down Expand Up @@ -202,7 +205,7 @@ public String toString()
{ {
return format( "%s[version:%d.%d, identifier:%d, keySize:%d, valueSize:%d]", return format( "%s[version:%d.%d, identifier:%d, keySize:%d, valueSize:%d]",
getClass().getSimpleName(), majorVersion(), minorVersion(), identifier(), getClass().getSimpleName(), majorVersion(), minorVersion(), identifier(),
keySize(), valueSize() ); keySize( null ), valueSize() );
} }


@Override @Override
Expand Down Expand Up @@ -238,7 +241,7 @@ public Object newValue()
} }


@Override @Override
public int keySize() public int keySize( Object key )
{ {
throw new UnsupportedOperationException( "Not allowed with read only layout" ); throw new UnsupportedOperationException( "Not allowed with read only layout" );
} }
Expand All @@ -262,7 +265,7 @@ public void writeValue( PageCursor cursor, Object value )
} }


@Override @Override
public void readKey( PageCursor cursor, Object into ) public void readKey( PageCursor cursor, Object into, int keySize )
{ {
throw new UnsupportedOperationException( "Not allowed with read only layout" ); throw new UnsupportedOperationException( "Not allowed with read only layout" );
} }
Expand Down
Expand Up @@ -84,14 +84,14 @@ enum Type
static final int BYTE_POS_RIGHTSIBLING = BYTE_POS_KEYCOUNT + Integer.BYTES; static final int BYTE_POS_RIGHTSIBLING = BYTE_POS_KEYCOUNT + Integer.BYTES;
static final int BYTE_POS_LEFTSIBLING = BYTE_POS_RIGHTSIBLING + SIZE_PAGE_REFERENCE; static final int BYTE_POS_LEFTSIBLING = BYTE_POS_RIGHTSIBLING + SIZE_PAGE_REFERENCE;
static final int BYTE_POS_SUCCESSOR = BYTE_POS_LEFTSIBLING + SIZE_PAGE_REFERENCE; static final int BYTE_POS_SUCCESSOR = BYTE_POS_LEFTSIBLING + SIZE_PAGE_REFERENCE;
static final int HEADER_LENGTH = BYTE_POS_SUCCESSOR + SIZE_PAGE_REFERENCE; static final int BASE_HEADER_LENGTH = BYTE_POS_SUCCESSOR + SIZE_PAGE_REFERENCE;


static final byte LEAF_FLAG = 1; static final byte LEAF_FLAG = 1;
static final byte INTERNAL_FLAG = 0; static final byte INTERNAL_FLAG = 0;
static final long NO_NODE_FLAG = 0; static final long NO_NODE_FLAG = 0;


final Layout<KEY,VALUE> layout; final Layout<KEY,VALUE> layout;
private final int pageSize; final int pageSize;


TreeNode( int pageSize, Layout<KEY,VALUE> layout ) TreeNode( int pageSize, Layout<KEY,VALUE> layout )
{ {
Expand Down Expand Up @@ -218,6 +218,30 @@ long pointerGeneration( PageCursor cursor, long readResult )


// BODY METHODS // BODY METHODS


/**
* Moves items (key/value/child) one step to the right, which means rewriting all items of the particular type
* from pos - itemCount.
* itemCount is keyCount for key and value, but keyCount+1 for children.
*/
static void insertSlotsAt( PageCursor cursor, int pos, int numberOfSlots, int itemCount, int baseOffset,
int itemSize )
{
for ( int posToMoveRight = itemCount - 1, offset = baseOffset + posToMoveRight * itemSize;
posToMoveRight >= pos; posToMoveRight--, offset -= itemSize )
{
cursor.copyTo( offset, cursor, offset + itemSize * numberOfSlots, itemSize );
}
}

static void removeSlotAt( PageCursor cursor, int pos, int itemCount, int baseOffset, int itemSize )
{
for ( int posToMoveLeft = pos + 1, offset = baseOffset + posToMoveLeft * itemSize;
posToMoveLeft < itemCount; posToMoveLeft++, offset += itemSize )
{
cursor.copyTo( offset, cursor, offset - itemSize, itemSize );
}
}

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


abstract void insertKeyAndRightChildAt( PageCursor cursor, KEY key, long child, int pos, int keyCount, abstract void insertKeyAndRightChildAt( PageCursor cursor, KEY key, long child, int pos, int keyCount,
Expand Down
@@ -1,11 +1,31 @@
/*
* Copyright (c) 2002-2017 "Neo Technology,"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.neo4j.index.internal.gbptree; package org.neo4j.index.internal.gbptree;


import org.neo4j.io.pagecache.PageCursor; import org.neo4j.io.pagecache.PageCursor;


import static org.neo4j.index.internal.gbptree.GenerationSafePointerPair.read; import static org.neo4j.index.internal.gbptree.GenerationSafePointerPair.read;
import static org.neo4j.index.internal.gbptree.Layout.FIXED_SIZE_KEY;
import static org.neo4j.index.internal.gbptree.TreeNode.Type.INTERNAL; import static org.neo4j.index.internal.gbptree.TreeNode.Type.INTERNAL;


public class TreeNodeFixedSize<KEY,VALUE> extends TreeNode<KEY,VALUE> class TreeNodeFixedSize<KEY,VALUE> extends TreeNode<KEY,VALUE>
{ {
private final int internalMaxKeyCount; private final int internalMaxKeyCount;
private final int leafMaxKeyCount; private final int leafMaxKeyCount;
Expand All @@ -15,11 +35,11 @@ public class TreeNodeFixedSize<KEY,VALUE> extends TreeNode<KEY,VALUE>
TreeNodeFixedSize( int pageSize, Layout<KEY,VALUE> layout ) TreeNodeFixedSize( int pageSize, Layout<KEY,VALUE> layout )
{ {
super( pageSize, layout ); super( pageSize, layout );
this.keySize = layout.keySize(); this.keySize = layout.keySize( null );
this.valueSize = layout.valueSize(); this.valueSize = layout.valueSize();
this.internalMaxKeyCount = Math.floorDiv( pageSize - (HEADER_LENGTH + SIZE_PAGE_REFERENCE), this.internalMaxKeyCount = Math.floorDiv( pageSize - (BASE_HEADER_LENGTH + SIZE_PAGE_REFERENCE),
keySize + SIZE_PAGE_REFERENCE); keySize + SIZE_PAGE_REFERENCE);
this.leafMaxKeyCount = Math.floorDiv( pageSize - HEADER_LENGTH, keySize + valueSize ); this.leafMaxKeyCount = Math.floorDiv( pageSize - BASE_HEADER_LENGTH, keySize + valueSize );


if ( internalMaxKeyCount < 2 ) if ( internalMaxKeyCount < 2 )
{ {
Expand All @@ -34,30 +54,6 @@ public class TreeNodeFixedSize<KEY,VALUE> extends TreeNode<KEY,VALUE>
} }
} }


/**
* Moves items (key/value/child) one step to the right, which means rewriting all items of the particular type
* from pos - itemCount.
* itemCount is keyCount for key and value, but keyCount+1 for children.
*/
private static void insertSlotsAt( PageCursor cursor, int pos, int numberOfSlots, int itemCount, int baseOffset,
int itemSize )
{
for ( int posToMoveRight = itemCount - 1, offset = baseOffset + posToMoveRight * itemSize;
posToMoveRight >= pos; posToMoveRight--, offset -= itemSize )
{
cursor.copyTo( offset, cursor, offset + itemSize * numberOfSlots, itemSize );
}
}

private static void removeSlotAt( PageCursor cursor, int pos, int itemCount, int baseOffset, int itemSize )
{
for ( int posToMoveLeft = pos + 1, offset = baseOffset + posToMoveLeft * itemSize;
posToMoveLeft < itemCount; posToMoveLeft++, offset += itemSize )
{
cursor.copyTo( offset, cursor, offset - itemSize, itemSize );
}
}

private static int childSize() private static int childSize()
{ {
return SIZE_PAGE_REFERENCE; return SIZE_PAGE_REFERENCE;
Expand All @@ -67,7 +63,7 @@ private static int childSize()
KEY keyAt( PageCursor cursor, KEY into, int pos, Type type ) KEY keyAt( PageCursor cursor, KEY into, int pos, Type type )
{ {
cursor.setOffset( keyOffset( pos ) ); cursor.setOffset( keyOffset( pos ) );
layout.readKey( cursor, into ); layout.readKey( cursor, into, FIXED_SIZE_KEY );
return into; return into;
} }


Expand Down Expand Up @@ -224,18 +220,18 @@ boolean reasonableKeyCount( int keyCount )


private int keyOffset( int pos ) private int keyOffset( int pos )
{ {
return HEADER_LENGTH + pos * keySize; return BASE_HEADER_LENGTH + pos * keySize;
} }


private int valueOffset( int pos ) private int valueOffset( int pos )
{ {
return HEADER_LENGTH + leafMaxKeyCount * keySize + pos * valueSize; return BASE_HEADER_LENGTH + leafMaxKeyCount * keySize + pos * valueSize;
} }


@Override @Override
int childOffset( int pos ) int childOffset( int pos )
{ {
return HEADER_LENGTH + internalMaxKeyCount * keySize + pos * SIZE_PAGE_REFERENCE; return BASE_HEADER_LENGTH + internalMaxKeyCount * keySize + pos * SIZE_PAGE_REFERENCE;
} }


@Override @Override
Expand Down
Expand Up @@ -72,7 +72,7 @@ public MutableLong newValue()
} }


@Override @Override
public int keySize() public int keySize( MutableLong key )
{ {
// pad the key here to affect the max key count, useful to get odd or even max key count // pad the key here to affect the max key count, useful to get odd or even max key count
return Long.BYTES + keyPadding; return Long.BYTES + keyPadding;
Expand All @@ -97,7 +97,7 @@ public void writeValue( PageCursor cursor, MutableLong value )
} }


@Override @Override
public void readKey( PageCursor cursor, MutableLong into ) public void readKey( PageCursor cursor, MutableLong into, int keySize )
{ {
into.setValue( cursor.getLong() ); into.setValue( cursor.getLong() );
} }
Expand Down
Expand Up @@ -412,7 +412,7 @@ public void shouldAssertPageSizeBigEnoughForAtLeastTwoKeys() throws Exception
// WHEN // WHEN
try try
{ {
new TreeNodeFixedSize<>( TreeNode.HEADER_LENGTH + layout.keySize() + layout.valueSize(), layout ); new TreeNodeFixedSize<>( TreeNode.BASE_HEADER_LENGTH + layout.keySize( null ) + layout.valueSize(), layout );
fail( "Should have failed" ); fail( "Should have failed" );
} }
catch ( MetadataMismatchException e ) catch ( MetadataMismatchException e )
Expand Down
Expand Up @@ -79,7 +79,7 @@ public LabelScanValue newValue()
} }


@Override @Override
public int keySize() public int keySize( LabelScanKey key )
{ {
return KEY_SIZE; return KEY_SIZE;
} }
Expand Down Expand Up @@ -110,7 +110,7 @@ public void writeValue( PageCursor cursor, LabelScanValue value )
} }


@Override @Override
public void readKey( PageCursor cursor, LabelScanKey into ) public void readKey( PageCursor cursor, LabelScanKey into, int keySize )
{ {
into.labelId = cursor.getInt(); into.labelId = cursor.getInt();
into.idRange = get6ByteLong( cursor ); into.idRange = get6ByteLong( cursor );
Expand Down
Expand Up @@ -50,7 +50,7 @@ public NativeSchemaValue newValue()
} }


@Override @Override
public int keySize() public int keySize( NumberSchemaKey key )
{ {
return NumberSchemaKey.SIZE; return NumberSchemaKey.SIZE;
} }
Expand All @@ -75,7 +75,7 @@ public void writeValue( PageCursor cursor, NativeSchemaValue value )
} }


@Override @Override
public void readKey( PageCursor cursor, NumberSchemaKey into ) public void readKey( PageCursor cursor, NumberSchemaKey into, int keySize )
{ {
into.type = cursor.getByte(); into.type = cursor.getByte();
into.rawValueBits = cursor.getLong(); into.rawValueBits = cursor.getLong();
Expand Down

0 comments on commit 48b1607

Please sign in to comment.