Skip to content

Commit

Permalink
Immutable information in RelationshipProxy
Browse files Browse the repository at this point in the history
Since the start node, end node, and type of a relationship never
changes, this information can be kept within the RelationshipProxy
object. Doing so does not require significant storage overhead, with the
current address sizes (nodeId=35bit, relationshipId=35bit, typeId=16bit)
this information (together with the id of the relationship) occupies 212
bits, which can be stored in 16 bytes (128 bits). The implementation in
this changeset packs the high bits of the start/end node ids and the
relationship id into separate nibbles of a 16 bit (short) fields.

This limits the number of roundtrips required down to the store layer.
  • Loading branch information
thobe committed Jan 8, 2015
1 parent 27806d6 commit 7dd9f0b
Show file tree
Hide file tree
Showing 9 changed files with 136 additions and 109 deletions.
Expand Up @@ -110,7 +110,6 @@
import org.neo4j.kernel.impl.core.NodeProxy.NodeActions; import org.neo4j.kernel.impl.core.NodeProxy.NodeActions;
import org.neo4j.kernel.impl.core.PropertyKeyTokenHolder; import org.neo4j.kernel.impl.core.PropertyKeyTokenHolder;
import org.neo4j.kernel.impl.core.ReadOnlyTokenCreator; import org.neo4j.kernel.impl.core.ReadOnlyTokenCreator;
import org.neo4j.kernel.impl.core.RelationshipData;
import org.neo4j.kernel.impl.core.RelationshipProxy.RelationshipActions; import org.neo4j.kernel.impl.core.RelationshipProxy.RelationshipActions;
import org.neo4j.kernel.impl.core.RelationshipTypeTokenHolder; import org.neo4j.kernel.impl.core.RelationshipTypeTokenHolder;
import org.neo4j.kernel.impl.core.StartupStatistics; import org.neo4j.kernel.impl.core.StartupStatistics;
Expand All @@ -131,6 +130,8 @@
import org.neo4j.kernel.impl.locking.ResourceTypes; import org.neo4j.kernel.impl.locking.ResourceTypes;
import org.neo4j.kernel.impl.locking.community.CommunityLockManger; import org.neo4j.kernel.impl.locking.community.CommunityLockManger;
import org.neo4j.kernel.impl.pagecache.LifecycledPageCache; import org.neo4j.kernel.impl.pagecache.LifecycledPageCache;
import org.neo4j.kernel.impl.query.QueryEngineProvider;
import org.neo4j.kernel.impl.query.QueryExecutionEngine;
import org.neo4j.kernel.impl.query.QueryExecutionKernelException; import org.neo4j.kernel.impl.query.QueryExecutionKernelException;
import org.neo4j.kernel.impl.store.NeoStore; import org.neo4j.kernel.impl.store.NeoStore;
import org.neo4j.kernel.impl.store.StoreFactory; import org.neo4j.kernel.impl.store.StoreFactory;
Expand Down Expand Up @@ -168,11 +169,10 @@
import org.neo4j.kernel.logging.Logging; import org.neo4j.kernel.logging.Logging;
import org.neo4j.kernel.logging.RollingLogMonitor; import org.neo4j.kernel.logging.RollingLogMonitor;
import org.neo4j.kernel.monitoring.Monitors; import org.neo4j.kernel.monitoring.Monitors;
import org.neo4j.kernel.impl.query.QueryEngineProvider;
import org.neo4j.kernel.impl.query.QueryExecutionEngine;
import org.neo4j.tooling.GlobalGraphOperations; import org.neo4j.tooling.GlobalGraphOperations;


import static java.lang.String.format; import static java.lang.String.format;

import static org.neo4j.collection.primitive.PrimitiveLongCollections.map; import static org.neo4j.collection.primitive.PrimitiveLongCollections.map;
import static org.neo4j.helpers.Settings.STRING; import static org.neo4j.helpers.Settings.STRING;
import static org.neo4j.helpers.Settings.setting; import static org.neo4j.helpers.Settings.setting;
Expand Down Expand Up @@ -773,21 +773,6 @@ public Node newNodeProxy( long nodeId )
return nodeManager.newNodeProxyById( nodeId ); return nodeManager.newNodeProxyById( nodeId );
} }


@Override
public RelationshipData getRelationshipData( long relationshipId )
{
try ( Statement statement = threadToTransactionBridge.instance() )
{
RelationshipData data = new RelationshipData();
statement.readOperations().relationshipVisit( relationshipId, data );
return data;
}
catch ( EntityNotFoundException e )
{
throw new NotFoundException( e );
}
}

@Override @Override
public RelationshipType getRelationshipTypeById( int type ) public RelationshipType getRelationshipTypeById( int type )
{ {
Expand Down Expand Up @@ -833,10 +818,22 @@ public void failTransaction()
} }


@Override @Override
public Relationship newRelationshipProxy( long id ) public Relationship lazyRelationshipProxy( long id )
{ {
return nodeManager.newRelationshipProxyById( id ); return nodeManager.newRelationshipProxyById( id );
} }

