Search in sources :

Example 91 with RelationshipRecord

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;
}
Also used : RelationshipRecord(org.neo4j.kernel.impl.store.record.RelationshipRecord)

Example 92 with RelationshipRecord

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);
}
Also used : DynamicRecord(org.neo4j.kernel.impl.store.record.DynamicRecord) IntObjectHashMap(org.eclipse.collections.impl.map.mutable.primitive.IntObjectHashMap) CacheAccess(org.neo4j.consistency.checking.cache.CacheAccess) RelationshipRecord(org.neo4j.kernel.impl.store.record.RelationshipRecord) CursorContext(org.neo4j.io.pagecache.context.CursorContext) EntityTokenRange(org.neo4j.kernel.impl.index.schema.EntityTokenRange) NodeRecord(org.neo4j.kernel.impl.store.record.NodeRecord) ProgressListener(org.neo4j.internal.helpers.progress.ProgressListener) Value(org.neo4j.values.storable.Value)

Example 93 with RelationshipRecord

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()));
                            }
                        }
                    }
                }
            }
        }
    };
}
Also used : CacheAccess(org.neo4j.consistency.checking.cache.CacheAccess) RelationshipRecord(org.neo4j.kernel.impl.store.record.RelationshipRecord) CursorContext(org.neo4j.io.pagecache.context.CursorContext)

Example 94 with RelationshipRecord

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);
    }
}
Also used : RelationshipRecord(org.neo4j.kernel.impl.store.record.RelationshipRecord) InvalidRecordException(org.neo4j.kernel.impl.store.InvalidRecordException)

Example 95 with RelationshipRecord

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);
    }
}
Also used : RelationshipRecord(org.neo4j.kernel.impl.store.record.RelationshipRecord)

Aggregations

RelationshipRecord (org.neo4j.kernel.impl.store.record.RelationshipRecord)207 Test (org.junit.Test)73 NodeRecord (org.neo4j.kernel.impl.store.record.NodeRecord)69 ConsistencyReport (org.neo4j.consistency.report.ConsistencyReport)43 Test (org.junit.jupiter.api.Test)34 RelationshipTypeTokenRecord (org.neo4j.kernel.impl.store.record.RelationshipTypeTokenRecord)30 PropertyRecord (org.neo4j.kernel.impl.store.record.PropertyRecord)19 RelationshipGroupRecord (org.neo4j.kernel.impl.store.record.RelationshipGroupRecord)19 ParameterizedTest (org.junit.jupiter.params.ParameterizedTest)15 RelationshipStore (org.neo4j.kernel.impl.store.RelationshipStore)14 GraphStoreFixture (org.neo4j.consistency.checking.GraphStoreFixture)12 IdGenerator (org.neo4j.consistency.checking.GraphStoreFixture.IdGenerator)12 ConsistencySummaryStatistics (org.neo4j.consistency.report.ConsistencySummaryStatistics)12 TransactionDataBuilder (org.neo4j.consistency.checking.GraphStoreFixture.TransactionDataBuilder)11 InMemoryClosableChannel (org.neo4j.kernel.impl.transaction.log.InMemoryClosableChannel)11 RecordAccessStub (org.neo4j.consistency.store.RecordAccessStub)9 InputRelationship (org.neo4j.unsafe.impl.batchimport.input.InputRelationship)8 RepeatedTest (org.junit.jupiter.api.RepeatedTest)7 IOException (java.io.IOException)6 CursorContext (org.neo4j.io.pagecache.context.CursorContext)6