Skip to content

Commit

Permalink
More record object reuse in new store cursor
Browse files Browse the repository at this point in the history
  • Loading branch information
tinwelint committed Feb 15, 2015
1 parent e895398 commit 9d359a9
Show file tree
Hide file tree
Showing 13 changed files with 87 additions and 40 deletions.
Expand Up @@ -77,8 +77,13 @@ interface RecordCursor<RECORD> extends AutoCloseable
{
// TODO: Note that we need some way to force the page-cache retry operation upstream here

/** Read a full record from the current position. */
RECORD record();
/** Read a full record from the current position. The returned instance is potentially the same
* as the one returned from other calls to this method. */
RECORD reusedRecord();

/** Read a full record from the current position. The returned instance is a new instance,
* unlike {@link #reusedRecord()}. */
RECORD clonedRecord();

/** Is the record at the current position in use? */
boolean inUse();
Expand Down
Expand Up @@ -83,6 +83,12 @@ public long id( NodeRecord nodeRecord )
return nodeRecord.getId();
}

@Override
public NodeRecord newRecord( long id )
{
return new NodeRecord( id );
}

@Override
public void serialize( PageCursor cursor, int offset, NodeRecord record )
{
Expand Down Expand Up @@ -120,9 +126,9 @@ public void serialize( PageCursor cursor, int offset, NodeRecord record )
}

@Override
public NodeRecord deserialize( PageCursor cursor, int offset, long id )
public void deserialize( PageCursor cursor, int offset, long id, NodeRecord record )
{
NodeRecord record = new NodeRecord( id );
record.setId( id );
byte inUseByte = cursor.getByte(offset + IN_USE);
long nextRel = cursor.getUnsignedInt( offset + NEXT_REL_BASE );
long nextProp = cursor.getUnsignedInt(offset + NEXT_PROP_BASE);
Expand All @@ -140,7 +146,6 @@ public NodeRecord deserialize( PageCursor cursor, int offset, long id )
record.setNextProp( longFromIntAndMod( nextProp, propModifier ) );
record.setInUse( (inUseByte & 0x1) == 1 );
record.setLabelField( labels, Collections.<DynamicRecord>emptyList() );
return record;
}

@Override
Expand Down
Expand Up @@ -71,13 +71,19 @@ public static class RelationshipGroupRecordFormat implements StoreFormat.RecordF
@Override
public String recordName()
{
return "NodeRecord";
return "RelationshipGroupRecord";
}

@Override
public long id( RelationshipGroupRecord nodeRecord )
public long id( RelationshipGroupRecord record )
{
return nodeRecord.getId();
return record.getId();
}

@Override
public RelationshipGroupRecord newRecord( long id )
{
return new RelationshipGroupRecord( id, -1 );
}

@Override
Expand Down Expand Up @@ -113,7 +119,7 @@ public void serialize( PageCursor cursor, int offset, RelationshipGroupRecord re
}

