Skip to content

Commit

Permalink
Add unit tests for TxState getIndexUpdates and getSortedIndexUpdates
Browse files Browse the repository at this point in the history
  • Loading branch information
sherfert committed Aug 14, 2018
1 parent 6c15f17 commit 67a44a8
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 38 deletions.
Expand Up @@ -19,6 +19,7 @@
*/
package org.neo4j.storageengine.api.txstate;

import com.sun.istack.internal.Nullable;
import org.eclipse.collections.api.set.primitive.MutableLongSet;
import org.eclipse.collections.impl.UnmodifiableMap;

Expand Down Expand Up @@ -110,17 +111,20 @@ public interface ReadableTransactionState
// INDEX UPDATES

/**
* A readonly view of all index updates for the provided schema
* A readonly view of all index updates for the provided schema. Returns {@code null}, if the index
* updates for this schema have not been initialized.
*/
@Nullable
UnmodifiableMap<ValueTuple, ? extends LongDiffSets> getIndexUpdates( SchemaDescriptor schema );

/**
* A readonly view of all index updates for the provided schema, in sorted order. The returned
* Map is unmodifiable.
* Map is unmodifiable. Returns {@code null}, if the index updates for this schema have not been initialized.
*
* Ensure sorted index updates for a given index. This is needed for range query support and
* ay involve converting the existing hash map first.
*/
@Nullable
NavigableMap<ValueTuple, ? extends LongDiffSets> getSortedIndexUpdates( SchemaDescriptor descriptor );

// OTHER
Expand Down
Expand Up @@ -19,6 +19,7 @@
*/
package org.neo4j.kernel.impl.api.state;

import com.sun.istack.internal.Nullable;
import org.eclipse.collections.api.iterator.LongIterator;
import org.eclipse.collections.api.map.primitive.MutableLongObjectMap;
import org.eclipse.collections.api.map.primitive.MutableObjectLongMap;
Expand Down Expand Up @@ -704,6 +705,7 @@ public Long indexCreatedForConstraint( ConstraintDescriptor constraint )
}

@Override
@Nullable
public UnmodifiableMap<ValueTuple, ? extends LongDiffSets> getIndexUpdates( SchemaDescriptor schema )
{
if ( indexUpdates == null )
Expand All @@ -720,6 +722,7 @@ public Long indexCreatedForConstraint( ConstraintDescriptor constraint )
}

