use of org.neo4j.storageengine.api.txstate.LongDiffSets in project neo4j by neo4j.
the class TxStateIndexChanges method indexUpdatesWithValuesScanAndFilter.
private static AddedWithValuesAndRemoved indexUpdatesWithValuesScanAndFilter(ReadableTransactionState txState, IndexDescriptor descriptor, PropertyIndexQuery filter, IndexOrder indexOrder) {
Map<ValueTuple, ? extends LongDiffSets> updates = getUpdates(txState, descriptor, indexOrder);
if (updates == null) {
return EMPTY_ADDED_AND_REMOVED_WITH_VALUES;
}
MutableList<EntityWithPropertyValues> added = Lists.mutable.empty();
MutableLongSet removed = LongSets.mutable.empty();
for (Map.Entry<ValueTuple, ? extends LongDiffSets> entry : updates.entrySet()) {
ValueTuple key = entry.getKey();
if (filter == null || filter.acceptsValue(key.valueAt(0))) {
Value[] values = key.getValues();
LongDiffSets diffSet = entry.getValue();
diffSet.getAdded().each(nodeId -> added.add(new EntityWithPropertyValues(nodeId, values)));
removed.addAll(diffSet.getRemoved());
}
}
return new AddedWithValuesAndRemoved(indexOrder == IndexOrder.DESCENDING ? added.asReversed() : added, removed);
}
use of org.neo4j.storageengine.api.txstate.LongDiffSets in project neo4j by neo4j.
the class TxStateIndexChanges method indexUpdatesWithValuesForRangeSeek.
static AddedWithValuesAndRemoved indexUpdatesWithValuesForRangeSeek(ReadableTransactionState txState, IndexDescriptor descriptor, Value[] equalityPrefix, PropertyIndexQuery.RangePredicate<?> predicate, IndexOrder indexOrder) {
NavigableMap<ValueTuple, ? extends LongDiffSets> sortedUpdates = txState.getSortedIndexUpdates(descriptor.schema());
if (sortedUpdates == null) {
return EMPTY_ADDED_AND_REMOVED_WITH_VALUES;
}
int size = descriptor.schema().getPropertyIds().length;
RangeFilterValues rangeFilter = predicate == null ? RangeFilterValues.fromExists(size, equalityPrefix) : RangeFilterValues.fromRange(size, equalityPrefix, predicate);
MutableList<EntityWithPropertyValues> added = Lists.mutable.empty();
MutableLongSet removed = LongSets.mutable.empty();
Map<ValueTuple, ? extends LongDiffSets> inRange = sortedUpdates.subMap(rangeFilter.lower, true, rangeFilter.upper, true);
for (Map.Entry<ValueTuple, ? extends LongDiffSets> entry : inRange.entrySet()) {
ValueTuple values = entry.getKey();
Value rangeKey = values.valueAt(equalityPrefix.length);
Value[] valuesArray = values.getValues();
LongDiffSets diffForSpecificValue = entry.getValue();
// Needs to manually filter for if lower or upper should be included
// since we only wants to compare the first value of the key and not all of them for composite indexes
boolean allowed = rangeFilter.allowedEntry(rangeKey, equalityPrefix.length);
// The TreeMap cannot perfectly order multi-dimensional types (spatial) and need additional filtering out false positives
if (allowed && (predicate == null || predicate.isRegularOrder() || predicate.acceptsValue(rangeKey))) {
diffForSpecificValue.getAdded().each(nodeId -> added.add(new EntityWithPropertyValues(nodeId, valuesArray)));
removed.addAll(diffForSpecificValue.getRemoved());
}
}
return new AddedWithValuesAndRemoved(indexOrder == IndexOrder.DESCENDING ? added.asReversed() : added, removed);
}
use of org.neo4j.storageengine.api.txstate.LongDiffSets in project neo4j by neo4j.
the class TxStateIndexChanges method indexUpdatesForRangeSeekByPrefix.
// PREFIX
static AddedAndRemoved indexUpdatesForRangeSeekByPrefix(ReadableTransactionState txState, IndexDescriptor descriptor, Value[] equalityPrefix, TextValue prefix, IndexOrder indexOrder) {
NavigableMap<ValueTuple, ? extends LongDiffSets> sortedUpdates = txState.getSortedIndexUpdates(descriptor.schema());
if (sortedUpdates == null) {
return EMPTY_ADDED_AND_REMOVED;
}
int size = descriptor.schema().getPropertyIds().length;
ValueTuple floor = getCompositeValueTuple(size, equalityPrefix, prefix, true);
ValueTuple maxString = getCompositeValueTuple(size, equalityPrefix, Values.MAX_STRING, false);
MutableLongList added = LongLists.mutable.empty();
MutableLongSet removed = LongSets.mutable.empty();
for (Map.Entry<ValueTuple, ? extends LongDiffSets> entry : sortedUpdates.subMap(floor, maxString).entrySet()) {
Value key = entry.getKey().valueAt(equalityPrefix.length);
// Needs to check type since the subMap might include non-TextValue for composite index
if (key.valueGroup() == ValueGroup.TEXT && ((TextValue) key).startsWith(prefix)) {
LongDiffSets diffSets = entry.getValue();
added.addAll(diffSets.getAdded());
removed.addAll(diffSets.getRemoved());
} else {
break;
}
}
return new AddedAndRemoved(indexOrder == IndexOrder.DESCENDING ? added.asReversed() : added, removed);
}
use of org.neo4j.storageengine.api.txstate.LongDiffSets in project neo4j by neo4j.
the class TxStateTest method shouldComputeSortedIndexUpdatesOnTxStateWithAddedNodes.
@Test
void shouldComputeSortedIndexUpdatesOnTxStateWithAddedNodes() {
// GIVEN
addNodesToIndex(indexOn_1_1).withDefaultStringProperties(42L);
addNodesToIndex(indexOn_1_1).withDefaultStringProperties(43L);
addNodesToIndex(indexOn_1_1).withDefaultStringProperties(41L);
// WHEN
NavigableMap<ValueTuple, ? extends LongDiffSets> diffSets = state.getSortedIndexUpdates(indexOn_1_1.schema());
TreeMap<ValueTuple, LongDiffSets> expected = sortedAddedNodesDiffSets(42, 41, 43);
// THEN
assertNotNull(diffSets);
assertEquals(expected.keySet(), diffSets.keySet());
for (final ValueTuple key : expected.keySet()) {
assertEqualDiffSets(expected.get(key), diffSets.get(key));
}
}
use of org.neo4j.storageengine.api.txstate.LongDiffSets in project neo4j by neo4j.
the class TxState method accept.
@Override
public void accept(final TxStateVisitor visitor) throws KernelException {
if (nodes != null) {
nodes.getAdded().each(visitor::visitCreatedNode);
}
if (relationships != null) {
try (HeapTrackingArrayList<NodeRelationshipIds> sortedNodeRelState = HeapTrackingArrayList.newArrayList(nodeStatesMap.size(), memoryTracker)) {
nodeStatesMap.forEachValue(nodeState -> {
if (nodeState.isDeleted() && nodeState.isAddedInThisTx()) {
return;
}
if (nodeState.hasAddedRelationships() || nodeState.hasRemovedRelationships()) {
sortedNodeRelState.add(StateNodeRelationshipIds.createStateNodeRelationshipIds(nodeState, this::relationshipVisit, memoryTracker));
}
});
sortedNodeRelState.sort(Comparator.comparingLong(NodeRelationshipIds::nodeId));
// Visit relationships, this will grab all the locks needed to do the updates
visitor.visitRelationshipModifications(new RelationshipModifications() {
@Override
public void forEachSplit(IdsVisitor visitor) {
sortedNodeRelState.forEach(visitor);
}
@Override
public RelationshipBatch creations() {
return idsAsBatch(relationships.getAdded(), TxState.this::relationshipVisit);
}
@Override
public RelationshipBatch deletions() {
return idsAsBatch(relationships.getRemoved());
}
});
}
}
if (nodes != null) {
nodes.getRemoved().each(visitor::visitDeletedNode);
}
for (NodeState node : modifiedNodes()) {
if (node.hasPropertyChanges()) {
visitor.visitNodePropertyChanges(node.getId(), node.addedProperties(), node.changedProperties(), node.removedProperties());
}
final LongDiffSets labelDiffSets = node.labelDiffSets();
if (!labelDiffSets.isEmpty()) {
visitor.visitNodeLabelChanges(node.getId(), labelDiffSets.getAdded(), labelDiffSets.getRemoved());
}
}
for (RelationshipState rel : modifiedRelationships()) {
visitor.visitRelPropertyChanges(rel.getId(), rel.addedProperties(), rel.changedProperties(), rel.removedProperties());
}
if (indexChanges != null) {
for (IndexDescriptor indexDescriptor : indexChanges.getAdded()) {
visitor.visitAddedIndex(indexDescriptor);
}
indexChanges.getRemoved().forEach(visitor::visitRemovedIndex);
}
if (constraintsChanges != null) {
for (ConstraintDescriptor added : constraintsChanges.getAdded()) {
visitor.visitAddedConstraint(added);
}
constraintsChanges.getRemoved().forEach(visitor::visitRemovedConstraint);
}
if (createdLabelTokens != null) {
createdLabelTokens.forEachKeyValue((id, token) -> visitor.visitCreatedLabelToken(id, token.name, token.internal));
}
if (createdPropertyKeyTokens != null) {
createdPropertyKeyTokens.forEachKeyValue((id, token) -> visitor.visitCreatedPropertyKeyToken(id, token.name, token.internal));
}
if (createdRelationshipTypeTokens != null) {
createdRelationshipTypeTokens.forEachKeyValue((id, token) -> visitor.visitCreatedRelationshipTypeToken(id, token.name, token.internal));
}
}
Aggregations