@Override
public Relationship newRelationshipProxy( long id )
{
return nodeManager.newRelationshipProxy( id );
}

@Override
public Relationship newRelationshipProxy( long id, long startNodeId, int typeId, long endNodeId )
{
return nodeManager.newRelationshipProxy( id, startNodeId, typeId, endNodeId );
}
}; };
} }


Expand Down Expand Up @@ -1101,7 +1098,7 @@ public Relationship getRelationshipById( long id )
throw new NotFoundException( format( "Relationship %d not found", id ) ); throw new NotFoundException( format( "Relationship %d not found", id ) );
} }


return nodeManager.newRelationshipProxyById( id ); return nodeManager.newRelationshipProxy( id );
} }
} }


Expand Down
Expand Up @@ -23,8 +23,11 @@
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;


import org.neo4j.graphdb.Node; import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.NotFoundException;
import org.neo4j.graphdb.Relationship; import org.neo4j.graphdb.Relationship;
import org.neo4j.kernel.PropertyTracker; import org.neo4j.kernel.PropertyTracker;
import org.neo4j.kernel.api.Statement;
import org.neo4j.kernel.api.exceptions.EntityNotFoundException;
import org.neo4j.kernel.lifecycle.LifecycleAdapter; import org.neo4j.kernel.lifecycle.LifecycleAdapter;


import static java.lang.System.currentTimeMillis; import static java.lang.System.currentTimeMillis;
Expand Down Expand Up @@ -69,12 +72,34 @@ public NodeProxy newNodeProxyById( long id )
return new NodeProxy( nodeActions, id ); return new NodeProxy( nodeActions, id );
} }


/** Returns a "lazy" proxy, where additional fields are initialized on access. */
@Override @Override
public RelationshipProxy newRelationshipProxyById( long id ) public RelationshipProxy newRelationshipProxyById( long id )
{ {
return new RelationshipProxy( relationshipActions, id ); return new RelationshipProxy( relationshipActions, id );
} }


/** Returns a fully initialized proxy. */
public RelationshipProxy newRelationshipProxy( long id )
{
try ( Statement statement = threadToTransactionBridge.instance() )
{
RelationshipProxy proxy = new RelationshipProxy( relationshipActions, id );
statement.readOperations().relationshipVisit( id, proxy );
return proxy;
}
catch ( EntityNotFoundException e )
{
throw new NotFoundException( e );
}
}

/** Returns a fully initialized proxy. */
public RelationshipProxy newRelationshipProxy( long id, long startNodeId, int typeId, long endNodeId )
{
return new RelationshipProxy( relationshipActions, id, startNodeId, typeId, endNodeId );
}

@Override @Override
public GraphPropertiesImpl newGraphProperties() public GraphPropertiesImpl newGraphProperties()
{ {
Expand Down
Expand Up @@ -83,7 +83,11 @@ public interface NodeActions


void failTransaction(); void failTransaction();


Relationship lazyRelationshipProxy( long id );

Relationship newRelationshipProxy( long id ); Relationship newRelationshipProxy( long id );

Relationship newRelationshipProxy( long id, long startNodeId, int typeId, long endNodeId );
} }


private final NodeActions actions; private final NodeActions actions;
Expand Down Expand Up @@ -431,16 +435,16 @@ public Relationship createRelationshipTo( Node otherNode, RelationshipType type
throw new IllegalArgumentException( "Other node is null." ); throw new IllegalArgumentException( "Other node is null." );
} }
// TODO: This is the checks we would like to do, but we have tests that expect to mix nodes... // TODO: This is the checks we would like to do, but we have tests that expect to mix nodes...
//if ( !(otherNode instanceof NodeProxy) || (((NodeProxy) otherNode).nodeLookup != nodeLookup) ) //if ( !(otherNode instanceof NodeProxy) || (((NodeProxy) otherNode).actions != actions) )
//{ //{
// throw new IllegalArgumentException( "Nodes do not belong to same graph database." ); // throw new IllegalArgumentException( "Nodes do not belong to same graph database." );
//} //}
try ( Statement statement = actions.statement() ) try ( Statement statement = actions.statement() )
{ {
int relationshipTypeId = statement.tokenWriteOperations().relationshipTypeGetOrCreateForName( type.name() ); int relationshipTypeId = statement.tokenWriteOperations().relationshipTypeGetOrCreateForName( type.name() );
return actions.newRelationshipProxy( long relationshipId = statement.dataWriteOperations()
statement.dataWriteOperations() .relationshipCreate( relationshipTypeId, nodeId, otherNode.getId() );
.relationshipCreate( relationshipTypeId, nodeId, otherNode.getId() ) ); return actions.newRelationshipProxy( relationshipId, nodeId, relationshipTypeId, otherNode.getId() );
} }
catch ( IllegalTokenNameException | RelationshipTypeIdNotFoundKernelException e ) catch ( IllegalTokenNameException | RelationshipTypeIdNotFoundKernelException e )
{ {
Expand Down

This file was deleted.

0 comments on commit 7dd9f0b

Please sign in to comment.