Search in sources :

Example 61 with CursorContext

use of org.neo4j.io.pagecache.context.CursorContext in project neo4j by neo4j.

the class RecordStorageEngineTestUtils method applyLogicalChanges.

public static void applyLogicalChanges(RecordStorageEngine storageEngine, ThrowingBiConsumer<ReadableTransactionState, TxStateVisitor, Exception> changes) throws Exception {
    ReadableTransactionState txState = mock(ReadableTransactionState.class);
    doAnswer(invocationOnMock -> {
        TxStateVisitor visitor = invocationOnMock.getArgument(0);
        changes.accept(txState, visitor);
        return null;
    }).when(txState).accept(any());
    List<StorageCommand> commands = new ArrayList<>();
    NeoStores neoStores = storageEngine.testAccessNeoStores();
    MetaDataStore metaDataStore = neoStores.getMetaDataStore();
    CursorContext cursorContext = CursorContext.NULL;
    try (RecordStorageCommandCreationContext commandCreationContext = storageEngine.newCommandCreationContext(EmptyMemoryTracker.INSTANCE)) {
        commandCreationContext.initialize(cursorContext);
        storageEngine.createCommands(commands, txState, storageEngine.newReader(), commandCreationContext, ResourceLocker.IGNORE, LockTracer.NONE, metaDataStore.getLastCommittedTransactionId(), t -> t, cursorContext, EmptyMemoryTracker.INSTANCE);
        storageEngine.apply(new GroupOfCommands(metaDataStore.nextCommittingTransactionId(), commands.toArray(new StorageCommand[0])), TransactionApplicationMode.EXTERNAL);
    }
}
Also used : TxStateVisitor(org.neo4j.storageengine.api.txstate.TxStateVisitor) MetaDataStore(org.neo4j.kernel.impl.store.MetaDataStore) StorageCommand(org.neo4j.storageengine.api.StorageCommand) NeoStores(org.neo4j.kernel.impl.store.NeoStores) ArrayList(java.util.ArrayList) ReadableTransactionState(org.neo4j.storageengine.api.txstate.ReadableTransactionState) CursorContext(org.neo4j.io.pagecache.context.CursorContext)

Example 62 with CursorContext

use of org.neo4j.io.pagecache.context.CursorContext in project neo4j by neo4j.

the class ManyPropertyKeysIT method databaseWithManyPropertyKeys.

private GraphDatabaseAPI databaseWithManyPropertyKeys(int propertyKeyCount) throws IOException {
    var cacheTracer = PageCacheTracer.NULL;
    var cursorContext = new CursorContext(cacheTracer.createPageCursorTracer("databaseWithManyPropertyKeys"));
    StoreFactory storeFactory = new StoreFactory(databaseLayout, Config.defaults(), new DefaultIdGeneratorFactory(fileSystem, immediate(), databaseLayout.getDatabaseName()), pageCache, fileSystem, NullLogProvider.getInstance(), cacheTracer, writable());
    NeoStores neoStores = storeFactory.openAllNeoStores(true);
    PropertyKeyTokenStore store = neoStores.getPropertyKeyTokenStore();
    for (int i = 0; i < propertyKeyCount; i++) {
        PropertyKeyTokenRecord record = new PropertyKeyTokenRecord((int) store.nextId(cursorContext));
        record.setInUse(true);
        Collection<DynamicRecord> nameRecords = store.allocateNameRecords(PropertyStore.encodeString(key(i)), cursorContext, INSTANCE);
        record.addNameRecords(nameRecords);
        record.setNameId((int) Iterables.first(nameRecords).getId());
        store.updateRecord(record, NULL);
    }
    neoStores.flush(cursorContext);
    neoStores.close();
    return database();
}
Also used : PropertyKeyTokenStore(org.neo4j.kernel.impl.store.PropertyKeyTokenStore) DynamicRecord(org.neo4j.kernel.impl.store.record.DynamicRecord) NeoStores(org.neo4j.kernel.impl.store.NeoStores) DefaultIdGeneratorFactory(org.neo4j.internal.id.DefaultIdGeneratorFactory) CursorContext(org.neo4j.io.pagecache.context.CursorContext) StoreFactory(org.neo4j.kernel.impl.store.StoreFactory) PropertyKeyTokenRecord(org.neo4j.kernel.impl.store.record.PropertyKeyTokenRecord)

Example 63 with CursorContext

use of org.neo4j.io.pagecache.context.CursorContext 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 64 with CursorContext