@Override
public RelationshipGroupRecord deserialize( PageCursor cursor, int offset, long id )
public void deserialize( PageCursor cursor, int offset, long id, RelationshipGroupRecord record )
{
// [ , x] in use
// [ ,xxx ] high next id bits
Expand All @@ -130,16 +136,15 @@ public RelationshipGroupRecord deserialize( PageCursor cursor, int offset, long
long ownerLowBits = cursor.getUnsignedInt(offset + OWNER_LOW_BITS );
byte ownerHighBits = cursor.getByte(offset + OWNER_HIGH_BITS );

RelationshipGroupRecord record = new RelationshipGroupRecord( id, type );
record.setId( id );
record.setType( type );

record.setInUse( (inUseByte&0x1) > 0 );
record.setNext( longFromIntAndMod( nextLowBits, (inUseByte & 0xE) << 31 ) );
record.setFirstOut( longFromIntAndMod( nextOutLowBits, (inUseByte & 0x70) << 28 ) );
record.setFirstIn( longFromIntAndMod( nextInLowBits, (highByte & 0xE) << 31 ) );
record.setFirstLoop( longFromIntAndMod( nextLoopLowBits, (highByte & 0x70) << 28 ) );
record.setOwningNode( ownerLowBits | (((long) ownerHighBits) << 32) );

return record;
}

@Override
Expand Down
Expand Up @@ -72,13 +72,19 @@ public static class RelationshipRecordFormat implements StoreFormat.RecordFormat
@Override
public String recordName()
{
return "NodeRecord";
return "RelationshipRecord";
}

@Override
public long id( RelationshipRecord nodeRecord )
public long id( RelationshipRecord record )
{
return nodeRecord.getId();
return record.getId();
}

@Override
public RelationshipRecord newRecord( long id )
{
return new RelationshipRecord( id );
}

@Override
Expand Down Expand Up @@ -144,9 +150,9 @@ public void serialize( PageCursor cursor, int offset, RelationshipRecord record
}

@Override
public RelationshipRecord deserialize( PageCursor cursor, int offset, long id )
public void deserialize( PageCursor cursor, int offset, long id, RelationshipRecord record )
{
RelationshipRecord record = new RelationshipRecord( id );
record.setId( id );

// [ , x] in use flag
// [ ,xxx ] first node high order bits
Expand Down Expand Up @@ -179,8 +185,6 @@ public RelationshipRecord deserialize( PageCursor cursor, int offset, long id )
record.setFirstInFirstChain( (extraByte & 0x1) != 0 );
record.setFirstInSecondChain( (extraByte & 0x2) != 0 );
record.setNextProp( longFromIntAndMod( nextProp, (inUseByte & 0xF0L) << 28 ) );

return record;
}

@Override
Expand Down
Expand Up @@ -22,7 +22,7 @@

public class RelationshipGroupRecord extends Abstract64BitRecord
{
private final int type;
private int type;
private long next = Record.NO_NEXT_RELATIONSHIP.intValue();
private long firstOut = Record.NO_NEXT_RELATIONSHIP.intValue();
private long firstIn = Record.NO_NEXT_RELATIONSHIP.intValue();
Expand Down Expand Up @@ -62,6 +62,11 @@ public int getType()
return type;
}

public void setType( int type )
{
this.type = type;
}

public long getFirstOut()
{
return firstOut;
Expand Down
Expand Up @@ -19,19 +19,19 @@
*/
package org.neo4j.kernel.impl.store.standard;

import static org.neo4j.io.pagecache.PagedFile.PF_READ_AHEAD;
import static org.neo4j.io.pagecache.PagedFile.PF_SHARED_LOCK;
import static org.neo4j.io.pagecache.PagedFile.PF_TRANSIENT;
import static org.neo4j.kernel.impl.store.format.Store.SF_REVERSE_CURSOR;
import static org.neo4j.kernel.impl.store.format.Store.SF_SCAN;
import static org.neo4j.kernel.impl.store.standard.StoreFormat.RecordFormat;

import java.io.IOException;

import org.neo4j.io.pagecache.PageCursor;
import org.neo4j.io.pagecache.PagedFile;
import org.neo4j.kernel.impl.store.UnderlyingStorageException;
import org.neo4j.kernel.impl.store.format.Store;
import org.neo4j.kernel.impl.store.standard.StoreFormat.RecordFormat;

import static org.neo4j.io.pagecache.PagedFile.PF_READ_AHEAD;
import static org.neo4j.io.pagecache.PagedFile.PF_SHARED_LOCK;
import static org.neo4j.io.pagecache.PagedFile.PF_TRANSIENT;
import static org.neo4j.kernel.impl.store.format.Store.SF_REVERSE_CURSOR;
import static org.neo4j.kernel.impl.store.format.Store.SF_SCAN;

/**
* A complete cursor implementation to be used on it's own or as a base class for building custom cursors.
Expand Down Expand Up @@ -61,6 +61,7 @@ public class BaseRecordCursor<RECORD, FORMAT extends RecordFormat<RECORD>> imple
protected PageCursor pageCursor;
protected long currentRecordId = -1;
protected int currentRecordOffset = -1;
protected RECORD record;

public BaseRecordCursor( PagedFile file, StoreToolkit toolkit, FORMAT format, int flags )
{
Expand All @@ -78,12 +79,22 @@ public BaseRecordCursor( PagedFile file, StoreToolkit toolkit, FORMAT format, in
this.currentRecordId = toolkit.highestKnownId() + 1;
this.stepSize = -1;
}
this.record = format.newRecord( -1 );
}

@Override
public RECORD reusedRecord()
{
format.deserialize( pageCursor, currentRecordOffset, currentRecordId, record );
return record;
}

@Override
public RECORD record()
public RECORD clonedRecord()
{
return format.deserialize( pageCursor, currentRecordOffset, currentRecordId );
RECORD result = format.newRecord( currentRecordId );
format.deserialize( pageCursor, currentRecordOffset, currentRecordId, result );
return result;
}

@Override
Expand Down
Expand Up @@ -96,10 +96,10 @@ public RECORD read( long id ) throws IOException
{
if ( cursor.next() )
{
RECORD record;
RECORD record = recordFormat.newRecord( id );
do
{
record = recordFormat.deserialize( cursor, offset, id );
recordFormat.deserialize( cursor, offset, id, record );
} while ( cursor.shouldRetry() );

return record;
Expand Down
Expand Up @@ -74,11 +74,13 @@ interface RecordFormat<RECORD>
/** Get the id from a record. */
long id( RECORD record );

RECORD newRecord( long id );

/** Serialize a full record at the specified offset. */
void serialize( PageCursor cursor, int offset, RECORD record );

/** Deserialize a full record at the specified offset. */
RECORD deserialize( PageCursor cursor, int offset, long id );
void deserialize( PageCursor cursor, int offset, long id, RECORD record );

/** Determine if a record at the specified offset is in use. */
boolean inUse( PageCursor cursor, int offset );
Expand Down
Expand Up @@ -36,16 +36,23 @@ public long id( TestRecord myRecord )
return myRecord.id;
}

@Override
public TestRecord newRecord( long id )
{
return new TestRecord( id, 0 );
}

@Override
public void serialize( PageCursor cursor, int offset, TestRecord myRecord )
{
cursor.putLong(offset, myRecord.value);
}

@Override
public TestRecord deserialize( PageCursor cursor, int offset, long id )
public void deserialize( PageCursor cursor, int offset, long id, TestRecord record )
{
return new TestRecord( id, cursor.getLong(offset) );
record.id = id;
record.value = cursor.getLong( offset );
}

@Override
Expand Down
Expand Up @@ -62,6 +62,6 @@ public void testCursorFieldReading() throws Exception
assertThat(cursor.recordId(), equalTo(12l));
assertThat(cursor.firstRelationship(), equalTo( 1l ));
assertThat(cursor.inUse(), equalTo(true));
assertThat(cursor.record().toString(), equalTo( record.toString() ) );
assertThat(cursor.reusedRecord().toString(), equalTo( record.toString() ) );
}
}
Expand Up @@ -24,17 +24,18 @@

