Skip to content

Commit

Permalink
Make GraphPropertiesProxy use Kernel API
Browse files Browse the repository at this point in the history
  • Loading branch information
pontusmelke committed Mar 1, 2018
1 parent 2f74c49 commit 76eb142
Showing 1 changed file with 140 additions and 71 deletions.
Expand Up @@ -20,23 +20,25 @@
package org.neo4j.kernel.impl.core; package org.neo4j.kernel.impl.core;


import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;


import org.neo4j.collection.primitive.PrimitiveIntIterator;
import org.neo4j.graphdb.ConstraintViolationException; import org.neo4j.graphdb.ConstraintViolationException;
import org.neo4j.graphdb.GraphDatabaseService; import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.NotFoundException; import org.neo4j.graphdb.NotFoundException;
import org.neo4j.graphdb.TransactionTerminatedException;
import org.neo4j.internal.kernel.api.PropertyCursor;
import org.neo4j.internal.kernel.api.TokenRead;
import org.neo4j.internal.kernel.api.exceptions.InvalidTransactionTypeKernelException; import org.neo4j.internal.kernel.api.exceptions.InvalidTransactionTypeKernelException;
import org.neo4j.internal.kernel.api.exceptions.PropertyKeyIdNotFoundKernelException; import org.neo4j.internal.kernel.api.exceptions.PropertyKeyIdNotFoundKernelException;
import org.neo4j.kernel.api.ReadOperations;
import org.neo4j.kernel.api.Statement;
import org.neo4j.kernel.api.StatementTokenNameLookup;
import org.neo4j.kernel.api.exceptions.PropertyNotFoundException;
import org.neo4j.internal.kernel.api.exceptions.schema.IllegalTokenNameException; import org.neo4j.internal.kernel.api.exceptions.schema.IllegalTokenNameException;
import org.neo4j.kernel.api.KernelTransaction;
import org.neo4j.kernel.api.Statement;
import org.neo4j.kernel.api.exceptions.Status;
import org.neo4j.kernel.impl.api.operations.KeyReadOperations; import org.neo4j.kernel.impl.api.operations.KeyReadOperations;
import org.neo4j.storageengine.api.EntityType;
import org.neo4j.values.storable.Value; import org.neo4j.values.storable.Value;
import org.neo4j.values.storable.Values; import org.neo4j.values.storable.Values;


Expand Down Expand Up @@ -65,11 +67,23 @@ public boolean hasProperty( String key )
return false; return false;
} }


try ( Statement statement = actions.statement() ) KernelTransaction transaction = safeAcquireTransaction();
int propertyKey = transaction.tokenRead().propertyKey( key );
if ( propertyKey == KeyReadOperations.NO_SUCH_PROPERTY_KEY )
{ {
int propertyKeyId = statement.readOperations().propertyKeyGetForName( key ); return false;
return statement.readOperations().graphHasProperty( propertyKeyId );
} }

PropertyCursor properties = transaction.propertyCursor();
transaction.dataRead().graphProperties( properties );
while ( properties.next() )
{
if ( propertyKey == properties.propertyKey() )
{
return true;
}
}
return false;
} }


@Override @Override
Expand All @@ -79,32 +93,29 @@ public Object getProperty( String key )
{ {
throw new IllegalArgumentException( "(null) property key is not allowed" ); throw new IllegalArgumentException( "(null) property key is not allowed" );
} }

KernelTransaction transaction = safeAcquireTransaction();
try ( Statement statement = actions.statement() ) int propertyKey = transaction.tokenRead().propertyKey( key );
if ( propertyKey == KeyReadOperations.NO_SUCH_PROPERTY_KEY )
{ {
try throw new NotFoundException( format( "No such property, '%s'.", key ) );
{ }
int propertyKeyId = statement.readOperations().propertyKeyGetForName( key );
if ( propertyKeyId == KeyReadOperations.NO_SUCH_PROPERTY_KEY )
{
throw new NotFoundException( format( "No such property, '%s'.", key ) );
}


Value value = statement.readOperations().graphGetProperty( propertyKeyId ); PropertyCursor properties = transaction.propertyCursor();
transaction.dataRead().graphProperties( properties );


while ( properties.next() )
{
if ( propertyKey == properties.propertyKey() )
{
Value value = properties.propertyValue();
if ( value == Values.NO_VALUE ) if ( value == Values.NO_VALUE )
{ {
throw new PropertyNotFoundException( propertyKeyId, EntityType.GRAPH, -1 ); throw new NotFoundException( format( "No such property, '%s'.", key ) );
} }

return value.asObjectCopy(); return value.asObjectCopy();
} }
catch ( PropertyNotFoundException e )
{
throw new NotFoundException(
e.getUserMessage( new StatementTokenNameLookup( statement.readOperations() ) ), e );
}
} }
throw new NotFoundException( format( "No such property, '%s'.", key ) );
} }