use of org.neo4j.io.pagecache.context.CursorContext in project neo4j by neo4j.

the class NodeChecker method checkIndexVsNodes.

private void checkIndexVsNodes(LongRange range, IndexDescriptor descriptor, boolean lastRange) throws Exception {
    CacheAccess.Client client = context.cacheAccess.client();
    IndexAccessor accessor = context.indexAccessors.accessorFor(descriptor);
    RelationshipCounter.NodeLabelsLookup nodeLabelsLookup = observedCounts.nodeLabelsLookup();
    SchemaDescriptor schema = descriptor.schema();
    PropertySchemaType propertySchemaType = schema.propertySchemaType();
    long[] indexEntityTokenIds = toLongArray(schema.getEntityTokenIds());
    indexEntityTokenIds = sortAndDeduplicate(indexEntityTokenIds);
    try (var cursorContext = new CursorContext(context.pageCacheTracer.createPageCursorTracer(NODE_INDEXES_CHECKER_TAG));
        var allEntriesReader = accessor.newAllEntriesValueReader(range.from(), lastRange ? Long.MAX_VALUE : range.to(), cursorContext)) {
        for (long entityId : allEntriesReader) {
            try {
                boolean entityExists = client.getBooleanFromCache(entityId, CacheSlots.NodeLink.SLOT_IN_USE);
                if (!entityExists) {
                    reporter.forIndexEntry(new IndexEntry(descriptor, context.tokenNameLookup, entityId)).nodeNotInUse(recordLoader.node(entityId, cursorContext));
                } else {
                    long[] entityTokenIds = nodeLabelsLookup.nodeLabels(entityId);
                    compareTwoSortedLongArrays(propertySchemaType, entityTokenIds, indexEntityTokenIds, indexLabel -> reporter.forIndexEntry(new IndexEntry(descriptor, context.tokenNameLookup, entityId)).nodeDoesNotHaveExpectedLabel(recordLoader.node(entityId, cursorContext), indexLabel), storeLabel -> {
                    /*here we're only interested in what the the index has that the store doesn't have*/
                    });
                }
            } catch (ArrayIndexOutOfBoundsException e) {
                // OK so apparently the index has a node way outside node highId
                reporter.forIndexEntry(new IndexEntry(descriptor, context.tokenNameLookup, entityId)).nodeNotInUse(recordLoader.node(entityId, cursorContext));
            }
        }
    }
}
Also used : SchemaDescriptor(org.neo4j.internal.schema.SchemaDescriptor) IndexAccessor(org.neo4j.kernel.api.index.IndexAccessor) CacheAccess(org.neo4j.consistency.checking.cache.CacheAccess) IndexEntry(org.neo4j.consistency.store.synthetic.IndexEntry) CursorContext(org.neo4j.io.pagecache.context.CursorContext) PropertySchemaType(org.neo4j.internal.schema.PropertySchemaType) RelationshipCounter(org.neo4j.internal.recordstorage.RelationshipCounter)

Example 65 with CursorContext

use of org.neo4j.io.pagecache.context.CursorContext 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)

Aggregations

CursorContext (org.neo4j.io.pagecache.context.CursorContext)161 Test (org.junit.jupiter.api.Test)74 DefaultPageCacheTracer (org.neo4j.io.pagecache.tracing.DefaultPageCacheTracer)52 PageCursor (org.neo4j.io.pagecache.PageCursor)40 IOException (java.io.IOException)31 UncheckedIOException (java.io.UncheckedIOException)27 PageCursorTracer (org.neo4j.io.pagecache.tracing.cursor.PageCursorTracer)27 Path (java.nio.file.Path)17 PagedFile (org.neo4j.io.pagecache.PagedFile)17 ArrayList (java.util.ArrayList)16 PageCacheTest (org.neo4j.io.pagecache.PageCacheTest)15 MutableLong (org.apache.commons.lang3.mutable.MutableLong)13 MemoryTracker (org.neo4j.memory.MemoryTracker)12 PageCache (org.neo4j.io.pagecache.PageCache)11 ProgressListener (org.neo4j.internal.helpers.progress.ProgressListener)10 DynamicRecord (org.neo4j.kernel.impl.store.record.DynamicRecord)10 List (java.util.List)9 RepeatedTest (org.junit.jupiter.api.RepeatedTest)9 NodeRecord (org.neo4j.kernel.impl.store.record.NodeRecord)9 PageCacheTracer (org.neo4j.io.pagecache.tracing.PageCacheTracer)8