use of org.neo4j.kernel.impl.store.record.RelationshipRecord in project neo4j by neo4j.
the class CheckerTestBase method relationship.
long relationship(long id, long startNode, long endNode, int type, long startPrev, long startNext, long endPrev, long endNext, boolean firstInStart, boolean firstInEnd) {
RelationshipRecord relationship = new RelationshipRecord(id).initialize(true, NULL, startNode, endNode, type, startPrev, startNext, endPrev, endNext, firstInStart, firstInEnd);
relationshipStore.updateRecord(relationship, CursorContext.NULL);
return id;
}
use of org.neo4j.kernel.impl.store.record.RelationshipRecord in project neo4j by neo4j.
the class NodeChecker method check.
private void check(long fromNodeId, long toNodeId, boolean last) throws Exception {
long usedNodes = 0;
try (var cursorContext = new CursorContext(context.pageCacheTracer.createPageCursorTracer(NODE_RANGE_CHECKER_TAG));
RecordReader<NodeRecord> nodeReader = new RecordReader<>(context.neoStores.getNodeStore(), true, cursorContext);
RecordReader<DynamicRecord> labelReader = new RecordReader<>(context.neoStores.getNodeStore().getDynamicLabelStore(), false, cursorContext);
BoundedIterable<EntityTokenRange> labelIndexReader = getLabelIndexReader(fromNodeId, toNodeId, last, cursorContext);
SafePropertyChainReader property = new SafePropertyChainReader(context, cursorContext);
SchemaComplianceChecker schemaComplianceChecker = new SchemaComplianceChecker(context, mandatoryProperties, smallIndexes, cursorContext, context.memoryTracker)) {
ProgressListener localProgress = nodeProgress.threadLocalReporter();
MutableIntObjectMap<Value> propertyValues = new IntObjectHashMap<>();
CacheAccess.Client client = context.cacheAccess.client();
long[] nextRelCacheFields = new long[] { -1, -1, 1, /*inUse*/
0, 0, 1, /*note that this needs to be checked*/
0, 0 };
Iterator<EntityTokenRange> nodeLabelRangeIterator = labelIndexReader.iterator();
EntityTokenIndexCheckState labelIndexState = new EntityTokenIndexCheckState(null, fromNodeId - 1);
for (long nodeId = fromNodeId; nodeId < toNodeId && !context.isCancelled(); nodeId++) {
localProgress.add(1);
NodeRecord nodeRecord = nodeReader.read(nodeId);
if (!nodeRecord.inUse()) {
continue;
}
// Cache nextRel
long nextRel = nodeRecord.getNextRel();
if (nextRel < NULL_REFERENCE.longValue()) {
reporter.forNode(nodeRecord).relationshipNotInUse(new RelationshipRecord(nextRel));
nextRel = NULL_REFERENCE.longValue();
}
nextRelCacheFields[CacheSlots.NodeLink.SLOT_RELATIONSHIP_ID] = nextRel;
nextRelCacheFields[CacheSlots.NodeLink.SLOT_IS_DENSE] = longOf(nodeRecord.isDense());
usedNodes++;
// Labels
long[] unverifiedLabels = RecordLoading.safeGetNodeLabels(context, nodeRecord.getId(), nodeRecord.getLabelField(), labelReader, cursorContext);
long[] labels = checkNodeLabels(nodeRecord, unverifiedLabels, cursorContext);
// Cache the label field, so that if it contains inlined labels then it's free.
// Otherwise cache the dynamic labels in another data structure and point into it.
long labelField = nodeRecord.getLabelField();
boolean hasInlinedLabels = !NodeLabelsField.fieldPointsToDynamicRecordOfLabels(nodeRecord.getLabelField());
if (labels == null) {
// There was some inconsistency in the label field or dynamic label chain. Let's continue but w/o labels for this node
hasInlinedLabels = true;
labelField = NO_LABELS_FIELD.longValue();
}
boolean hasSingleLabel = labels != null && labels.length == 1;
nextRelCacheFields[CacheSlots.NodeLink.SLOT_HAS_INLINED_LABELS] = longOf(hasInlinedLabels);
nextRelCacheFields[CacheSlots.NodeLink.SLOT_LABELS] = hasSingleLabel ? // this makes RelationshipChecker "parse" the cached node labels more efficiently for single-label nodes
labels[0] : // Otherwise put the encoded label field if inlined, otherwise a ref to the cached dynamic labels
hasInlinedLabels ? labelField : observedCounts.cacheDynamicNodeLabels(labels);
nextRelCacheFields[CacheSlots.NodeLink.SLOT_HAS_SINGLE_LABEL] = longOf(hasSingleLabel);
// Properties
lightClear(propertyValues);
boolean propertyChainIsOk = property.read(propertyValues, nodeRecord, reporter::forNode, cursorContext);
// Label index
if (labelIndexReader.maxCount() != 0) {
checkNodeVsLabelIndex(nodeRecord, nodeLabelRangeIterator, labelIndexState, nodeId, labels, fromNodeId, cursorContext);
}
client.putToCache(nodeId, nextRelCacheFields);
// Mandatory properties and (some) indexing
if (labels != null && propertyChainIsOk) {
schemaComplianceChecker.checkContainsMandatoryProperties(nodeRecord, labels, propertyValues, reporter::forNode);
// gets checked this way, larger indexes will be checked in IndexChecker
if (context.consistencyFlags.isCheckIndexes()) {
schemaComplianceChecker.checkCorrectlyIndexed(nodeRecord, labels, propertyValues, reporter::forNode);
}
}
// Large indexes are checked elsewhere, more efficiently than per-entity
}
if (!context.isCancelled() && labelIndexReader.maxCount() != 0) {
reportRemainingLabelIndexEntries(nodeLabelRangeIterator, labelIndexState, last ? Long.MAX_VALUE : toNodeId, cursorContext);
}
localProgress.done();
}
observedCounts.incrementNodeLabel(ANY_LABEL, usedNodes);
}
use of org.neo4j.kernel.impl.store.record.RelationshipRecord in project neo4j by neo4j.
the class RelationshipChainChecker method relationshipVsRelationshipChecker.
private ThrowingRunnable relationshipVsRelationshipChecker(LongRange nodeIdRange, ScanDirection direction, RelationshipStore store, ArrayBlockingQueue<BatchedRelationshipRecords> queue, AtomicBoolean end, int threadId) {
final RelationshipRecord relationship = store.newRecord();
final RelationshipRecord otherRelationship = store.newRecord();
final CacheAccess.Client client = cacheAccess.client();
final RelationshipLink sourceCachePointer = direction.sourceLink;
final RelationshipLink targetCachePointer = direction.targetLink;
final long prevOrNext = direction.cacheSlot;
return () -> {
try (var cursorContext = new CursorContext(context.pageCacheTracer.createPageCursorTracer(RELATIONSHIP_CONSISTENCY_CHECKER_TAG));
var otherRelationshipCursor = store.openPageCursorForReading(0, cursorContext)) {
while ((!end.get() || !queue.isEmpty()) && !context.isCancelled()) {
BatchedRelationshipRecords batch = queue.poll(100, TimeUnit.MILLISECONDS);
if (batch != null) {
while (batch.fillNext(relationship) && !context.isCancelled()) {
long firstNode = relationship.getFirstNode();
long secondNode = relationship.getSecondNode();
// Intentionally not checking nodes outside highId of node store because RelationshipChecker will spot this inconsistency
boolean processStartNode = Math.abs(firstNode % numberOfChainCheckers) == threadId && nodeIdRange.isWithinRangeExclusiveTo(firstNode);
boolean processEndNode = Math.abs(secondNode % numberOfChainCheckers) == threadId && nodeIdRange.isWithinRangeExclusiveTo(secondNode);
if (processStartNode) {
checkRelationshipLink(direction, SOURCE_PREV, relationship, client, otherRelationship, otherRelationshipCursor, store, cursorContext);
checkRelationshipLink(direction, SOURCE_NEXT, relationship, client, otherRelationship, otherRelationshipCursor, store, cursorContext);
}
if (processEndNode) {
checkRelationshipLink(direction, TARGET_PREV, relationship, client, otherRelationship, otherRelationshipCursor, store, cursorContext);
checkRelationshipLink(direction, TARGET_NEXT, relationship, client, otherRelationship, otherRelationshipCursor, store, cursorContext);
}
if (processStartNode) {
boolean wasInUse = client.getBooleanFromCache(firstNode, SLOT_IN_USE);
long link = sourceCachePointer.link(relationship);
if (link < NULL_REFERENCE.longValue()) {
sourceCachePointer.reportDoesNotReferenceBack(reporter, relationship, otherRelationship);
} else {
client.putToCache(firstNode, relationship.getId(), link, SOURCE, prevOrNext, 1, longOf(wasInUse), longOf(relationship.isFirstInFirstChain()));
}
}
if (processEndNode) {
boolean wasInUse = client.getBooleanFromCache(secondNode, SLOT_IN_USE);
long link = targetCachePointer.link(relationship);
if (link < NULL_REFERENCE.longValue()) {
targetCachePointer.reportDoesNotReferenceBack(reporter, relationship, otherRelationship);
} else {
client.putToCache(secondNode, relationship.getId(), link, TARGET, prevOrNext, 1, longOf(wasInUse), longOf(relationship.isFirstInSecondChain()));
}
}
}
}
}
}
};
}
use of org.neo4j.kernel.impl.store.record.RelationshipRecord in project neo4j by neo4j.
the class RelationshipDeleter method disconnect.
private void disconnect(RelationshipRecord rel, RelationshipConnection pointer, RecordAccess<RelationshipRecord, Void> relChanges) {
long otherRelId = pointer.otherSide().get(rel);
if (isNull(otherRelId)) {
return;
}
RelationshipRecord otherRel = relChanges.getOrLoad(otherRelId, null, cursorContext).forChangingLinkage();
boolean changed = false;
long newId = pointer.get(rel);
boolean newIsFirst = pointer.isFirstInChain(rel);
if (otherRel.getFirstNode() == pointer.compareNode(rel)) {
pointer.start().set(otherRel, newId, newIsFirst);
changed = true;
}
if (otherRel.getSecondNode() == pointer.compareNode(rel)) {
pointer.end().set(otherRel, newId, newIsFirst);
changed = true;
}
if (!changed) {
throw new InvalidRecordException(otherRel + " don't match " + rel);
}
}
use of org.neo4j.kernel.impl.store.record.RelationshipRecord in project neo4j by neo4j.
the class RelationshipDeleter method decrementTotalRelationshipCount.
private void decrementTotalRelationshipCount(long nodeId, RelationshipRecord rel, long firstRelId, RecordAccess<RelationshipRecord, Void> relRecords) {
if (isNull(firstRelId)) {
return;
}
boolean deletingFirstInChain = rel.isFirstInChain(nodeId);
RelationshipRecord firstRel = relRecords.getOrLoad(firstRelId, null, cursorContext).forChangingLinkage();
if (nodeId == firstRel.getFirstNode()) {
firstRel.setFirstPrevRel(deletingFirstInChain ? relCount(nodeId, rel) - 1 : firstRel.getFirstPrevRel() - 1);
assert firstRel.getFirstPrevRel() >= 0;
firstRel.setFirstInFirstChain(true);
}
if (nodeId == firstRel.getSecondNode()) {
firstRel.setSecondPrevRel(deletingFirstInChain ? relCount(nodeId, rel) - 1 : firstRel.getSecondPrevRel() - 1);
assert firstRel.getSecondPrevRel() >= 0;
firstRel.setFirstInSecondChain(true);
}
}
Aggregations