@Override @Override
Expand All @@ -114,36 +125,43 @@ public Object getProperty( String key, Object defaultValue )
{ {
throw new IllegalArgumentException( "(null) property key is not allowed" ); throw new IllegalArgumentException( "(null) property key is not allowed" );
} }

KernelTransaction transaction = safeAcquireTransaction();
try ( Statement statement = actions.statement() ) PropertyCursor properties = transaction.propertyCursor();
int propertyKey = transaction.tokenRead().propertyKey( key );
if ( propertyKey == KeyReadOperations.NO_SUCH_PROPERTY_KEY )
{
return defaultValue;
}
transaction.dataRead().graphProperties( properties );
while ( properties.next() )
{ {
int propertyKeyId = statement.readOperations().propertyKeyGetForName( key ); if ( propertyKey == properties.propertyKey() )
Value value = statement.readOperations().graphGetProperty( propertyKeyId ); {
return value == Values.NO_VALUE ? defaultValue : value.asObjectCopy(); Value value = properties.propertyValue();
return value == Values.NO_VALUE ? defaultValue : value.asObjectCopy();
}
} }
return defaultValue;
} }


@Override @Override
public void setProperty( String key, Object value ) public void setProperty( String key, Object value )
{ {
try ( Statement statement = actions.statement() ) KernelTransaction transaction = safeAcquireTransaction();
int propertyKeyId;
try
{ {
int propertyKeyId = statement.tokenWriteOperations().propertyKeyGetOrCreateForName( key ); propertyKeyId = transaction.tokenWrite().propertyKeyGetOrCreateForName( key );
try
{
statement.dataWriteOperations().graphSetProperty( propertyKeyId, Values.of( value, false ) );
}
catch ( IllegalArgumentException e )
{
// Trying to set an illegal value is a critical error - fail this transaction
actions.failTransaction();
throw e;
}
} }
catch ( IllegalTokenNameException e ) catch ( IllegalTokenNameException e )
{ {
throw new IllegalArgumentException( format( "Invalid property key '%s'.", key ), e ); throw new IllegalArgumentException( format( "Invalid property key '%s'.", key ), e );
} }

try ( Statement ignore = transaction.acquireStatement() )
{
transaction.dataWrite().graphSetProperty( propertyKeyId, Values.of( value, false ) );
}
catch ( InvalidTransactionTypeKernelException e ) catch ( InvalidTransactionTypeKernelException e )
{ {
throw new ConstraintViolationException( e.getMessage(), e ); throw new ConstraintViolationException( e.getMessage(), e );
Expand All @@ -153,15 +171,20 @@ public void setProperty( String key, Object value )
@Override @Override
public Object removeProperty( String key ) public Object removeProperty( String key )
{ {
try ( Statement statement = actions.statement() ) KernelTransaction transaction = safeAcquireTransaction();
int propertyKeyId;
try
{ {
int propertyKeyId = statement.tokenWriteOperations().propertyKeyGetOrCreateForName( key ); propertyKeyId = transaction.tokenWrite().propertyKeyGetOrCreateForName( key );
return statement.dataWriteOperations().graphRemoveProperty( propertyKeyId ).asObjectCopy();
} }
catch ( IllegalTokenNameException e ) catch ( IllegalTokenNameException e )
{ {
throw new IllegalArgumentException( format( "Invalid property key '%s'.", key ), e ); throw new IllegalArgumentException( format( "Invalid property key '%s'.", key ), e );
} }
try ( Statement ignore = transaction.acquireStatement() )
{
return transaction.dataWrite().graphRemoveProperty( propertyKeyId ).asObjectCopy();
}
catch ( InvalidTransactionTypeKernelException e ) catch ( InvalidTransactionTypeKernelException e )
{ {
throw new ConstraintViolationException( e.getMessage(), e ); throw new ConstraintViolationException( e.getMessage(), e );
Expand All @@ -171,62 +194,97 @@ public Object removeProperty( String key )
@Override @Override
public Iterable<String> getPropertyKeys() public Iterable<String> getPropertyKeys()
{ {
try ( Statement statement = actions.statement() ) KernelTransaction transaction = safeAcquireTransaction();
List<String> keys = new ArrayList<>();
try
{ {
List<String> keys = new ArrayList<>(); PropertyCursor properties = transaction.propertyCursor();
PrimitiveIntIterator properties = statement.readOperations().graphGetPropertyKeys(); TokenRead token = transaction.tokenRead();
while ( properties.hasNext() ) transaction.dataRead().graphProperties( properties );
while ( properties.next() )
{ {
keys.add( statement.readOperations().propertyKeyGetName( properties.next() ) ); keys.add( token.propertyKeyName( properties.propertyKey() ) );
} }
return keys;
} }
catch ( PropertyKeyIdNotFoundKernelException e ) catch ( PropertyKeyIdNotFoundKernelException e )
{ {
throw new IllegalStateException( "Property key retrieved through kernel API should exist.", e ); throw new IllegalStateException( "Property key retrieved through kernel API should exist.", e );
} }
return keys;
} }


@Override @Override
public Map<String, Object> getProperties( String... names ) public Map<String,Object> getProperties( String... names )
{ {
try ( Statement statement = actions.statement() ) Objects.requireNonNull( names, "Properties keys should be not null array." );

if ( names.length == 0 )
{ {
Map<String, Object> properties = new HashMap<>(); return Collections.emptyMap();
ReadOperations readOperations = statement.readOperations(); }
for ( String name : names )
KernelTransaction transaction = safeAcquireTransaction();

int itemsToReturn = names.length;
Map<String,Object> properties = new HashMap<>( itemsToReturn );
TokenRead token = transaction.tokenRead();

//Find ids, note we are betting on that the number of keys
//is small enough not to use a set here.
int[] propertyIds = new int[itemsToReturn];
for ( int i = 0; i < itemsToReturn; i++ )
{
String key = names[i];
if ( key == null )
{
throw new NullPointerException( String.format( "Key %d was null", i ) );
}
propertyIds[i] = token.propertyKey( key );
}

PropertyCursor propertyCursor = transaction.propertyCursor();
transaction.dataRead().graphProperties( propertyCursor );
int propertiesToFind = itemsToReturn;
while ( propertiesToFind > 0 && propertyCursor.next() )
{
//Do a linear check if this is a property we are interested in.
int currentKey = propertyCursor.propertyKey();
for ( int i = 0; i < itemsToReturn; i++ )
{ {
int propertyKeyId = readOperations.propertyKeyGetForName( name ); if ( propertyIds[i] == currentKey )
Object value = readOperations.graphGetProperty( propertyKeyId );
if ( value != null )
{ {
properties.put( name, value ); properties.put( names[i],
propertyCursor.propertyValue().asObjectCopy() );
propertiesToFind--;
break;
} }
} }
return properties;
} }
return properties;
} }


@Override @Override
public Map<String, Object> getAllProperties() public Map<String, Object> getAllProperties()
{ {
try ( Statement statement = actions.statement() ) KernelTransaction transaction = safeAcquireTransaction();
Map<String,Object> properties = new HashMap<>();

try
{ {
Map<String, Object> properties = new HashMap<>(); PropertyCursor propertyCursor = transaction.propertyCursor();
ReadOperations readOperations = statement.readOperations(); TokenRead token = transaction.tokenRead();
PrimitiveIntIterator propertyKeys = readOperations.graphGetPropertyKeys(); transaction.dataRead().graphProperties( propertyCursor );
while ( propertyKeys.hasNext() ) while ( propertyCursor.next() )
{ {
int propertyKeyId = propertyKeys.next(); properties.put( token.propertyKeyName( propertyCursor.propertyKey() ),
properties.put( readOperations.propertyKeyGetName( propertyKeyId ), propertyCursor.propertyValue().asObjectCopy() );
readOperations.graphGetProperty( propertyKeyId ).asObjectCopy() );
} }
return properties;
} }
catch ( PropertyKeyIdNotFoundKernelException e ) catch ( PropertyKeyIdNotFoundKernelException e )
{ {
throw new IllegalStateException( "Property key retrieved through kernel API should exist.", e ); throw new IllegalStateException( "Property key retrieved through kernel API should exist.", e );
} }
return properties;
} }


@Override @Override
Expand All @@ -243,4 +301,15 @@ public int hashCode()
{ {
return actions.getGraphDatabase().hashCode(); return actions.getGraphDatabase().hashCode();
} }

private KernelTransaction safeAcquireTransaction()
{
org.neo4j.kernel.api.KernelTransaction transaction = actions.kernelTransaction();
if ( transaction.isTerminated() )
{
Status terminationReason = transaction.getReasonIfTerminated().orElse( Status.Transaction.Terminated );
throw new TransactionTerminatedException( terminationReason );
}
return transaction;
}
} }

0 comments on commit 76eb142

Please sign in to comment.