diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/StateHandlingStatementOperations.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/StateHandlingStatementOperations.java index c09530e530326..6d68955126f6f 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/StateHandlingStatementOperations.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/StateHandlingStatementOperations.java @@ -102,6 +102,7 @@ import org.neo4j.storageengine.api.schema.IndexReader; import org.neo4j.storageengine.api.schema.PopulationProgress; import org.neo4j.storageengine.api.txstate.NodeState; +import org.neo4j.storageengine.api.txstate.PrimitiveLongReadableDiffSets; import org.neo4j.storageengine.api.txstate.ReadableDiffSets; import org.neo4j.values.storable.Value; import org.neo4j.values.storable.ValueTuple; @@ -947,7 +948,7 @@ private PrimitiveLongResourceIterator filterIndexStateChangesForScan( { if ( state.hasTxStateWithChanges() ) { - ReadableDiffSets labelPropertyChanges = + PrimitiveLongReadableDiffSets labelPropertyChanges = state.txState().indexUpdatesForScan( index ); ReadableDiffSets nodes = state.txState().addedAndRemovedNodes(); @@ -963,7 +964,7 @@ private PrimitiveLongResourceIterator filterIndexStateChangesForSeek( { if ( state.hasTxStateWithChanges() ) { - ReadableDiffSets labelPropertyChanges = + PrimitiveLongReadableDiffSets labelPropertyChanges = state.txState().indexUpdatesForSeek( index, propertyValues ); ReadableDiffSets nodes = state.txState().addedAndRemovedNodes(); @@ -981,10 +982,10 @@ private PrimitiveLongResourceIterator filterIndexStateChangesForRangeSeekByNumbe { if ( state.hasTxStateWithChanges() ) { - ReadableDiffSets labelPropertyChangesForNumber = - state.txState().indexUpdatesForRangeSeekByNumber( - index, lower, includeLower, upper, includeUpper ); - ReadableDiffSets nodes = state.txState().addedAndRemovedNodes(); + TransactionState txState = state.txState(); + PrimitiveLongReadableDiffSets labelPropertyChangesForNumber = + txState.indexUpdatesForRangeSeekByNumber( index, lower, includeLower, upper, includeUpper ); + ReadableDiffSets nodes = txState.addedAndRemovedNodes(); // Apply to actual index lookup return nodes.augmentWithRemovals( labelPropertyChangesForNumber.augment( nodeIds ) ); @@ -1001,10 +1002,10 @@ private PrimitiveLongResourceIterator filterIndexStateChangesForRangeSeekByStrin { if ( state.hasTxStateWithChanges() ) { - ReadableDiffSets labelPropertyChangesForString = - state.txState().indexUpdatesForRangeSeekByString( + TransactionState txState = state.txState(); + PrimitiveLongReadableDiffSets labelPropertyChangesForString = txState.indexUpdatesForRangeSeekByString( index, lower, includeLower, upper, includeUpper ); - ReadableDiffSets nodes = state.txState().addedAndRemovedNodes(); + ReadableDiffSets nodes = txState.addedAndRemovedNodes(); // Apply to actual index lookup return nodes.augmentWithRemovals( labelPropertyChangesForString.augment( nodeIds ) ); @@ -1020,9 +1021,10 @@ private PrimitiveLongResourceIterator filterIndexStateChangesForRangeSeekByPrefi { if ( state.hasTxStateWithChanges() ) { - ReadableDiffSets labelPropertyChangesForPrefix = - state.txState().indexUpdatesForRangeSeekByPrefix( index, prefix ); - ReadableDiffSets nodes = state.txState().addedAndRemovedNodes(); + TransactionState txState = state.txState(); + PrimitiveLongReadableDiffSets labelPropertyChangesForPrefix = + txState.indexUpdatesForRangeSeekByPrefix( index, prefix ); + ReadableDiffSets nodes = txState.addedAndRemovedNodes(); // Apply to actual index lookup return nodes.augmentWithRemovals( labelPropertyChangesForPrefix.augment( nodeIds ) ); diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/state/NodeStateImpl.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/state/NodeStateImpl.java index 9c0f530c2a751..03b47ee4ed06a 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/state/NodeStateImpl.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/state/NodeStateImpl.java @@ -19,8 +19,7 @@ */ package org.neo4j.kernel.impl.api.state; -import java.util.Collections; -import java.util.IdentityHashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.Set; @@ -31,6 +30,7 @@ import org.neo4j.internal.kernel.api.exceptions.schema.ConstraintValidationException; import org.neo4j.kernel.impl.api.state.RelationshipChangesForNode.DiffStrategy; import org.neo4j.kernel.impl.util.diffsets.DiffSets; +import org.neo4j.kernel.impl.util.diffsets.PrimitiveLongDiffSets; import org.neo4j.storageengine.api.Direction; import org.neo4j.storageengine.api.StorageProperty; import org.neo4j.storageengine.api.txstate.NodeState; @@ -45,7 +45,8 @@ public class NodeStateImpl extends PropertyContainerStateImpl implements NodeSta private DiffSets labelDiffSets; private RelationshipChangesForNode relationshipsAdded; private RelationshipChangesForNode relationshipsRemoved; - private Set> indexDiffs; // TODO: does this really fill any function? + + private Set indexDiffs; private final TxState state; NodeStateImpl( long id, TxState state ) @@ -176,16 +177,16 @@ public PrimitiveIntSet relationshipTypes() return intSet(); } - void addIndexDiff( DiffSets diff ) + void addIndexDiff( PrimitiveLongDiffSets diff ) { if ( indexDiffs == null ) { - indexDiffs = Collections.newSetFromMap( new IdentityHashMap, Boolean>() ); + indexDiffs = new HashSet<>(); } indexDiffs.add( diff ); } - void removeIndexDiff( DiffSets diff ) + void removeIndexDiff( PrimitiveLongDiffSets diff ) { if ( indexDiffs != null ) { @@ -197,7 +198,7 @@ void clearIndexDiffs( long nodeId ) { if ( indexDiffs != null ) { - for ( DiffSets diff : indexDiffs ) + for ( PrimitiveLongDiffSets diff : indexDiffs ) { if ( diff.getAdded().contains( nodeId ) ) { diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/state/TxState.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/state/TxState.java index e93c6d3108577..57c05aee92118 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/state/TxState.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/state/TxState.java @@ -56,6 +56,8 @@ import org.neo4j.kernel.impl.api.store.RelationshipIterator; import org.neo4j.kernel.impl.util.InstanceCache; import org.neo4j.kernel.impl.util.diffsets.DiffSets; +import org.neo4j.kernel.impl.util.diffsets.EmptyPrimitiveLongReadableDiffSets; +import org.neo4j.kernel.impl.util.diffsets.PrimitiveLongDiffSets; import org.neo4j.kernel.impl.util.diffsets.RelationshipDiffSets; import org.neo4j.storageengine.api.Direction; import org.neo4j.storageengine.api.NodeItem; @@ -64,6 +66,7 @@ import org.neo4j.storageengine.api.StorageProperty; import org.neo4j.storageengine.api.txstate.DiffSetsVisitor; import org.neo4j.storageengine.api.txstate.NodeState; +import org.neo4j.storageengine.api.txstate.PrimitiveLongReadableDiffSets; import org.neo4j.storageengine.api.txstate.PropertyContainerState; import org.neo4j.storageengine.api.txstate.ReadableDiffSets; import org.neo4j.storageengine.api.txstate.ReadableRelationshipDiffSets; @@ -125,7 +128,7 @@ public final class TxState implements TransactionState, RelationshipVisitor.Home private Map createdConstraintIndexesByConstraint; - private Map>> indexUpdates; + private Map> indexUpdates; private InstanceCache singleNodeCursor; private InstanceCache iteratorRelationshipCursor; @@ -923,36 +926,43 @@ public Long indexCreatedForConstraint( ConstraintDescriptor constraint ) } @Override - public ReadableDiffSets indexUpdatesForScan( IndexDescriptor descriptor ) + public PrimitiveLongReadableDiffSets indexUpdatesForScan( IndexDescriptor descriptor ) { - return ReadableDiffSets.Empty.ifNull( getIndexUpdatesForScan( descriptor.schema() ) ); + if ( indexUpdates == null ) + { + return EmptyPrimitiveLongReadableDiffSets.INSTANCE; + } + Map updates = indexUpdates.get( descriptor.schema() ); + if ( updates == null ) + { + return EmptyPrimitiveLongReadableDiffSets.INSTANCE; + } + PrimitiveLongDiffSets diffs = new PrimitiveLongDiffSets(); + for ( PrimitiveLongDiffSets diffSet : updates.values() ) + { + diffs.addAll( diffSet.getAdded().iterator() ); + diffs.removeAll( diffSet.getRemoved().iterator() ); + } + return diffs; } @Override - public ReadableDiffSets indexUpdatesForSeek( IndexDescriptor descriptor, ValueTuple values ) + public PrimitiveLongReadableDiffSets indexUpdatesForSeek( IndexDescriptor descriptor, ValueTuple values ) { assert values != null; - return ReadableDiffSets.Empty.ifNull( getIndexUpdatesForSeek( descriptor.schema(), values, /*create=*/false ) ); + PrimitiveLongDiffSets indexUpdatesForSeek = getIndexUpdatesForSeek( descriptor.schema(), values, /*create=*/false ); + return indexUpdatesForSeek == null ? EmptyPrimitiveLongReadableDiffSets.INSTANCE : indexUpdatesForSeek; } @Override - public ReadableDiffSets indexUpdatesForRangeSeekByNumber( IndexDescriptor descriptor, + public PrimitiveLongReadableDiffSets indexUpdatesForRangeSeekByNumber( IndexDescriptor descriptor, Number lower, boolean includeLower, Number upper, boolean includeUpper ) { - return ReadableDiffSets.Empty.ifNull( - getIndexUpdatesForRangeSeekByNumber( descriptor, lower, includeLower, upper, includeUpper ) - ); - } - - private ReadableDiffSets getIndexUpdatesForRangeSeekByNumber( IndexDescriptor descriptor, - Number lower, boolean includeLower, - Number upper, boolean includeUpper ) - { - TreeMap> sortedUpdates = getSortedIndexUpdates( descriptor.schema() ); + TreeMap sortedUpdates = getSortedIndexUpdates( descriptor.schema() ); if ( sortedUpdates == null ) { - return null; + return EmptyPrimitiveLongReadableDiffSets.INSTANCE; } ValueTuple selectedLower; @@ -961,7 +971,6 @@ private ReadableDiffSets getIndexUpdatesForRangeSeekByNumber( IndexDescrip ValueTuple selectedUpper; boolean selectedIncludeUpper; - //TODO: Get working with composite indexes' if ( lower == null ) { selectedLower = ValueTuple.of( Values.MIN_NUMBER ); @@ -984,12 +993,12 @@ private ReadableDiffSets getIndexUpdatesForRangeSeekByNumber( IndexDescrip selectedIncludeUpper = includeUpper; } - DiffSets diffs = new DiffSets<>(); + PrimitiveLongDiffSets diffs = new PrimitiveLongDiffSets(); - Collection> inRange = + Collection inRange = sortedUpdates.subMap( selectedLower, selectedIncludeLower, selectedUpper, selectedIncludeUpper ).values(); - for ( DiffSets diffForSpecificValue : inRange ) + for ( PrimitiveLongDiffSets diffForSpecificValue : inRange ) { diffs.addAll( diffForSpecificValue.getAdded().iterator() ); diffs.removeAll( diffForSpecificValue.getRemoved().iterator() ); @@ -998,23 +1007,14 @@ private ReadableDiffSets getIndexUpdatesForRangeSeekByNumber( IndexDescrip } @Override - public ReadableDiffSets indexUpdatesForRangeSeekByString( IndexDescriptor descriptor, + public PrimitiveLongReadableDiffSets indexUpdatesForRangeSeekByString( IndexDescriptor descriptor, String lower, boolean includeLower, String upper, boolean includeUpper ) { - return ReadableDiffSets.Empty.ifNull( - getIndexUpdatesForRangeSeekByString( descriptor, lower, includeLower, upper, includeUpper ) - ); - } - - private ReadableDiffSets getIndexUpdatesForRangeSeekByString( IndexDescriptor descriptor, - String lower, boolean includeLower, - String upper, boolean includeUpper ) - { - TreeMap> sortedUpdates = getSortedIndexUpdates( descriptor.schema() ); + TreeMap sortedUpdates = getSortedIndexUpdates( descriptor.schema() ); if ( sortedUpdates == null ) { - return null; + return EmptyPrimitiveLongReadableDiffSets.INSTANCE; } ValueTuple selectedLower; @@ -1023,7 +1023,6 @@ private ReadableDiffSets getIndexUpdatesForRangeSeekByString( IndexDescrip ValueTuple selectedUpper; boolean selectedIncludeUpper; - //TODO: Get working with composite indexes if ( lower == null ) { selectedLower = ValueTuple.of( Values.MIN_STRING ); @@ -1046,11 +1045,11 @@ private ReadableDiffSets getIndexUpdatesForRangeSeekByString( IndexDescrip selectedIncludeUpper = includeUpper; } - DiffSets diffs = new DiffSets<>(); - Collection> inRange = - sortedUpdates.subMap( selectedLower, selectedIncludeLower, - selectedUpper, selectedIncludeUpper ).values(); - for ( DiffSets diffForSpecificValue : inRange ) + PrimitiveLongDiffSets diffs = new PrimitiveLongDiffSets(); + Collection inRange = sortedUpdates.subMap( selectedLower, selectedIncludeLower, + selectedUpper, selectedIncludeUpper ) + .values(); + for ( PrimitiveLongDiffSets diffForSpecificValue : inRange ) { diffs.addAll( diffForSpecificValue.getAdded().iterator() ); diffs.removeAll( diffForSpecificValue.getRemoved().iterator() ); @@ -1059,27 +1058,21 @@ private ReadableDiffSets getIndexUpdatesForRangeSeekByString( IndexDescrip } @Override - public ReadableDiffSets indexUpdatesForRangeSeekByPrefix( IndexDescriptor descriptor, String prefix ) - { - return ReadableDiffSets.Empty.ifNull( getIndexUpdatesForRangeSeekByPrefix( descriptor, prefix ) ); - } - - private ReadableDiffSets getIndexUpdatesForRangeSeekByPrefix( IndexDescriptor descriptor, String prefix ) + public PrimitiveLongReadableDiffSets indexUpdatesForRangeSeekByPrefix( IndexDescriptor descriptor, String prefix ) { - TreeMap> sortedUpdates = getSortedIndexUpdates( descriptor.schema() ); + TreeMap sortedUpdates = getSortedIndexUpdates( descriptor.schema() ); if ( sortedUpdates == null ) { - return null; + return EmptyPrimitiveLongReadableDiffSets.INSTANCE; } - //TODO: get working with composite indexes ValueTuple floor = ValueTuple.of( Values.stringValue( prefix ) ); - DiffSets diffs = new DiffSets<>(); - for ( Map.Entry> entry : sortedUpdates.tailMap( floor ).entrySet() ) + PrimitiveLongDiffSets diffs = new PrimitiveLongDiffSets(); + for ( Map.Entry entry : sortedUpdates.tailMap( floor ).entrySet() ) { ValueTuple key = entry.getKey(); - if ( ((TextValue)key.getOnlyValue()).stringValue().startsWith( prefix ) ) + if ( ((TextValue) key.getOnlyValue()).stringValue().startsWith( prefix ) ) { - DiffSets diffSets = entry.getValue(); + PrimitiveLongDiffSets diffSets = entry.getValue(); diffs.addAll( diffSets.getAdded().iterator() ); diffs.removeAll( diffSets.getRemoved().iterator() ); } @@ -1094,21 +1087,21 @@ private ReadableDiffSets getIndexUpdatesForRangeSeekByPrefix( IndexDescrip // Ensure sorted index updates for a given index. This is needed for range query support and // may involve converting the existing hash map first // - private TreeMap> getSortedIndexUpdates( LabelSchemaDescriptor descriptor ) + private TreeMap getSortedIndexUpdates( LabelSchemaDescriptor descriptor ) { if ( indexUpdates == null ) { return null; } - Map> updates = indexUpdates.get( descriptor ); + Map updates = indexUpdates.get( descriptor ); if ( updates == null ) { return null; } - TreeMap> sortedUpdates; + TreeMap sortedUpdates; if ( updates instanceof TreeMap ) { - sortedUpdates = (TreeMap>) updates; + sortedUpdates = (TreeMap) updates; } else { @@ -1124,10 +1117,10 @@ public void indexDoUpdateEntry( LabelSchemaDescriptor descriptor, long nodeId, ValueTuple propertiesBefore, ValueTuple propertiesAfter ) { NodeStateImpl nodeState = getOrCreateNodeState( nodeId ); - Map> updates = getIndexUpdatesByDescriptor( descriptor, true); + Map updates = getIndexUpdatesByDescriptor( descriptor, true); if ( propertiesBefore != null ) { - DiffSets before = getIndexUpdatesForSeek( updates, propertiesBefore, true ); + PrimitiveLongDiffSets before = getIndexUpdatesForSeek( updates, propertiesBefore, true ); //noinspection ConstantConditions before.remove( nodeId ); if ( before.getRemoved().contains( nodeId ) ) @@ -1141,7 +1134,7 @@ public void indexDoUpdateEntry( LabelSchemaDescriptor descriptor, long nodeId, } if ( propertiesAfter != null ) { - DiffSets after = getIndexUpdatesForSeek( updates, propertiesAfter, true ); + PrimitiveLongDiffSets after = getIndexUpdatesForSeek( updates, propertiesAfter, true ); //noinspection ConstantConditions after.add( nodeId ); if ( after.getAdded().contains( nodeId ) ) @@ -1155,10 +1148,10 @@ public void indexDoUpdateEntry( LabelSchemaDescriptor descriptor, long nodeId, } } - private DiffSets getIndexUpdatesForSeek( + private PrimitiveLongDiffSets getIndexUpdatesForSeek( LabelSchemaDescriptor schema, ValueTuple values, boolean create ) { - Map> updates = getIndexUpdatesByDescriptor( schema, create ); + Map updates = getIndexUpdatesByDescriptor( schema, create ); if ( updates != null ) { return getIndexUpdatesForSeek( updates, values, create ); @@ -1166,18 +1159,13 @@ private DiffSets getIndexUpdatesForSeek( return null; } - private DiffSets getIndexUpdatesForSeek( Map> updates, + private PrimitiveLongDiffSets getIndexUpdatesForSeek( Map updates, ValueTuple values, boolean create ) { - DiffSets diffs = updates.get( values ); - if ( diffs == null && create ) - { - updates.put( values, diffs = new DiffSets<>() ); - } - return diffs; + return create ? updates.computeIfAbsent( values, value -> new PrimitiveLongDiffSets() ) : updates.get( values ); } - private Map> getIndexUpdatesByDescriptor( LabelSchemaDescriptor schema, + private Map getIndexUpdatesByDescriptor( LabelSchemaDescriptor schema, boolean create ) { if ( indexUpdates == null ) @@ -1188,38 +1176,19 @@ private Map> getIndexUpdatesByDescriptor( LabelSchemaD } indexUpdates = new HashMap<>(); } - Map> updates = indexUpdates.get( schema ); + Map updates = indexUpdates.get( schema ); if ( updates == null ) { if ( !create ) { return null; } - indexUpdates.put( schema, updates = new HashMap<>() ); + updates = new HashMap<>(); + indexUpdates.put( schema, updates ); } return updates; } - private DiffSets getIndexUpdatesForScan( LabelSchemaDescriptor schema ) - { - if ( indexUpdates == null ) - { - return null; - } - Map> updates = indexUpdates.get( schema ); - if ( updates == null ) - { - return null; - } - DiffSets diffs = new DiffSets<>(); - for ( DiffSets diffSet : updates.values() ) - { - diffs.addAll( diffSet.getAdded().iterator() ); - diffs.removeAll( diffSet.getRemoved().iterator() ); - } - return diffs; - } - private Map createdConstraintIndexesByConstraint() { if ( createdConstraintIndexesByConstraint == null ) diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/newapi/NodeValueIndexCursor.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/newapi/NodeValueIndexCursor.java index 3cbb186a3ff5f..a309ad9beb726 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/newapi/NodeValueIndexCursor.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/newapi/NodeValueIndexCursor.java @@ -20,23 +20,21 @@ package org.neo4j.kernel.impl.newapi; import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; -import java.util.function.IntFunction; -import java.util.stream.Stream; -import org.neo4j.collection.primitive.PrimitiveLongCollections; import org.neo4j.collection.primitive.PrimitiveLongIterator; +import org.neo4j.collection.primitive.PrimitiveLongSet; import org.neo4j.internal.kernel.api.IndexQuery; import org.neo4j.internal.kernel.api.NodeCursor; import org.neo4j.kernel.api.schema.index.IndexDescriptor; -import org.neo4j.register.Register; +import org.neo4j.kernel.api.txstate.TransactionState; import org.neo4j.storageengine.api.schema.IndexProgressor; import org.neo4j.storageengine.api.schema.IndexProgressor.NodeValueClient; -import org.neo4j.storageengine.api.txstate.ReadableDiffSets; +import org.neo4j.storageengine.api.txstate.PrimitiveLongReadableDiffSets; import org.neo4j.values.storable.Value; import static java.util.Arrays.stream; +import static org.neo4j.collection.primitive.PrimitiveLongCollections.asSet; +import static org.neo4j.collection.primitive.PrimitiveLongCollections.emptyIterator; import static org.neo4j.kernel.impl.api.StateHandlingStatementOperations.assertOnlyExactPredicates; import static org.neo4j.kernel.impl.store.record.AbstractBaseRecord.NO_ID; @@ -48,7 +46,7 @@ class NodeValueIndexCursor extends IndexCursor private IndexQuery[] query; private Value[] values; private PrimitiveLongIterator added; - private Set removed; + private PrimitiveLongSet removed; NodeValueIndexCursor() { @@ -208,13 +206,11 @@ private void prefixQuery( IndexDescriptor descriptor, IndexQuery.StringPrefixPre { if ( read.hasTxStateWithChanges() ) { - ReadableDiffSets changes = - read.txState().indexUpdatesForRangeSeekByPrefix( descriptor, predicate.prefix() ); - added = - changes - .augment( PrimitiveLongCollections.emptyIterator() ); - removed = new HashSet<>( read.txState().addedAndRemovedNodes().getRemoved() ); - removed.addAll( changes.getRemoved() ); + TransactionState txState = read.txState(); + PrimitiveLongReadableDiffSets changes = + txState.indexUpdatesForRangeSeekByPrefix( descriptor, predicate.prefix() ); + added = changes.augment( emptyIterator() ); + removed = removed( txState, changes ); } } @@ -222,13 +218,12 @@ private void stringRangeQuery( IndexDescriptor descriptor, IndexQuery.StringRang { if ( read.hasTxStateWithChanges() ) { - ReadableDiffSets changes = read.txState().indexUpdatesForRangeSeekByString( + TransactionState txState = read.txState(); + PrimitiveLongReadableDiffSets changes = txState.indexUpdatesForRangeSeekByString( descriptor, predicate.from(), predicate.fromInclusive(), predicate.to(), predicate.toInclusive() ); - added = - changes.augment( PrimitiveLongCollections.emptyIterator() ); - removed = new HashSet<>( read.txState().addedAndRemovedNodes().getRemoved() ); - removed.addAll( changes.getRemoved() ); + added = changes.augment( emptyIterator() ); + removed = removed( txState, changes ); } } @@ -236,13 +231,12 @@ private void numericRangeQuery( IndexDescriptor descriptor, IndexQuery.NumberRan { if ( read.hasTxStateWithChanges() ) { - ReadableDiffSets changes = read.txState().indexUpdatesForRangeSeekByNumber( + TransactionState txState = read.txState(); + PrimitiveLongReadableDiffSets changes = txState.indexUpdatesForRangeSeekByNumber( descriptor, predicate.from(), predicate.fromInclusive(), predicate.to(), predicate.toInclusive() ); - added = - changes.augment( PrimitiveLongCollections.emptyIterator() ); - removed = new HashSet<>( read.txState().addedAndRemovedNodes().getRemoved() ); - removed.addAll( changes.getRemoved() ); + added = changes.augment( emptyIterator() ); + removed = removed( txState, changes ); } } @@ -250,11 +244,10 @@ private void scanQuery( IndexDescriptor descriptor ) { if ( read.hasTxStateWithChanges() ) { - ReadableDiffSets changes = read.txState().indexUpdatesForScan( descriptor ); - added = changes - .augment( PrimitiveLongCollections.emptyIterator() ); - removed = new HashSet<>( read.txState().addedAndRemovedNodes().getRemoved() ); - removed.addAll( changes.getRemoved() ); + TransactionState txState = read.txState(); + PrimitiveLongReadableDiffSets changes = txState.indexUpdatesForScan( descriptor ); + added = changes.augment( emptyIterator() ); + removed = removed( txState, changes ); } } @@ -263,12 +256,18 @@ private void seekQuery( IndexDescriptor descriptor, IndexQuery[] query ) IndexQuery.ExactPredicate[] exactPreds = assertOnlyExactPredicates( query ); if ( read.hasTxStateWithChanges() ) { - ReadableDiffSets changes = read.txState() + TransactionState txState = read.txState(); + PrimitiveLongReadableDiffSets changes = txState .indexUpdatesForSeek( descriptor, IndexQuery.asValueTuple( exactPreds ) ); - added = changes - .augment( PrimitiveLongCollections.emptyIterator() ); - removed = new HashSet<>( read.txState().addedAndRemovedNodes().getRemoved() ); - removed.addAll( changes.getRemoved() ); + added = changes.augment( emptyIterator() ); + removed = removed( txState, changes ); } } + + private PrimitiveLongSet removed( TransactionState txState, PrimitiveLongReadableDiffSets changes ) + { + PrimitiveLongSet longSet = asSet( txState.addedAndRemovedNodes().getRemoved() ); + longSet.addAll( changes.getRemoved().iterator() ); + return longSet; + } } diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/util/diffsets/DiffApplyingLongIterator.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/util/diffsets/DiffApplyingLongIterator.java index 54bc5bf5ba9f9..2ef9adeabdaf0 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/util/diffsets/DiffApplyingLongIterator.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/util/diffsets/DiffApplyingLongIterator.java @@ -72,8 +72,7 @@ boolean fetchNext( DiffApplyingLongIterator self ) private final Set removedElements; protected Phase phase; - public DiffApplyingLongIterator( PrimitiveLongIterator source, - Set addedElements, Set removedElements ) + DiffApplyingLongIterator( PrimitiveLongIterator source, Set addedElements, Set removedElements ) { this.source = source; this.addedElements = addedElements; diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/util/diffsets/EmptyPrimitiveLongReadableDiffSets.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/util/diffsets/EmptyPrimitiveLongReadableDiffSets.java index a0f1815e5999e..2ca255168c6db 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/util/diffsets/EmptyPrimitiveLongReadableDiffSets.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/util/diffsets/EmptyPrimitiveLongReadableDiffSets.java @@ -23,6 +23,11 @@ import static org.neo4j.collection.primitive.PrimitiveLongCollections.emptySet; +/** + * Empty implementation of {@link PrimitiveLongDiffSets}. + * + * Use {@link #INSTANCE} to reference static singleton. + */ public class EmptyPrimitiveLongReadableDiffSets extends PrimitiveLongDiffSets { public static final PrimitiveLongDiffSets INSTANCE = new EmptyPrimitiveLongReadableDiffSets(); diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/util/diffsets/PrimitiveLongDiffSets.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/util/diffsets/PrimitiveLongDiffSets.java index e87ea42f95b5f..febcfe09069ee 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/util/diffsets/PrimitiveLongDiffSets.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/util/diffsets/PrimitiveLongDiffSets.java @@ -20,7 +20,6 @@ package org.neo4j.kernel.impl.util.diffsets; import org.neo4j.collection.primitive.Primitive; -import org.neo4j.collection.primitive.PrimitiveLongCollections; import org.neo4j.collection.primitive.PrimitiveLongIterator; import org.neo4j.collection.primitive.PrimitiveLongSet; import org.neo4j.internal.kernel.api.exceptions.schema.ConstraintValidationException; @@ -28,6 +27,7 @@ import org.neo4j.storageengine.api.txstate.PrimitiveLongDiffSetsVisitor; import org.neo4j.storageengine.api.txstate.PrimitiveLongReadableDiffSets; +import static org.neo4j.collection.primitive.PrimitiveLongCollections.asSet; import static org.neo4j.collection.primitive.PrimitiveLongCollections.emptySet; /** @@ -66,24 +66,37 @@ public boolean isRemoved( long element ) return removedElements.contains( element ); } - public void add( long element ) + public void removeAll( PrimitiveLongIterator elementsToRemove ) + { + checkRemovedElements(); + while ( elementsToRemove.hasNext() ) + { + removeElement( elementsToRemove.next() ); + } + } + + public void addAll( PrimitiveLongIterator elementsToAdd ) { checkAddedElements(); - boolean removed = removedElements.remove( element ); - if ( !removed ) + while ( elementsToAdd.hasNext() ) { - addedElements.add( element ); + addElement( elementsToAdd.next() ); } } + public void add( long element ) + { + checkAddedElements(); + addElement( element ); + } + public boolean remove( long element ) { checkRemovedElements(); - boolean removed = addedElements.remove( element ); - return removed || removedElements.add( element ); + return removeElement( element ); } - public void accept( PrimitiveLongDiffSetsVisitor visitor ) + public void visit( PrimitiveLongDiffSetsVisitor visitor ) throws ConstraintValidationException, CreateConstraintFailureException { PrimitiveLongIterator addedItems = addedElements.iterator(); @@ -98,16 +111,12 @@ public void accept( PrimitiveLongDiffSetsVisitor visitor ) } } - public T augment( T source ) + @Override + public PrimitiveLongIterator augment( PrimitiveLongIterator source ) { return (T) new DiffApplyingPrimitiveLongIterator( source, addedElements, removedElements ); } - public PrimitiveLongIterator augmentWithRemovals( PrimitiveLongIterator source ) - { - return new DiffApplyingPrimitiveLongIterator( source, PrimitiveLongCollections.emptySet(), removedElements ); - } - @Override public int delta() { @@ -129,7 +138,7 @@ public PrimitiveLongSet getRemoved() @Override public PrimitiveLongSet getAddedSnapshot() { - return PrimitiveLongCollections.asSet( addedElements ); + return asSet( addedElements ); } @Override @@ -138,6 +147,21 @@ public boolean isEmpty() return addedElements.isEmpty() && removedElements.isEmpty(); } + private void addElement( long element ) + { + boolean removed = removedElements.remove( element ); + if ( !removed ) + { + addedElements.add( element ); + } + } + + private boolean removeElement( long element ) + { + boolean removed = addedElements.remove( element ); + return removed || removedElements.add( element ); + } + private void checkAddedElements() { if ( emptySet() == addedElements ) diff --git a/community/kernel/src/main/java/org/neo4j/storageengine/api/txstate/PrimitiveLongReadableDiffSets.java b/community/kernel/src/main/java/org/neo4j/storageengine/api/txstate/PrimitiveLongReadableDiffSets.java index 93b3c8c73aa66..3143079637d0f 100644 --- a/community/kernel/src/main/java/org/neo4j/storageengine/api/txstate/PrimitiveLongReadableDiffSets.java +++ b/community/kernel/src/main/java/org/neo4j/storageengine/api/txstate/PrimitiveLongReadableDiffSets.java @@ -19,6 +19,7 @@ */ package org.neo4j.storageengine.api.txstate; +import org.neo4j.collection.primitive.PrimitiveLongIterator; import org.neo4j.collection.primitive.PrimitiveLongSet; /** @@ -72,4 +73,12 @@ public interface PrimitiveLongReadableDiffSets * @return difference between number of added and removed elements */ int delta(); + + /** + * Augment current diff sets with elements. Provided element will be augmented if diffset + * does not remove and add that specific element. + * @param elements elements to augment with + * @return iterator that will iterate over augmented elements as well as over diff set + */ + PrimitiveLongIterator augment( PrimitiveLongIterator elements ); } diff --git a/community/kernel/src/main/java/org/neo4j/storageengine/api/txstate/ReadableTransactionState.java b/community/kernel/src/main/java/org/neo4j/storageengine/api/txstate/ReadableTransactionState.java index 211886deb0853..665650f6263c0 100644 --- a/community/kernel/src/main/java/org/neo4j/storageengine/api/txstate/ReadableTransactionState.java +++ b/community/kernel/src/main/java/org/neo4j/storageengine/api/txstate/ReadableTransactionState.java @@ -125,19 +125,19 @@ public interface ReadableTransactionState Long indexCreatedForConstraint( ConstraintDescriptor constraint ); - ReadableDiffSets indexUpdatesForScan( IndexDescriptor index ); + PrimitiveLongReadableDiffSets indexUpdatesForScan( IndexDescriptor index ); - ReadableDiffSets indexUpdatesForSeek( IndexDescriptor index, ValueTuple values ); + PrimitiveLongReadableDiffSets indexUpdatesForSeek( IndexDescriptor index, ValueTuple values ); - ReadableDiffSets indexUpdatesForRangeSeekByNumber( IndexDescriptor index, + PrimitiveLongReadableDiffSets indexUpdatesForRangeSeekByNumber( IndexDescriptor index, Number lower, boolean includeLower, Number upper, boolean includeUpper ); - ReadableDiffSets indexUpdatesForRangeSeekByString( IndexDescriptor index, + PrimitiveLongReadableDiffSets indexUpdatesForRangeSeekByString( IndexDescriptor index, String lower, boolean includeLower, String upper, boolean includeUpper ); - ReadableDiffSets indexUpdatesForRangeSeekByPrefix( IndexDescriptor index, String prefix ); + PrimitiveLongReadableDiffSets indexUpdatesForRangeSeekByPrefix( IndexDescriptor index, String prefix ); NodeState getNodeState( long id ); diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/DiffSetsTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/DiffSetsTest.java index 3b1fa01e029bd..a208ab424b91e 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/DiffSetsTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/DiffSetsTest.java @@ -38,6 +38,8 @@ public class DiffSetsTest { + private static final Predicate ODD_FILTER = item -> item % 2 == 1L; + @Test public void testAdd() { @@ -244,6 +246,4 @@ public void replaceMultipleTimesWithNoInitialValue() throws Exception assertEquals( asSet( 2 ), diff.getAdded() ); assertEquals( asSet( 0 ), diff.getRemoved() ); } - - private static final Predicate ODD_FILTER = item -> item % 2 == 1L; } diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/state/StateHandlingStatementOperationsTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/state/StateHandlingStatementOperationsTest.java index d6af99af53095..3d35ba6ae7eaf 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/state/StateHandlingStatementOperationsTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/state/StateHandlingStatementOperationsTest.java @@ -51,6 +51,7 @@ import org.neo4j.kernel.impl.index.ExplicitIndexStore; import org.neo4j.kernel.impl.storageengine.impl.recordstorage.StoreStatement; import org.neo4j.kernel.impl.util.diffsets.DiffSets; +import org.neo4j.kernel.impl.util.diffsets.PrimitiveLongDiffSets; import org.neo4j.storageengine.api.NodeItem; import org.neo4j.storageengine.api.PropertyItem; import org.neo4j.storageengine.api.RelationshipItem; @@ -74,6 +75,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; +import static org.neo4j.collection.primitive.PrimitiveLongCollections.setOf; import static org.neo4j.helpers.collection.Iterators.asIterable; import static org.neo4j.helpers.collection.Iterators.asSet; import static org.neo4j.helpers.collection.Iterators.iterator; @@ -221,9 +223,7 @@ public void shouldConsiderTransactionStateDuringIndexScanWithIndexQuery() throws KernelStatement statement = mock( KernelStatement.class ); when( statement.hasTxStateWithChanges() ).thenReturn( true ); when( statement.txState() ).thenReturn( txState ); - when( txState.indexUpdatesForScan( index ) ).thenReturn( - new DiffSets<>( Collections.singleton( 42L ), Collections.singleton( 44L ) ) - ); + when( txState.indexUpdatesForScan( index ) ).thenReturn( new PrimitiveLongDiffSets( setOf( 42L ), setOf( 44L ) ) ); when( txState.addedAndRemovedNodes() ).thenReturn( new DiffSets<>( Collections.singleton( 45L ), Collections.singleton( 46L ) ) ); @@ -252,9 +252,8 @@ public void shouldConsiderTransactionStateDuringIndexSeekWithIndexQuery() throws KernelStatement statement = mock( KernelStatement.class ); when( statement.hasTxStateWithChanges() ).thenReturn( true ); when( statement.txState() ).thenReturn( txState ); - when( txState.indexUpdatesForSeek( index, ValueTuple.of( "value" ) ) ).thenReturn( - new DiffSets<>( Collections.singleton( 42L ), Collections.singleton( 44L ) ) - ); + when( txState.indexUpdatesForSeek( index, ValueTuple.of( "value" ) ) ) + .thenReturn( new PrimitiveLongDiffSets( setOf( 42L ), setOf( 44L ) ) ); when( txState.addedAndRemovedNodes() ).thenReturn( new DiffSets<>( Collections.singleton( 45L ), Collections.singleton( 46L ) ) ); @@ -274,36 +273,6 @@ public void shouldConsiderTransactionStateDuringIndexSeekWithIndexQuery() throws assertEquals( asSet( 42L, 43L ), PrimitiveLongCollections.toSet( results ) ); } - @Test - public void shouldConsiderTransactionStateDuringIndexRangeSeekByPrefix() throws Exception - { - // Given - TransactionState txState = mock( TransactionState.class ); - KernelStatement statement = mock( KernelStatement.class ); - when( statement.hasTxStateWithChanges() ).thenReturn( true ); - when( statement.txState() ).thenReturn( txState ); - when( txState.indexUpdatesForRangeSeekByPrefix( index, "prefix" ) ).thenReturn( - new DiffSets<>( Collections.singleton( 42L ), Collections.singleton( 44L ) ) - ); - when( txState.addedAndRemovedNodes() ).thenReturn( - new DiffSets<>( Collections.singleton( 45L ), Collections.singleton( 46L ) ) - ); - - StoreReadLayer storeReadLayer = mock( StoreReadLayer.class ); - IndexReader indexReader = addMockedIndexReader( statement ); - IndexQuery.StringPrefixPredicate query = IndexQuery.stringPrefix( index.schema().getPropertyId(), "prefix" ); - when( indexReader.query( query ) ) - .thenReturn( PrimitiveLongCollections.resourceIterator( PrimitiveLongCollections.iterator( 43L, 44L, 46L ), null ) ); - - StateHandlingStatementOperations context = newTxStateOps( storeReadLayer ); - - // When - PrimitiveLongIterator results = context.indexQuery( statement, index, query ); - - // Then - assertEquals( asSet( 42L, 43L ), PrimitiveLongCollections.toSet( results ) ); - } - @Test public void shouldConsiderTransactionStateDuringIndexRangeSeekByPrefixWithIndexQuery() throws Exception { @@ -313,7 +282,7 @@ public void shouldConsiderTransactionStateDuringIndexRangeSeekByPrefixWithIndexQ when( statement.hasTxStateWithChanges() ).thenReturn( true ); when( statement.txState() ).thenReturn( txState ); when( txState.indexUpdatesForRangeSeekByPrefix( index, "prefix" ) ).thenReturn( - new DiffSets<>( Collections.singleton( 42L ), Collections.singleton( 44L ) ) + new PrimitiveLongDiffSets( setOf( 42L ), setOf( 44L ) ) ); when( txState.addedAndRemovedNodes() ).thenReturn( new DiffSets<>( Collections.singleton( 45L ), Collections.singleton( 46L ) ) @@ -343,7 +312,7 @@ public void shouldConsiderTransactionStateDuringIndexRangeSeekByContainsWithInde when( statement.hasTxStateWithChanges() ).thenReturn( true ); when( statement.txState() ).thenReturn( txState ); when( txState.indexUpdatesForScan( index ) ).thenReturn( - new DiffSets<>( Collections.singleton( 42L ), Collections.singleton( 44L ) ) + new PrimitiveLongDiffSets( setOf( 42L ), setOf( 44L ) ) ); when( txState.addedAndRemovedNodes() ).thenReturn( new DiffSets<>( Collections.singleton( 45L ), Collections.singleton( 46L ) ) @@ -373,7 +342,7 @@ public void shouldConsiderTransactionStateDuringIndexRangeSeekBySuffixWithIndexQ when( statement.hasTxStateWithChanges() ).thenReturn( true ); when( statement.txState() ).thenReturn( txState ); when( txState.indexUpdatesForScan( index ) ).thenReturn( - new DiffSets<>( Collections.singleton( 42L ), Collections.singleton( 44L ) ) + new PrimitiveLongDiffSets( setOf( 42L ), setOf( 44L ) ) ); when( txState.addedAndRemovedNodes() ).thenReturn( new DiffSets<>( Collections.singleton( 45L ), Collections.singleton( 46L ) ) @@ -411,7 +380,7 @@ public void shouldConsiderTransactionStateDuringIndexBetweenRangeSeekByNumberWit StorageStatement storageStatement = mock( StorageStatement.class ); when( statement.getStoreStatement() ).thenReturn( storageStatement ); when( txState.indexUpdatesForRangeSeekByNumber( index, lower, true, upper, false ) ).thenReturn( - new DiffSets<>( Collections.singleton( 42L ), Collections.singleton( 44L ) ) + new PrimitiveLongDiffSets( setOf( 42L ), setOf( 44L ) ) ); when( txState.addedAndRemovedNodes() ).thenReturn( new DiffSets<>( Collections.singleton( 45L ), Collections.singleton( 46L ) ) @@ -458,9 +427,8 @@ public void shouldConsiderTransactionStateDuringIndexBetweenRangeSeekByStringWit KernelStatement statement = mock( KernelStatement.class ); when( statement.hasTxStateWithChanges() ).thenReturn( true ); when( statement.txState() ).thenReturn( txState ); - when( txState.indexUpdatesForRangeSeekByString( index, "Anne", true, "Bill", false ) ).thenReturn( - new DiffSets<>( Collections.singleton( 42L ), Collections.singleton( 44L ) ) - ); + when( txState.indexUpdatesForRangeSeekByString( index, "Anne", true, "Bill", false ) ) + .thenReturn( new PrimitiveLongDiffSets( setOf( 42L ), setOf( 44L ) ) ); when( txState.addedAndRemovedNodes() ).thenReturn( new DiffSets<>( Collections.singleton( 45L ), Collections.singleton( 46L ) ) ); diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/state/TxStateCompositeIndexTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/state/TxStateCompositeIndexTest.java index be6d0fc24708f..c690c01fce0dc 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/state/TxStateCompositeIndexTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/state/TxStateCompositeIndexTest.java @@ -30,11 +30,12 @@ import org.neo4j.kernel.api.schema.index.IndexDescriptor; import org.neo4j.kernel.api.schema.index.IndexDescriptorFactory; import org.neo4j.kernel.api.txstate.TransactionState; -import org.neo4j.storageengine.api.txstate.ReadableDiffSets; +import org.neo4j.storageengine.api.txstate.PrimitiveLongReadableDiffSets; import org.neo4j.values.storable.ValueTuple; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import static org.neo4j.collection.primitive.PrimitiveLongCollections.toSet; import static org.neo4j.helpers.collection.Iterators.asSet; import static org.neo4j.helpers.collection.Pair.of; @@ -57,7 +58,7 @@ public void before() throws Exception public void shouldScanOnAnEmptyTxState() throws Exception { // WHEN - ReadableDiffSets diffSets = state.indexUpdatesForScan( indexOn_1_1_2 ); + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForScan( indexOn_1_1_2 ); // THEN assertTrue( diffSets.isEmpty() ); @@ -67,7 +68,7 @@ public void shouldScanOnAnEmptyTxState() throws Exception public void shouldSeekOnAnEmptyTxState() throws Exception { // WHEN - ReadableDiffSets diffSets = + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForSeek( indexOn_1_1_2, ValueTuple.of( "43value1", "43value2" ) ); // THEN @@ -82,10 +83,10 @@ public void shouldScanWhenThereAreNewNodes() throws Exception modifyIndex( indexOn_1_2_3 ).addDefaultStringEntries( 44L ); // WHEN - ReadableDiffSets diffSets = state.indexUpdatesForScan( indexOn_1_1_2 ); + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForScan( indexOn_1_1_2 ); // THEN - assertEquals( asSet( 42L, 43L ), diffSets.getAdded() ); + assertEquals( asSet( 42L, 43L ), toSet( diffSets.getAdded() ) ); } @Test @@ -96,11 +97,11 @@ public void shouldSeekWhenThereAreNewStringNodes() throws Exception modifyIndex( indexOn_1_2_3 ).addDefaultStringEntries( 44L ); // WHEN - ReadableDiffSets diffSets = + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForSeek( indexOn_1_1_2, ValueTuple.of( "43value1", "43value2" ) ); // THEN - assertEquals( asSet( 43L ), diffSets.getAdded() ); + assertEquals( asSet( 43L ), toSet( diffSets.getAdded() ) ); } @Test @@ -111,11 +112,11 @@ public void shouldSeekWhenThereAreNewNumberNodes() throws Exception modifyIndex( indexOn_1_2_3 ).addDefaultStringProperties( 44L ); // WHEN - ReadableDiffSets diffSets = + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForSeek( indexOn_1_1_2, ValueTuple.of( 43001.0, 43002.0 ) ); // THEN - assertEquals( asSet( 43L ), diffSets.getAdded() ); + assertEquals( asSet( 43L ), toSet( diffSets.getAdded() ) ); } @Test @@ -127,12 +128,11 @@ public void shouldHandleMixedAddsAndRemovesEntry() throws Exception modifyIndex( indexOn_1_1_2 ).removeDefaultStringEntries( 44L ); // WHEN - ReadableDiffSets diffSets = - state.indexUpdatesForScan( indexOn_1_1_2 ); + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForScan( indexOn_1_1_2 ); // THEN - assertEquals( asSet( 42L ), diffSets.getAdded() ); - assertEquals( asSet( 44L ), diffSets.getRemoved() ); + assertEquals( asSet( 42L ), toSet( diffSets.getAdded() ) ); + assertEquals( asSet( 44L ), toSet( diffSets.getRemoved() ) ); } @Test @@ -144,11 +144,11 @@ public void shouldSeekWhenThereAreManyEntriesWithTheSameValues() throws Exceptio getDefaultStringPropertyValues( 43L, indexOn_1_1_2.schema().getPropertyIds() ) ); // WHEN - ReadableDiffSets diffSets = + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForSeek( indexOn_1_1_2, ValueTuple.of( "43value1", "43value2" ) ); // THEN - assertEquals( asSet( 43L, 44L ), diffSets.getAdded() ); + assertEquals( asSet( 43L, 44L ), toSet( diffSets.getAdded() ) ); } @Test @@ -192,10 +192,10 @@ private void assertSeek( IndexDescriptor index, ValueTuple[] values, long nodeId for ( int i = 0; i < values.length; i++ ) { // WHEN - ReadableDiffSets diffSets = state.indexUpdatesForSeek( index, values[i] ); + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForSeek( index, values[i] ); // THEN - assertEquals( asSet( nodeIdStart + i ), diffSets.getAdded() ); + assertEquals( asSet( nodeIdStart + i ), toSet( diffSets.getAdded() ) ); } } diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/state/TxStateTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/state/TxStateTest.java index 13bf6dbbebdd6..77c2a130c2c5d 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/state/TxStateTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/state/TxStateTest.java @@ -46,6 +46,7 @@ import org.neo4j.kernel.api.txstate.TransactionState; import org.neo4j.storageengine.api.Direction; import org.neo4j.storageengine.api.RelationshipItem; +import org.neo4j.storageengine.api.txstate.PrimitiveLongReadableDiffSets; import org.neo4j.storageengine.api.txstate.ReadableDiffSets; import org.neo4j.storageengine.api.txstate.TxStateVisitor; import org.neo4j.test.rule.RandomRule; @@ -66,6 +67,7 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.neo4j.collection.primitive.PrimitiveIntCollections.toList; +import static org.neo4j.collection.primitive.PrimitiveLongCollections.toSet; import static org.neo4j.helpers.collection.Iterators.asSet; import static org.neo4j.helpers.collection.Pair.of; import static org.neo4j.kernel.impl.api.state.StubCursors.cursor; @@ -194,7 +196,7 @@ public void shouldAddAndGetByRuleId() throws Exception public void shouldComputeIndexUpdatesForScanOrSeekOnAnEmptyTxState() throws Exception { // WHEN - ReadableDiffSets diffSets = state.indexUpdatesForScan( indexOn_1_1 ); + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForScan( indexOn_1_1 ); // THEN assertTrue( diffSets.isEmpty() ); @@ -208,10 +210,10 @@ public void shouldComputeIndexUpdatesForScanWhenThereAreNewNodes() throws Except addNodesToIndex( indexOn_1_2 ).withDefaultStringProperties( 44L ); // WHEN - ReadableDiffSets diffSets = state.indexUpdatesForScan( indexOn_1_1 ); + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForScan( indexOn_1_1 ); // THEN - assertEquals( asSet( 42L, 43L ), diffSets.getAdded() ); + assertEquals( asSet( 42L, 43L ), toSet( diffSets.getAdded() ) ); } @Test @@ -222,10 +224,10 @@ public void shouldComputeIndexUpdatesForSeekWhenThereAreNewNodes() throws Except addNodesToIndex( indexOn_1_2 ).withDefaultStringProperties( 44L ); // WHEN - ReadableDiffSets diffSets = state.indexUpdatesForSeek( indexOn_1_1, ValueTuple.of( "value43" ) ); + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForSeek( indexOn_1_1, ValueTuple.of( "value43" ) ); // THEN - assertEquals( asSet( 43L ), diffSets.getAdded() ); + assertEquals( asSet( 43L ), toSet( diffSets.getAdded() ) ); } //endregion @@ -240,10 +242,10 @@ public void shouldComputeIndexUpdatesForBetweenRangeSeekByNumberWhenThereAreNoMa addNodesToIndex( indexOn_1_2 ).withNumberProperties( singletonList( of( 44L, 520 ) ) ); // WHEN - ReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByNumber( indexOn_1_1, 660, false, 800, true ); + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByNumber( indexOn_1_1, 660, false, 800, true ); // THEN - assertEquals( emptySet(), diffSets.getAdded() ); + assertEquals( emptySet(), toSet( diffSets.getAdded() ) ); } @Test @@ -255,10 +257,10 @@ public void shouldComputeIndexUpdatesForBetweenRangeSeekByNumberWhenThereAreNewN addNodesToIndex( indexOn_1_2 ).withNumberProperties( singletonList( of( 44L, 520 ) ) ); // WHEN - ReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByNumber( indexOn_1_1, 510, true, 600, true ); + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByNumber( indexOn_1_1, 510, true, 600, true ); // THEN - assertEquals( asSet( 43L ), diffSets.getAdded() ); + assertEquals( asSet( 43L ), toSet( diffSets.getAdded() ) ); } @Test @@ -271,10 +273,10 @@ public void shouldComputeIndexUpdatesForBetweenRangeSeekByNumberWhenThereAreNewN addNodesToIndex( indexOn_1_1 ).withNumberProperties( singletonList( of( 43L, 550 ) ) ); // WHEN - ReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByNumber( indexOn_1_1, 510, true, 600, true ); + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByNumber( indexOn_1_1, 510, true, 600, true ); // THEN - assertEquals( asSet( 43L ), diffSets.getAdded() ); + assertEquals( asSet( 43L ), toSet( diffSets.getAdded() ) ); } @Test @@ -287,10 +289,10 @@ public void shouldComputeIndexUpdatesForBetweenRangeSeekByNumberWithIncludeLower addNodesToIndex( indexOn_1_2 ).withNumberProperties( singletonList( of( 46L, 520 ) ) ); // WHEN - ReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByNumber( indexOn_1_1, 510, true, 550, true ); + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByNumber( indexOn_1_1, 510, true, 550, true ); // THEN - assertEquals( asSet( 43L, 44L, 45L, 47L, 48L ), diffSets.getAdded() ); + assertEquals( asSet( 43L, 44L, 45L, 47L, 48L ), toSet( diffSets.getAdded() ) ); } @Test @@ -303,10 +305,10 @@ public void shouldComputeIndexUpdatesForBetweenRangeSeekByNumberWithIncludeLower addNodesToIndex( indexOn_1_2 ).withNumberProperties( singletonList( of( 46L, 520 ) ) ); // WHEN - ReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByNumber( indexOn_1_1, 510, true, 550, false ); + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByNumber( indexOn_1_1, 510, true, 550, false ); // THEN - assertEquals( asSet( 43L, 44L, 45L, 47L ), diffSets.getAdded() ); + assertEquals( asSet( 43L, 44L, 45L, 47L ), toSet( diffSets.getAdded() ) ); } @Test @@ -319,10 +321,10 @@ public void shouldComputeIndexUpdatesForBetweenRangeSeekByNumberWithExcludeLower addNodesToIndex( indexOn_1_2 ).withNumberProperties( singletonList( of( 46L, 520 ) ) ); // WHEN - ReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByNumber( indexOn_1_1, 510, false, 550, true ); + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByNumber( indexOn_1_1, 510, false, 550, true ); // THEN - assertEquals( asSet( 44L, 45L, 47L, 48L ), diffSets.getAdded() ); + assertEquals( asSet( 44L, 45L, 47L, 48L ), toSet( diffSets.getAdded() ) ); } @Test @@ -335,10 +337,10 @@ public void shouldComputeIndexUpdatesForBetweenRangeSeekByNumberWithExcludeLower addNodesToIndex( indexOn_1_2 ).withNumberProperties( singletonList( of( 46L, 520 ) ) ); // WHEN - ReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByNumber( indexOn_1_1, 510, false, 550, false ); + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByNumber( indexOn_1_1, 510, false, 550, false ); // THEN - assertEquals( asSet( 44L, 45L, 47L ), diffSets.getAdded() ); + assertEquals( asSet( 44L, 45L, 47L ), toSet( diffSets.getAdded() ) ); } @Test @@ -353,10 +355,10 @@ public void shouldComputeIndexUpdatesForBetweenRangeSeekByNumberWithUnboundedLow addNodesToIndex( indexOn_1_2 ).withNumberProperties( singletonList( of( 46L, 520 ) ) ); // WHEN - ReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByNumber( indexOn_1_1, null, false, 550, true ); + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByNumber( indexOn_1_1, null, false, 550, true ); // THEN - assertEquals( asSet( 42L, 43L, 44L, 45L, 47L, 48L ), diffSets.getAdded() ); + assertEquals( asSet( 42L, 43L, 44L, 45L, 47L, 48L ), toSet( diffSets.getAdded() ) ); } @Test @@ -371,10 +373,10 @@ public void shouldComputeIndexUpdatesForBetweenRangeSeekByNumberWithUnboundedLow addNodesToIndex( indexOn_1_2 ).withNumberProperties( singletonList( of( 46L, 520 ) ) ); // WHEN - ReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByNumber( indexOn_1_1, null, true, 550, true ); + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByNumber( indexOn_1_1, null, true, 550, true ); // THEN - assertEquals( asSet( 42L, 43L, 44L, 45L, 47L, 48L ), diffSets.getAdded() ); + assertEquals( asSet( 42L, 43L, 44L, 45L, 47L, 48L ), toSet( diffSets.getAdded() ) ); } @Test @@ -389,11 +391,11 @@ public void shouldComputeIndexUpdatesForBetweenRangeSeekByNumberWithUnboundedLow addNodesToIndex( indexOn_1_2 ).withNumberProperties( singletonList( of( 46L, 520 ) ) ); // WHEN - ReadableDiffSets diffSets = + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByNumber( indexOn_1_1, null, false, 550, false ); // THEN - assertEquals( asSet( 42L, 43L, 44L, 45L, 47L ), diffSets.getAdded() ); + assertEquals( asSet( 42L, 43L, 44L, 45L, 47L ), toSet( diffSets.getAdded() ) ); } @Test @@ -408,10 +410,10 @@ public void shouldComputeIndexUpdatesForBetweenRangeSeekByNumberWithUnboundedLow addNodesToIndex( indexOn_1_2 ).withNumberProperties( singletonList( of( 46L, 520 ) ) ); // WHEN - ReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByNumber( indexOn_1_1, null, true, 550, false ); + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByNumber( indexOn_1_1, null, true, 550, false ); // THEN - assertEquals( asSet( 42L, 43L, 44L, 45L, 47L ), diffSets.getAdded() ); + assertEquals( asSet( 42L, 43L, 44L, 45L, 47L ), toSet( diffSets.getAdded() ) ); } @Test @@ -426,10 +428,10 @@ public void shouldComputeIndexUpdatesForBetweenRangeSeekByNumberWithUnboundedUpp addNodesToIndex( indexOn_1_2 ).withNumberProperties( singletonList( of( 46L, 520 ) ) ); // WHEN - ReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByNumber( indexOn_1_1, 540, true, null, true ); + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByNumber( indexOn_1_1, 540, true, null, true ); // THEN - assertEquals( asSet( 47L, 48L, 49L ), diffSets.getAdded() ); + assertEquals( asSet( 47L, 48L, 49L ), toSet( diffSets.getAdded() ) ); } @Test @@ -444,10 +446,10 @@ public void shouldComputeIndexUpdatesForBetweenRangeSeekByNumberWithUnboundedUpp addNodesToIndex( indexOn_1_2 ).withNumberProperties( singletonList( of( 46L, 520 ) ) ); // WHEN - ReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByNumber( indexOn_1_1, 540, true, null, false ); + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByNumber( indexOn_1_1, 540, true, null, false ); // THEN - assertEquals( asSet( 47L, 48L, 49L ), diffSets.getAdded() ); + assertEquals( asSet( 47L, 48L, 49L ), toSet( diffSets.getAdded() ) ); } @Test @@ -462,10 +464,10 @@ public void shouldComputeIndexUpdatesForBetweenRangeSeekByNumberWithUnboundedUpp addNodesToIndex( indexOn_1_2 ).withNumberProperties( singletonList( of( 46L, 520 ) ) ); // WHEN - ReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByNumber( indexOn_1_1, 540, false, null, true ); + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByNumber( indexOn_1_1, 540, false, null, true ); // THEN - assertEquals( asSet( 48L, 49L ), diffSets.getAdded() ); + assertEquals( asSet( 48L, 49L ), toSet( diffSets.getAdded() ) ); } @Test @@ -480,11 +482,11 @@ public void shouldComputeIndexUpdatesForBetweenRangeSeekByNumberWithUnboundedUpp addNodesToIndex( indexOn_1_2 ).withNumberProperties( singletonList( of( 46L, 520 ) ) ); // WHEN - ReadableDiffSets diffSets = + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByNumber( indexOn_1_1, 540, false, null, false ); // THEN - assertEquals( asSet( 48L, 49L ), diffSets.getAdded() ); + assertEquals( asSet( 48L, 49L ), toSet( diffSets.getAdded() ) ); } @Test @@ -496,10 +498,10 @@ public void shouldComputeIndexUpdatesForBetweenRangeSeekByNumberWithNoBounds() t addNodesToIndex( indexOn_1_2 ).withNumberProperties( singletonList( of( 46L, 520 ) ) ); // WHEN - ReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByNumber( indexOn_1_1, null, true, null, true ); + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByNumber( indexOn_1_1, null, true, null, true ); // THEN - assertEquals( asSet( 42L, 43L, 44L ), diffSets.getAdded() ); + assertEquals( asSet( 42L, 43L, 44L ), toSet( diffSets.getAdded() ) ); } //endregion @@ -514,11 +516,11 @@ public void shouldComputeIndexUpdatesForBetweenRangeSeekByStringWhenThereAreNoMa addNodesToIndex( indexOn_1_2 ).withStringProperties( singletonList( of( 44L, "Andreas" ) ) ); // WHEN - ReadableDiffSets diffSets = + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByString( indexOn_1_1, "Cindy", false, "William", true ); // THEN - assertEquals( emptySet(), diffSets.getAdded() ); + assertEquals( emptySet(), toSet( diffSets.getAdded() ) ); } @Test @@ -530,11 +532,11 @@ public void shouldComputeIndexUpdatesForBetweenRangeSeekByStringWhenThereAreNewN addNodesToIndex( indexOn_1_2 ).withStringProperties( singletonList( of( 44L, "Andreas" ) ) ); // WHEN - ReadableDiffSets diffSets = + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByString( indexOn_1_1, "Amy", true, "Cathy", true ); // THEN - assertEquals( asSet( 43L ), diffSets.getAdded() ); + assertEquals( asSet( 43L ), toSet( diffSets.getAdded() ) ); } @Test @@ -547,11 +549,11 @@ public void shouldComputeIndexUpdatesForBetweenRangeSeekByStringWhenThereAreNewN addNodesToIndex( indexOn_1_1 ).withStringProperties( singletonList( of( 43L, "Barbara" ) ) ); // WHEN - ReadableDiffSets diffSets = + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByString( indexOn_1_1, "Amy", true, "Cathy", true ); // THEN - assertEquals( asSet( 43L ), diffSets.getAdded() ); + assertEquals( asSet( 43L ), toSet( diffSets.getAdded() ) ); } @Test @@ -564,11 +566,11 @@ public void shouldComputeIndexUpdatesForBetweenRangeSeekByStringWithIncludeLower addNodesToIndex( indexOn_1_2 ).withStringProperties( singletonList( of( 46L, "Andreas" ) ) ); // WHEN - ReadableDiffSets diffSets = + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByString( indexOn_1_1, "Amy", true, "Arwen", true ); // THEN - assertEquals( asSet( 43L, 44L, 45L, 47L, 48L ), diffSets.getAdded() ); + assertEquals( asSet( 43L, 44L, 45L, 47L, 48L ), toSet( diffSets.getAdded() ) ); } @Test @@ -581,11 +583,11 @@ public void shouldComputeIndexUpdatesForBetweenRangeSeekByStringWithIncludeLower addNodesToIndex( indexOn_1_2 ).withStringProperties( singletonList( of( 46L, "Andreas" ) ) ); // WHEN - ReadableDiffSets diffSets = + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByString( indexOn_1_1, "Amy", true, "Arwen", false ); // THEN - assertEquals( asSet( 43L, 44L, 45L, 47L ), diffSets.getAdded() ); + assertEquals( asSet( 43L, 44L, 45L, 47L ), toSet( diffSets.getAdded() ) ); } @Test @@ -598,11 +600,11 @@ public void shouldComputeIndexUpdatesForBetweenRangeSeekByStringWithExcludeLower addNodesToIndex( indexOn_1_2 ).withStringProperties( singletonList( of( 46L, "Andreas" ) ) ); // WHEN - ReadableDiffSets diffSets = + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByString( indexOn_1_1, "Amy", false, "Arwen", true ); // THEN - assertEquals( asSet( 44L, 45L, 47L, 48L ), diffSets.getAdded() ); + assertEquals( asSet( 44L, 45L, 47L, 48L ), toSet( diffSets.getAdded() ) ); } @Test @@ -615,11 +617,11 @@ public void shouldComputeIndexUpdatesForBetweenRangeSeekByStringWithExcludeLower addNodesToIndex( indexOn_1_2 ).withStringProperties( singletonList( of( 46L, "Andreas" ) ) ); // WHEN - ReadableDiffSets diffSets = + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByString( indexOn_1_1, "Amy", false, "Arwen", false ); // THEN - assertEquals( asSet( 44L, 45L, 47L ), diffSets.getAdded() ); + assertEquals( asSet( 44L, 45L, 47L ), toSet( diffSets.getAdded() ) ); } @Test @@ -634,11 +636,11 @@ public void shouldComputeIndexUpdatesForBetweenRangeSeekByStringWithUnboundedLow addNodesToIndex( indexOn_1_2 ).withStringProperties( singletonList( of( 46L, "Andreas" ) ) ); // WHEN - ReadableDiffSets diffSets = + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByString( indexOn_1_1, null, false, "Arwen", true ); // THEN - assertEquals( asSet( 42L, 43L, 44L, 45L, 47L, 48L ), diffSets.getAdded() ); + assertEquals( asSet( 42L, 43L, 44L, 45L, 47L, 48L ), toSet( diffSets.getAdded() ) ); } @Test @@ -653,11 +655,11 @@ public void shouldComputeIndexUpdatesForBetweenRangeSeekByStringWithUnboundedLow addNodesToIndex( indexOn_1_2 ).withStringProperties( singletonList( of( 46L, "Andreas" ) ) ); // WHEN - ReadableDiffSets diffSets = + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByString( indexOn_1_1, null, true, "Arwen", true ); // THEN - assertEquals( asSet( 42L, 43L, 44L, 45L, 47L, 48L ), diffSets.getAdded() ); + assertEquals( asSet( 42L, 43L, 44L, 45L, 47L, 48L ), toSet( diffSets.getAdded() ) ); } @Test @@ -672,11 +674,11 @@ public void shouldComputeIndexUpdatesForBetweenRangeSeekByStringWithUnboundedLow addNodesToIndex( indexOn_1_2 ).withStringProperties( singletonList( of( 46L, "Andreas" ) ) ); // WHEN - ReadableDiffSets diffSets = + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByString( indexOn_1_1, null, false, "Arwen", false ); // THEN - assertEquals( asSet( 42L, 43L, 44L, 45L, 47L ), diffSets.getAdded() ); + assertEquals( asSet( 42L, 43L, 44L, 45L, 47L ), toSet( diffSets.getAdded() ) ); } @Test @@ -691,11 +693,11 @@ public void shouldComputeIndexUpdatesForBetweenRangeSeekByStringWithUnboundedLow addNodesToIndex( indexOn_1_2 ).withStringProperties( singletonList( of( 46L, "Andreas" ) ) ); // WHEN - ReadableDiffSets diffSets = + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByString( indexOn_1_1, null, true, "Arwen", false ); // THEN - assertEquals( asSet( 42L, 43L, 44L, 45L, 47L ), diffSets.getAdded() ); + assertEquals( asSet( 42L, 43L, 44L, 45L, 47L ), toSet( diffSets.getAdded() ) ); } @Test @@ -710,11 +712,11 @@ public void shouldComputeIndexUpdatesForBetweenRangeSeekByStringWithUnboundedUpp addNodesToIndex( indexOn_1_2 ).withStringProperties( singletonList( of( 46L, "Andreas" ) ) ); // WHEN - ReadableDiffSets diffSets = + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByString( indexOn_1_1, "Arthur", true, null, true ); // THEN - assertEquals( asSet( 47L, 48L, 49L ), diffSets.getAdded() ); + assertEquals( asSet( 47L, 48L, 49L ), toSet( diffSets.getAdded() ) ); } @Test @@ -729,11 +731,11 @@ public void shouldComputeIndexUpdatesForBetweenRangeSeekByStringWithUnboundedUpp addNodesToIndex( indexOn_1_2 ).withStringProperties( singletonList( of( 46L, "Andreas" ) ) ); // WHEN - ReadableDiffSets diffSets = + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByString( indexOn_1_1, "Arthur", true, null, false ); // THEN - assertEquals( asSet( 47L, 48L, 49L ), diffSets.getAdded() ); + assertEquals( asSet( 47L, 48L, 49L ), toSet( diffSets.getAdded() ) ); } @Test @@ -748,11 +750,11 @@ public void shouldComputeIndexUpdatesForBetweenRangeSeekByStringWithUnboundedUpp addNodesToIndex( indexOn_1_2 ).withStringProperties( singletonList( of( 46L, "Andreas" ) ) ); // WHEN - ReadableDiffSets diffSets = + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByString( indexOn_1_1, "Arthur", false, null, true ); // THEN - assertEquals( asSet( 48L, 49L ), diffSets.getAdded() ); + assertEquals( asSet( 48L, 49L ), toSet( diffSets.getAdded() ) ); } @Test @@ -767,11 +769,11 @@ public void shouldComputeIndexUpdatesForBetweenRangeSeekByStringWithUnboundedUpp addNodesToIndex( indexOn_1_2 ).withStringProperties( singletonList( of( 46L, "Andreas" ) ) ); // WHEN - ReadableDiffSets diffSets = + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByString( indexOn_1_1, "Arthur", false, null, false ); // THEN - assertEquals( asSet( 48L, 49L ), diffSets.getAdded() ); + assertEquals( asSet( 48L, 49L ), toSet( diffSets.getAdded() ) ); } @Test @@ -784,10 +786,10 @@ public void shouldComputeIndexUpdatesForBetweenRangeSeekByStringWithNoBounds() t addNodesToIndex( indexOn_1_2 ).withStringProperties( singletonList( of( 46L, "Andreas" ) ) ); // WHEN - ReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByString( indexOn_1_1, null, true, null, true ); + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByString( indexOn_1_1, null, true, null, true ); // THEN - assertEquals( asSet( 42L, 43L, 44L ), diffSets.getAdded() ); + assertEquals( asSet( 42L, 43L, 44L ), toSet( diffSets.getAdded() ) ); } //endregion @@ -802,10 +804,10 @@ public void shouldComputeIndexUpdatesForRangeSeekByPrefixWhenThereAreNoMatchingN addNodesToIndex( indexOn_1_2 ).withDefaultStringProperties( 44L ); // WHEN - ReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByPrefix( indexOn_1_1, "eulav" ); + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByPrefix( indexOn_1_1, "eulav" ); // THEN - assertEquals( emptySet(), diffSets.getAdded() ); + assertEquals( emptySet(), toSet( diffSets.getAdded() ) ); } @Test @@ -816,10 +818,10 @@ public void shouldComputeIndexUpdatesForRangeSeekByPrefixWhenThereAreNewNodesCre addNodesToIndex( indexOn_1_2 ).withDefaultStringProperties( 44L ); // WHEN - ReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByPrefix( indexOn_1_1, "value" ); + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByPrefix( indexOn_1_1, "value" ); // THEN - assertEquals( asSet( 42L, 43L ), diffSets.getAdded() ); + assertEquals( asSet( 42L, 43L ), toSet( diffSets.getAdded() ) ); } @Test @@ -833,10 +835,10 @@ public void shouldComputeIndexUpdatesForRangeSeekByPrefixWhenThereArePartiallyMa addNodesToIndex( indexOn_1_2 ).withDefaultStringProperties( 44L ); // WHEN - ReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByPrefix( indexOn_1_1, "And" ); + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByPrefix( indexOn_1_1, "And" ); // THEN - assertEquals( asSet( 42L, 43L ), diffSets.getAdded() ); + assertEquals( asSet( 42L, 43L ), toSet( diffSets.getAdded() ) ); } @Test @@ -850,10 +852,10 @@ public void shouldComputeIndexUpdatesForRangeSeekByPrefixWhenThereArePartiallyMa addNodesToIndex( indexOn_1_2 ).withDefaultStringProperties( 44L ); // WHEN - ReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByPrefix( indexOn_1_1, "Bar" ); + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByPrefix( indexOn_1_1, "Bar" ); // THEN - assertEquals( asSet( 45L, 46L ), diffSets.getAdded() ); + assertEquals( asSet( 45L, 46L ), toSet( diffSets.getAdded() ) ); } @Test @@ -868,10 +870,10 @@ public void shouldComputeIndexUpdatesForRangeSeekByPrefixWhenThereArePartiallyMa addNodesToIndex( indexOn_1_2 ).withDefaultStringProperties( 44L ); // WHEN - ReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByPrefix( indexOn_1_1, "Aa" ); + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByPrefix( indexOn_1_1, "Aa" ); // THEN - assertEquals( asSet( 40L ), diffSets.getAdded() ); + assertEquals( asSet( 40L ), toSet( diffSets.getAdded() ) ); } @Test @@ -886,10 +888,10 @@ public void shouldComputeIndexUpdatesForRangeSeekByPrefixWhenThereArePartiallyMa addNodesToIndex( indexOn_1_2 ).withDefaultStringProperties( 44L ); // WHEN - ReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByPrefix( indexOn_1_1, "Ci" ); + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByPrefix( indexOn_1_1, "Ci" ); // THEN - assertEquals( asSet( 47L ), diffSets.getAdded() ); + assertEquals( asSet( 47L ), toSet( diffSets.getAdded() ) ); } @Test @@ -901,10 +903,10 @@ public void shouldComputeIndexUpdatesForRangeSeekByPrefixWhenThereAreNewNodesCre addNodesToIndex( indexOn_1_1 ).withDefaultStringProperties( 43L ); // WHEN - ReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByPrefix( indexOn_1_1, "value" ); + PrimitiveLongReadableDiffSets diffSets = state.indexUpdatesForRangeSeekByPrefix( indexOn_1_1, "value" ); // THEN - assertEquals( asSet( 42L, 43L ), diffSets.getAdded() ); + assertEquals( asSet( 42L, 43L ), toSet( diffSets.getAdded() ) ); } //endregion diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/coreapi/schema/SchemaImplTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/coreapi/schema/SchemaImplTest.java index 3993f76d1be42..557991e9b8a92 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/coreapi/schema/SchemaImplTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/coreapi/schema/SchemaImplTest.java @@ -21,7 +21,6 @@ import org.junit.After; import org.junit.Before; -import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; @@ -42,7 +41,6 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -@Ignore public class SchemaImplTest { @Rule diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/util/diffsets/DiffApplyingPrimitiveLongIteratorTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/util/diffsets/DiffApplyingPrimitiveLongIteratorTest.java new file mode 100644 index 0000000000000..df03110b50427 --- /dev/null +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/util/diffsets/DiffApplyingPrimitiveLongIteratorTest.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2002-2018 "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 . + */ +package org.neo4j.kernel.impl.util.diffsets; + +import org.apache.commons.lang3.ArrayUtils; +import org.junit.Test; + +import java.util.Set; + +import org.neo4j.collection.primitive.PrimitiveLongIterator; +import org.neo4j.collection.primitive.PrimitiveLongSet; + +import static org.hamcrest.Matchers.arrayContainingInAnyOrder; +import static org.hamcrest.Matchers.arrayWithSize; +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.junit.Assert.assertThat; +import static org.neo4j.collection.primitive.PrimitiveLongCollections.asArray; +import static org.neo4j.collection.primitive.PrimitiveLongCollections.emptyIterator; +import static org.neo4j.collection.primitive.PrimitiveLongCollections.iterator; +import static org.neo4j.collection.primitive.PrimitiveLongCollections.setOf; +import static org.neo4j.collection.primitive.PrimitiveLongCollections.toSet; + +public class DiffApplyingPrimitiveLongIteratorTest +{ + @Test + public void iterateOnlyOverAddedElementsWhenSourceIsEmpty() + { + PrimitiveLongIterator emptySource = emptyIterator(); + PrimitiveLongSet added = setOf( 1L, 2L ); + PrimitiveLongSet removed = setOf( 3L ); + + DiffApplyingPrimitiveLongIterator iterator = createIterator( emptySource, added, removed ); + Set resultSet = toSet( iterator ); + assertThat( resultSet, containsInAnyOrder(1L, 2L) ); + } + + @Test + public void appendSourceElementsDuringIteration() + { + PrimitiveLongIterator source = iterator( 4L, 5L ); + PrimitiveLongSet added = setOf( 1L, 2L ); + PrimitiveLongSet removed = setOf( 3L ); + + DiffApplyingPrimitiveLongIterator iterator = createIterator( source, added, removed ); + Set resultSet = toSet( iterator ); + assertThat( resultSet, containsInAnyOrder(1L, 2L, 4L, 5L) ); + } + + @Test + public void doNotIterateTwiceOverSameElementsWhenItsPartOfSourceAndAdded() + { + PrimitiveLongIterator source = iterator( 4L, 5L ); + PrimitiveLongSet added = setOf( 1L, 4L ); + PrimitiveLongSet removed = setOf( 3L ); + + DiffApplyingPrimitiveLongIterator iterator = createIterator( source, added, removed ); + Long[] values = ArrayUtils.toObject( asArray( iterator ) ); + assertThat( values, arrayContainingInAnyOrder( 1L, 4L, 5L ) ); + assertThat( values, arrayWithSize( 3 ) ); + } + + @Test + public void doNotIterateOverDeletedElement() + { + PrimitiveLongIterator source = iterator( 3L, 5L ); + PrimitiveLongSet added = setOf( 1L ); + PrimitiveLongSet removed = setOf( 3L ); + + DiffApplyingPrimitiveLongIterator iterator = createIterator( source, added, removed ); + Set resultSet = toSet( iterator ); + assertThat( resultSet, containsInAnyOrder(1L, 5L) ); + } + + private DiffApplyingPrimitiveLongIterator createIterator( PrimitiveLongIterator source, PrimitiveLongSet added, + PrimitiveLongSet removed ) + { + return new DiffApplyingPrimitiveLongIterator( source, added, removed ); + } +} diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/util/diffsets/PrimitiveLongDiffSetsTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/util/diffsets/PrimitiveLongDiffSetsTest.java new file mode 100644 index 0000000000000..52ff236881dc8 --- /dev/null +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/util/diffsets/PrimitiveLongDiffSetsTest.java @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2002-2018 "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 . + */ +package org.neo4j.kernel.impl.util.diffsets; + +import org.junit.Test; + +import org.neo4j.collection.primitive.Primitive; +import org.neo4j.collection.primitive.PrimitiveLongCollections; +import org.neo4j.collection.primitive.PrimitiveLongIterator; +import org.neo4j.collection.primitive.PrimitiveLongSet; +import org.neo4j.internal.kernel.api.exceptions.schema.ConstraintValidationException; +import org.neo4j.kernel.api.exceptions.schema.CreateConstraintFailureException; +import org.neo4j.storageengine.api.txstate.PrimitiveLongDiffSetsVisitor; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.neo4j.collection.primitive.PrimitiveLongCollections.iterator; +import static org.neo4j.collection.primitive.PrimitiveLongCollections.toSet; +import static org.neo4j.helpers.collection.Iterators.asSet; + +public class PrimitiveLongDiffSetsTest +{ + + @Test + public void newDiffSetIsEmpty() + { + assertTrue( createDiffSet().isEmpty() ); + } + + @Test + public void addElementsToDiffSets() + { + PrimitiveLongDiffSets diffSets = createDiffSet(); + + diffSets.add( 1L ); + diffSets.add( 2L ); + + assertEquals( asSet( 1L, 2L ), toSet( diffSets.getAdded() ) ); + assertTrue( diffSets.getRemoved().isEmpty() ); + assertFalse( diffSets.isEmpty() ); + } + + @Test + public void removeElementsInDiffSets() + { + PrimitiveLongDiffSets diffSets = createDiffSet(); + + diffSets.remove( 1L ); + diffSets.remove( 2L ); + + assertFalse( diffSets.isEmpty() ); + assertEquals( asSet( 1L, 2L ), toSet( diffSets.getRemoved() ) ); + } + + @Test + public void removeAndAddElementsToDiffSets() + { + PrimitiveLongDiffSets diffSets = createDiffSet(); + + diffSets.remove( 1L ); + diffSets.remove( 2L ); + diffSets.add( 1L ); + diffSets.add( 2L ); + diffSets.add( 3L ); + diffSets.remove( 4L ); + + assertFalse( diffSets.isEmpty() ); + assertEquals( asSet( 4L ), toSet( diffSets.getRemoved() ) ); + assertEquals( asSet( 3L ), toSet( diffSets.getAdded() ) ); + } + + @Test + public void checkIsElementsAddedOrRemoved() + { + PrimitiveLongDiffSets diffSet = createDiffSet(); + + diffSet.add( 1L ); + + assertTrue( diffSet.isAdded( 1L ) ); + assertFalse( diffSet.isRemoved( 1L ) ); + + diffSet.remove( 2L ); + + assertFalse( diffSet.isAdded( 2L ) ); + assertTrue( diffSet.isRemoved( 2L ) ); + + assertFalse( diffSet.isAdded( 3L ) ); + assertFalse( diffSet.isRemoved( 3L ) ); + } + + @Test + public void addAllElements() + { + PrimitiveLongDiffSets diffSet = createDiffSet(); + + diffSet.addAll( PrimitiveLongCollections.iterator( 7L, 8L ) ); + diffSet.addAll( PrimitiveLongCollections.iterator( 9L, 10L ) ); + + assertEquals( asSet( 7L, 8L, 9L, 10L ), toSet( diffSet.getAdded() ) ); + } + + @Test + public void removeAllElements() + { + PrimitiveLongDiffSets diffSet = createDiffSet(); + + diffSet.removeAll( PrimitiveLongCollections.iterator( 7L, 8L ) ); + diffSet.removeAll( PrimitiveLongCollections.iterator( 9L, 10L ) ); + + assertEquals( asSet( 7L, 8L, 9L, 10L ), toSet( diffSet.getRemoved() ) ); + } + + @Test + public void addedAndRemovedElementsDelta() + { + PrimitiveLongDiffSets diffSet = createDiffSet(); + assertEquals( 0, diffSet.delta() ); + + diffSet.addAll( PrimitiveLongCollections.iterator( 7L, 8L ) ); + diffSet.addAll( PrimitiveLongCollections.iterator( 9L, 10L ) ); + assertEquals( 4, diffSet.delta() ); + + diffSet.removeAll( PrimitiveLongCollections.iterator( 8L, 9L ) ); + assertEquals( 2, diffSet.delta() ); + } + + @Test + public void augmentDiffSetWithExternalElements() + { + PrimitiveLongDiffSets diffSet = createDiffSet(); + diffSet.addAll( PrimitiveLongCollections.iterator( 9L, 10L, 11L ) ); + diffSet.removeAll( PrimitiveLongCollections.iterator( 1L, 2L ) ); + + PrimitiveLongIterator augmentedIterator = diffSet.augment( iterator( 5L, 6L ) ); + assertEquals( asSet( 5L, 6L, 9L, 10L, 11L ), toSet( augmentedIterator ) ); + } + + @Test + public void visitAddedAndRemovedElements() throws ConstraintValidationException, CreateConstraintFailureException + { + PrimitiveLongDiffSets diffSet = createDiffSet(); + diffSet.addAll( PrimitiveLongCollections.iterator( 9L, 10L, 11L ) ); + diffSet.removeAll( PrimitiveLongCollections.iterator( 1L, 2L ) ); + + AggregatedPrimitiveLongDiffSetsVisitor visitor = new AggregatedPrimitiveLongDiffSetsVisitor(); + diffSet.visit( visitor ); + + assertEquals( asSet( 9L, 10L, 11L ), toSet( visitor.getAddedElements() ) ); + assertEquals( asSet( 1L, 2L ), toSet( visitor.getRemovedElements() ) ); + } + + private static PrimitiveLongDiffSets createDiffSet() + { + return new PrimitiveLongDiffSets(); + } + + private static class AggregatedPrimitiveLongDiffSetsVisitor implements PrimitiveLongDiffSetsVisitor + { + private final PrimitiveLongSet addedElements = Primitive.longSet(); + private final PrimitiveLongSet removedElements = Primitive.longSet(); + + @Override + public void visitAdded( long element ) + { + addedElements.add( element ); + } + + @Override + public void visitRemoved( long element ) + { + removedElements.add( element ); + } + + PrimitiveLongSet getAddedElements() + { + return addedElements; + } + + PrimitiveLongSet getRemovedElements() + { + return removedElements; + } + } +} diff --git a/community/primitive-collections/src/main/java/org/neo4j/collection/primitive/PrimitiveLongCollections.java b/community/primitive-collections/src/main/java/org/neo4j/collection/primitive/PrimitiveLongCollections.java index 933a799ba81c9..8547c0b44ec39 100644 --- a/community/primitive-collections/src/main/java/org/neo4j/collection/primitive/PrimitiveLongCollections.java +++ b/community/primitive-collections/src/main/java/org/neo4j/collection/primitive/PrimitiveLongCollections.java @@ -60,65 +60,6 @@ private PrimitiveLongCollections() { } - /** - * Base iterator for simpler implementations of {@link PrimitiveLongIterator}s. - */ - public abstract static class PrimitiveLongBaseIterator implements PrimitiveLongIterator - { - private boolean hasNextDecided; - private boolean hasNext; - protected long next; - - @Override - public boolean hasNext() - { - if ( !hasNextDecided ) - { - hasNext = fetchNext(); - hasNextDecided = true; - } - return hasNext; - } - - @Override - public long next() - { - if ( !hasNext() ) - { - throw new NoSuchElementException( "No more elements in " + this ); - } - hasNextDecided = false; - return next; - } - - /** - * Fetches the next item in this iterator. Returns whether or not a next item was found. If a next - * item was found, that value must have been set inside the implementation of this method - * using {@link #next(long)}. - */ - protected abstract boolean fetchNext(); - - /** - * Called from inside an implementation of {@link #fetchNext()} if a next item was found. - * This method returns {@code true} so that it can be used in short-hand conditionals - * (TODO what are they called?), like: - *
-         * @Override
-         * protected boolean fetchNext()
-         * {
-         *     return source.hasNext() ? next( source.next() ) : false;
-         * }
-         * 
- * @param nextItem the next item found. - */ - protected boolean next( long nextItem ) - { - next = nextItem; - hasNext = true; - return true; - } - } - public static PrimitiveLongIterator iterator( final long... items ) { return new PrimitiveLongBaseIterator() @@ -211,70 +152,6 @@ else if ( !singleItemReturned ) }; } - public static class PrimitiveLongConcatingIterator extends PrimitiveLongBaseIterator - { - private final Iterator iterators; - private PrimitiveLongIterator currentIterator; - - public PrimitiveLongConcatingIterator( Iterator iterators ) - { - this.iterators = iterators; - } - - @Override - protected boolean fetchNext() - { - if ( currentIterator == null || !currentIterator.hasNext() ) - { - while ( iterators.hasNext() ) - { - currentIterator = iterators.next(); - if ( currentIterator.hasNext() ) - { - break; - } - } - } - return (currentIterator != null && currentIterator.hasNext()) && next( currentIterator.next() ); - } - - protected final PrimitiveLongIterator currentIterator() - { - return currentIterator; - } - } - - // Interleave - public static class PrimitiveLongInterleavingIterator extends PrimitiveLongBaseIterator - { - private final Iterable iterators; - private Iterator currentRound; - - public PrimitiveLongInterleavingIterator( Iterable iterators ) - { - this.iterators = iterators; - } - - @Override - protected boolean fetchNext() - { - if ( currentRound == null || !currentRound.hasNext() ) - { - currentRound = iterators.iterator(); - } - while ( currentRound.hasNext() ) - { - PrimitiveLongIterator iterator = currentRound.next(); - if ( iterator.hasNext() ) - { - return next( iterator.next() ); - } - } - currentRound = null; - return false; - } - } - public static PrimitiveLongIterator filter( PrimitiveLongIterator source, final LongPredicate filter ) { return new PrimitiveLongFilteringIterator( source ) @@ -344,52 +221,6 @@ public boolean test( long item ) }; } - public abstract static class PrimitiveLongFilteringIterator extends PrimitiveLongBaseIterator - implements LongPredicate - { - protected final PrimitiveLongIterator source; - - public PrimitiveLongFilteringIterator( PrimitiveLongIterator source ) - { - this.source = source; - } - - @Override - protected boolean fetchNext() - { - while ( source.hasNext() ) - { - long testItem = source.next(); - if ( test( testItem ) ) - { - return next( testItem ); - } - } - return false; - } - - @Override - public abstract boolean test( long testItem ); - } - - public abstract static class PrimitiveLongResourceFilteringIterator extends PrimitiveLongFilteringIterator - implements PrimitiveLongResourceIterator - { - public PrimitiveLongResourceFilteringIterator( PrimitiveLongIterator source ) - { - super( source ); - } - - @Override - public void close() - { - if ( source instanceof Resource ) - { - ((Resource) source).close(); - } - } - } - // Limitinglic public static PrimitiveLongIterator limit( final PrimitiveLongIterator source, final int maxItems ) { @@ -428,33 +259,6 @@ public static PrimitiveLongIterator range( long start, long end, long stride ) return new PrimitiveLongRangeIterator( start, end, stride ); } - public static class PrimitiveLongRangeIterator extends PrimitiveLongBaseIterator - { - private long current; - private final long end; - private final long stride; - - public PrimitiveLongRangeIterator( long start, long end, long stride ) - { - this.current = start; - this.end = end; - this.stride = stride; - } - - @Override - protected boolean fetchNext() - { - try - { - return current <= end && next( current ); - } - finally - { - current += stride; - } - } - } - public static PrimitiveLongIterator singleton( final long item ) { return new PrimitiveLongBaseIterator() @@ -649,21 +453,17 @@ public static boolean equals( PrimitiveLongIterator first, PrimitiveLongIterator return true; } - public static PrimitiveLongSet asSet( PrimitiveLongIterator iterator ) + public static PrimitiveLongSet asSet( Collection collection ) { - PrimitiveLongSet set = Primitive.longSet(); - while ( iterator.hasNext() ) + PrimitiveLongSet set = Primitive.longSet( collection.size() ); + for ( Long next : collection ) { - long next = iterator.next(); - if ( !set.add( next ) ) - { - throw new IllegalStateException( "Duplicate " + next + " from " + iterator ); - } + set.add( next ); } return set; } - public static PrimitiveLongSet asSetAllowDuplicates( PrimitiveLongIterator iterator ) + public static PrimitiveLongSet asSet( PrimitiveLongIterator iterator ) { PrimitiveLongSet set = Primitive.longSet(); while ( iterator.hasNext() ) @@ -817,23 +617,6 @@ public static PrimitiveLongObjectMap emptyObjectMap() return Empty.EMPTY_PRIMITIVE_LONG_OBJECT_MAP; } - /** - * Adds all the items in {@code iterator} to {@code collection}. - * @param the type of {@link Collection} to add to items to. - * @param iterator the {@link Iterator} to grab the items from. - * @param collection the {@link Collection} to add the items to. - * @return the {@code collection} which was passed in, now filled - * with the items from {@code iterator}. - */ - public static > C addToCollection( PrimitiveLongIterator iterator, C collection ) - { - while ( iterator.hasNext() ) - { - collection.add( iterator.next() ); - } - return collection; - } - /** * Pulls all items from the {@code iterator} and puts them into a {@link List}, boxing each long. * @@ -911,13 +694,22 @@ public boolean hasNext() }; } + /** + * Convert primitive set into a plain old java {@link Set}, boxing each long. + * + * @param set {@link PrimitiveLongSet} set of primitive values. + * @return a {@link Set} containing all items. + */ + public static Set toSet( PrimitiveLongSet set ) + { + return toSet( set.iterator() ); + } + /** * Pulls all items from the {@code iterator} and puts them into a {@link Set}, boxing each long. - * Any duplicate value will throw {@link IllegalStateException}. * * @param iterator {@link PrimitiveLongIterator} to pull values from. * @return a {@link Set} containing all items. - * @throws IllegalStateException for the first encountered duplicate. */ public static Set toSet( PrimitiveLongIterator iterator ) { @@ -965,4 +757,168 @@ public static long[] deduplicate( long[] values ) } return unique < values.length ? Arrays.copyOf( values, unique ) : values; } + + /** + * Base iterator for simpler implementations of {@link PrimitiveLongIterator}s. + */ + public abstract static class PrimitiveLongBaseIterator implements PrimitiveLongIterator + { + private boolean hasNextDecided; + private boolean hasNext; + protected long next; + + @Override + public boolean hasNext() + { + if ( !hasNextDecided ) + { + hasNext = fetchNext(); + hasNextDecided = true; + } + return hasNext; + } + + @Override + public long next() + { + if ( !hasNext() ) + { + throw new NoSuchElementException( "No more elements in " + this ); + } + hasNextDecided = false; + return next; + } + + /** + * Fetches the next item in this iterator. Returns whether or not a next item was found. If a next + * item was found, that value must have been set inside the implementation of this method + * using {@link #next(long)}. + */ + protected abstract boolean fetchNext(); + + /** + * Called from inside an implementation of {@link #fetchNext()} if a next item was found. + * This method returns {@code true} so that it can be used in short-hand conditionals + * (TODO what are they called?), like: + *
+         * protected boolean fetchNext()
+         * {
+         *     return source.hasNext() ? next( source.next() ) : false;
+         * }
+         * 
+ * @param nextItem the next item found. + */ + protected boolean next( long nextItem ) + { + next = nextItem; + hasNext = true; + return true; + } + } + + public static class PrimitiveLongConcatingIterator extends PrimitiveLongBaseIterator + { + private final Iterator iterators; + private PrimitiveLongIterator currentIterator; + + public PrimitiveLongConcatingIterator( Iterator iterators ) + { + this.iterators = iterators; + } + + @Override + protected boolean fetchNext() + { + if ( currentIterator == null || !currentIterator.hasNext() ) + { + while ( iterators.hasNext() ) + { + currentIterator = iterators.next(); + if ( currentIterator.hasNext() ) + { + break; + } + } + } + return (currentIterator != null && currentIterator.hasNext()) && next( currentIterator.next() ); + } + + protected final PrimitiveLongIterator currentIterator() + { + return currentIterator; + } + } + + public abstract static class PrimitiveLongFilteringIterator extends PrimitiveLongBaseIterator + implements LongPredicate + { + protected final PrimitiveLongIterator source; + + PrimitiveLongFilteringIterator( PrimitiveLongIterator source ) + { + this.source = source; + } + + @Override + protected boolean fetchNext() + { + while ( source.hasNext() ) + { + long testItem = source.next(); + if ( test( testItem ) ) + { + return next( testItem ); + } + } + return false; + } + + @Override + public abstract boolean test( long testItem ); + } + + public abstract static class PrimitiveLongResourceFilteringIterator extends PrimitiveLongFilteringIterator + implements PrimitiveLongResourceIterator + { + PrimitiveLongResourceFilteringIterator( PrimitiveLongIterator source ) + { + super( source ); + } + + @Override + public void close() + { + if ( source instanceof Resource ) + { + ((Resource) source).close(); + } + } + } + + public static class PrimitiveLongRangeIterator extends PrimitiveLongBaseIterator + { + private long current; + private final long end; + private final long stride; + + PrimitiveLongRangeIterator( long start, long end, long stride ) + { + this.current = start; + this.end = end; + this.stride = stride; + } + + @Override + protected boolean fetchNext() + { + try + { + return current <= end && next( current ); + } + finally + { + current += stride; + } + } + } } diff --git a/community/primitive-collections/src/test/java/org/neo4j/collection/primitive/PrimitiveLongCollectionsTest.java b/community/primitive-collections/src/test/java/org/neo4j/collection/primitive/PrimitiveLongCollectionsTest.java index 2cdc46a481fa8..85da8bb703d08 100644 --- a/community/primitive-collections/src/test/java/org/neo4j/collection/primitive/PrimitiveLongCollectionsTest.java +++ b/community/primitive-collections/src/test/java/org/neo4j/collection/primitive/PrimitiveLongCollectionsTest.java @@ -22,7 +22,9 @@ import org.junit.Test; import java.util.Arrays; +import java.util.List; import java.util.NoSuchElementException; +import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; @@ -30,9 +32,11 @@ import static java.util.Arrays.asList; import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.Matchers.containsInAnyOrder; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -481,29 +485,6 @@ public void iteratorAsSet() throws Exception assertTrue( set.contains( 2 ) ); assertTrue( set.contains( 3 ) ); assertFalse( set.contains( 4 ) ); - try - { - PrimitiveLongCollections.asSet( PrimitiveLongCollections.iterator( 1, 2, 1 ) ); - fail( "Should fail on duplicates" ); - } - catch ( IllegalStateException e ) - { // good - } - } - - @Test - public void iteratorAsSetAllowDuplicates() throws Exception - { - // GIVEN - PrimitiveLongIterator items = PrimitiveLongCollections.iterator( 1, 2, 1 ); - - // WHEN - PrimitiveLongSet set = PrimitiveLongCollections.asSetAllowDuplicates( items ); - - // THEN - assertTrue( set.contains( 1 ) ); - assertTrue( set.contains( 2 ) ); - assertFalse( set.contains( 3 ) ); } @Test @@ -571,6 +552,38 @@ protected boolean fetchNext() assertEquals( -1L, count.get() ); } + @Test + public void copyPrimitiveSet() + { + PrimitiveLongSet longSet = PrimitiveLongCollections.setOf( 1L, 3L, 5L ); + PrimitiveLongSet copySet = PrimitiveLongCollections.asSet( longSet ); + assertNotSame( copySet, longSet ); + + assertTrue( copySet.contains( 1L ) ); + assertTrue( copySet.contains( 3L ) ); + assertTrue( copySet.contains( 5L ) ); + assertEquals( 3, copySet.size() ); + } + + @Test + public void convertJavaCollectionToSetOfPrimitives() + { + List longs = asList( 1L, 4L, 7L ); + PrimitiveLongSet longSet = PrimitiveLongCollections.asSet( longs ); + assertTrue( longSet.contains( 1L ) ); + assertTrue( longSet.contains( 4L ) ); + assertTrue( longSet.contains( 7L ) ); + assertEquals( 3, longSet.size() ); + } + + @Test + public void convertPrimitiveSetToJavaSet() + { + PrimitiveLongSet longSet = PrimitiveLongCollections.setOf( 1L, 3L, 5L ); + Set longs = PrimitiveLongCollections.toSet( longSet ); + assertThat( longs, containsInAnyOrder(1L, 3L, 5L) ); + } + private void assertNoMoreItems( PrimitiveLongIterator iterator ) { assertFalse( iterator + " should have no more items", iterator.hasNext() );