@Override
@Nullable
public NavigableMap<ValueTuple, ? extends LongDiffSets> getSortedIndexUpdates( SchemaDescriptor descriptor )
{
if ( indexUpdates == null )
Expand Down Expand Up @@ -750,10 +753,10 @@ public void indexDoUpdateEntry( SchemaDescriptor descriptor, long nodeId,
ValueTuple propertiesBefore, ValueTuple propertiesAfter )
{
NodeStateImpl nodeState = getOrCreateNodeState( nodeId );
Map<ValueTuple, MutableLongDiffSets> updates = getIndexUpdatesByDescriptor( descriptor );
Map<ValueTuple, MutableLongDiffSets> updates = getOrCreateIndexUpdatesByDescriptor( descriptor );
if ( propertiesBefore != null )
{
MutableLongDiffSets before = getIndexUpdatesForSeek( updates, propertiesBefore );
MutableLongDiffSets before = getOrCreateIndexUpdatesForSeek( updates, propertiesBefore );
//noinspection ConstantConditions
before.remove( nodeId );
if ( before.getRemoved().contains( nodeId ) )
Expand All @@ -767,7 +770,7 @@ public void indexDoUpdateEntry( SchemaDescriptor descriptor, long nodeId,
}
if ( propertiesAfter != null )
{
MutableLongDiffSets after = getIndexUpdatesForSeek( updates, propertiesAfter );
MutableLongDiffSets after = getOrCreateIndexUpdatesForSeek( updates, propertiesAfter );
//noinspection ConstantConditions
after.add( nodeId );
if ( after.getAdded().contains( nodeId ) )
Expand All @@ -781,18 +784,12 @@ public void indexDoUpdateEntry( SchemaDescriptor descriptor, long nodeId,
}
}

/**
* This method does some initialization of empty diffsets. Only call it from updating code.
*/
private MutableLongDiffSets getIndexUpdatesForSeek( Map<ValueTuple,MutableLongDiffSets> updates, ValueTuple values )
private MutableLongDiffSets getOrCreateIndexUpdatesForSeek( Map<ValueTuple,MutableLongDiffSets> updates, ValueTuple values )
{
return updates.computeIfAbsent( values, value -> new MutableLongDiffSetsImpl() );
}

/**
* This method does some initialization of empty diffsets. Only call it from updating code.
*/
private Map<ValueTuple, MutableLongDiffSets> getIndexUpdatesByDescriptor( SchemaDescriptor schema )
private Map<ValueTuple, MutableLongDiffSets> getOrCreateIndexUpdatesByDescriptor( SchemaDescriptor schema )
{
if ( indexUpdates == null )
{
Expand Down
Expand Up @@ -22,6 +22,8 @@
import org.apache.commons.lang3.mutable.MutableBoolean;
import org.eclipse.collections.api.IntIterable;
import org.eclipse.collections.api.set.primitive.LongSet;
import org.eclipse.collections.impl.UnmodifiableMap;
import org.eclipse.collections.impl.factory.primitive.LongSets;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
Expand All @@ -38,7 +40,9 @@
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.NavigableMap;
import java.util.Set;
import java.util.TreeMap;

import org.neo4j.function.Predicates;
import org.neo4j.helpers.collection.Iterators;
Expand All @@ -53,8 +57,10 @@
import org.neo4j.kernel.impl.util.collection.CollectionsFactory;
import org.neo4j.kernel.impl.util.collection.CollectionsFactorySupplier;
import org.neo4j.kernel.impl.util.collection.OffHeapCollectionsFactory;
import org.neo4j.kernel.impl.util.diffsets.MutableLongDiffSetsImpl;
import org.neo4j.storageengine.api.StorageProperty;
import org.neo4j.storageengine.api.schema.IndexDescriptor;
import org.neo4j.storageengine.api.txstate.LongDiffSets;
import org.neo4j.storageengine.api.txstate.ReadableDiffSets;
import org.neo4j.storageengine.api.txstate.TxStateVisitor;
import org.neo4j.test.rule.RandomRule;
Expand All @@ -69,6 +75,7 @@
import static org.hamcrest.core.IsEqual.equalTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
Expand Down Expand Up @@ -233,6 +240,89 @@ public void shouldMapFromRemovedLabelToNodes()

//endregion

//region index updates

@Test
public void shouldComputeIndexUpdatesOnUninitializedTxState()
{
// WHEN
UnmodifiableMap<ValueTuple,? extends LongDiffSets> diffSets = state.getIndexUpdates( indexOn_1_1.schema() );

// THEN
assertNull( diffSets );
}

@Test
public void shouldComputeSortedIndexUpdatesOnUninitializedTxState()
{
// WHEN
NavigableMap<ValueTuple,? extends LongDiffSets> diffSets = state.getSortedIndexUpdates( indexOn_1_1.schema() );

// THEN
assertNull( diffSets );
}

@Test
public void shouldComputeIndexUpdatesOnEmptyTxState()
{
// GIVEN
addNodesToIndex( indexOn_2_1 ).withDefaultStringProperties( 42L );

// WHEN
UnmodifiableMap<ValueTuple,? extends LongDiffSets> diffSets = state.getIndexUpdates( indexOn_1_1.schema() );

// THEN
assertNull( diffSets );
}

@Test
public void shouldComputeSortedIndexUpdatesOnEmptyTxState()
{
// GIVEN
addNodesToIndex( indexOn_2_1 ).withDefaultStringProperties( 42L );

// WHEN
NavigableMap<ValueTuple,? extends LongDiffSets> diffSets = state.getSortedIndexUpdates( indexOn_1_1.schema() );

// THEN
assertNull( diffSets );
}

@Test
public void shouldComputeIndexUpdatesOnTxStateWithAddedNodes()
{
// GIVEN
addNodesToIndex( indexOn_1_1 ).withDefaultStringProperties( 42L );
addNodesToIndex( indexOn_1_1 ).withDefaultStringProperties( 43L );
addNodesToIndex( indexOn_1_1 ).withDefaultStringProperties( 41L );

// WHEN
UnmodifiableMap<ValueTuple,? extends LongDiffSets> diffSets = state.getIndexUpdates( indexOn_1_1.schema() );

// THEN
assertEquals( addedNodes( 42L ), diffSets.get( ValueTuple.of( Values.stringValue( "value42" ) ) ) );
assertEquals( addedNodes( 43L ), diffSets.get( ValueTuple.of( Values.stringValue( "value43" ) ) ) );
assertEquals( addedNodes( 41L ), diffSets.get( ValueTuple.of( Values.stringValue( "value41" ) ) ) );
}

@Test
public void shouldComputeSortedIndexUpdatesOnTxStateWithAddedNodes()
{
// GIVEN
addNodesToIndex( indexOn_1_1 ).withDefaultStringProperties( 42L );
addNodesToIndex( indexOn_1_1 ).withDefaultStringProperties( 43L );
addNodesToIndex( indexOn_1_1 ).withDefaultStringProperties( 41L );

// WHEN
NavigableMap<ValueTuple,? extends LongDiffSets> diffSets = state.getSortedIndexUpdates( indexOn_1_1.schema() );

TreeMap<ValueTuple,LongDiffSets> expected = sortedAddedNodesDiffSets( 42, 41, 43 );
// THEN
assertEquals( expected, diffSets );
}

// endregion

//region index rule tests

@Test
Expand Down Expand Up @@ -752,6 +842,22 @@ public void visitDeletedNode( long id )

//endregion

private LongDiffSets addedNodes( long... added )
{
return new MutableLongDiffSetsImpl( LongSets.mutable.of( added ), LongSets.mutable.empty(), collectionsFactory );
}

private TreeMap<ValueTuple,LongDiffSets> sortedAddedNodesDiffSets( long... added )
{
TreeMap<ValueTuple,LongDiffSets> map = new TreeMap<>( ValueTuple.COMPARATOR );
for ( long node : added )
{

map.put( ValueTuple.of( Values.stringValue( "value" + node ) ), addedNodes( node ) );
}
return map;
}

abstract class VisitationOrder extends TxStateVisitor.Adapter
{
private final Set<String> visitMethods = new HashSet<>();
Expand Down Expand Up @@ -820,12 +926,6 @@ final void visitLate()
private interface IndexUpdater
{
void withDefaultStringProperties( long... nodeIds );

void withStringProperties( Collection<Pair<Long,String>> nodesWithValues );

<T extends Number> void withNumberProperties( Collection<Pair<Long,T>> nodesWithValues );

void withBooleanProperties( Collection<Pair<Long,Boolean>> nodesWithValues );
}

private IndexUpdater addNodesToIndex( final IndexDescriptor descriptor )
Expand All @@ -840,25 +940,7 @@ public void withDefaultStringProperties( long... nodeIds )
{
entries.add( of( nodeId, "value" + nodeId ) );
}
withStringProperties( entries );
}

@Override
public void withStringProperties( Collection<Pair<Long,String>> nodesWithValues )
{
withProperties( nodesWithValues );
}

@Override
public <T extends Number> void withNumberProperties( Collection<Pair<Long,T>> nodesWithValues )
{
withProperties( nodesWithValues );
}

@Override
public void withBooleanProperties( Collection<Pair<Long,Boolean>> nodesWithValues )
{
withProperties( nodesWithValues );
withProperties( entries );
}

private <T> void withProperties( Collection<Pair<Long,T>> nodesWithValues )
Expand Down

0 comments on commit 67a44a8

Please sign in to comment.