import org.junit.Before;
import org.junit.Rule;
import org.neo4j.io.pagecache.monitoring.PageCacheMonitor;

import org.neo4j.io.pagecache.PageCursor;
import org.neo4j.io.pagecache.PagedFile;
import org.neo4j.io.pagecache.StubPageCursor;
import org.neo4j.io.pagecache.impl.muninn.MuninnPageCache;
import org.neo4j.io.pagecache.monitoring.PageCacheMonitor;
import org.neo4j.kernel.impl.store.format.Store;
import org.neo4j.kernel.impl.store.standard.StoreFormat;
import org.neo4j.kernel.impl.store.standard.StoreToolkit;
import org.neo4j.test.EphemeralFileSystemRule;

import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;

public abstract class RecordFormatTest<FORMAT extends StoreFormat<RECORD, CURSOR>,
RECORD,
Expand Down Expand Up @@ -73,7 +74,9 @@ public void setup() throws IOException
public void assertSerializes( RECORD record )
{
recordFormat.serialize( pageCursor, 0, record );
assertEquals( record.toString(), recordFormat.deserialize( pageCursor, 0, recordFormat.id( record ) ).toString() );
RECORD deserialized = recordFormat.newRecord( 0 );
recordFormat.deserialize( pageCursor, 0, recordFormat.id( record ), deserialized );
assertEquals( record.toString(), deserialized.toString() );
}

public void writeToPagedFile( RECORD record ) throws IOException
Expand Down
Expand Up @@ -57,6 +57,6 @@ public void testCursorFieldReading() throws Exception
// Then
assertThat(cursor.recordId(), equalTo(12l));
assertThat(cursor.inUse(), equalTo(true));
assertThat(cursor.record().toString(), equalTo( record.toString() ) );
assertThat(cursor.reusedRecord().toString(), equalTo( record.toString() ) );
}
}
Expand Up @@ -32,7 +32,7 @@ public static <R> List<R> records( Store<R, ? extends Store.RecordCursor<R>> sto
Store.RecordCursor<R> cursor = store.cursor(0);
while(cursor.next())
{
records.add(cursor.record());
records.add( cursor.clonedRecord() );
}
return records;
}
Expand Down

0 comments on commit 9d359a9

Please sign in to comment.