Search in sources :

Example 6 with RelationshipGroupStore

use of org.neo4j.kernel.impl.store.RelationshipGroupStore in project neo4j by neo4j.

the class DegreesRebuildFromStoreTest method skipNotUsedRecordsOnDegreeStoreRebuild.

@Test
void skipNotUsedRecordsOnDegreeStoreRebuild() throws Exception {
    // given a dataset containing mixed sparse and dense nodes with relationships in random directions,
    // where some chains have been marked as having external degrees
    int denseThreshold = dense_node_threshold.defaultValue();
    DatabaseLayout layout = DatabaseLayout.ofFlat(directory.homePath());
    int[] relationshipTypes;
    MutableLongLongMap expectedDegrees = LongLongMaps.mutable.empty();
    try (Lifespan life = new Lifespan()) {
        RecordStorageEngine storageEngine = openStorageEngine(layout, denseThreshold);
        relationshipTypes = createRelationshipTypes(storageEngine);
        life.add(storageEngine);
        generateData(storageEngine, denseThreshold, relationshipTypes);
        storageEngine.relationshipGroupDegreesStore().accept((groupId, direction, degree) -> expectedDegrees.put(combinedKeyOnGroupAndDirection(groupId, direction), degree), NULL);
        assertThat(expectedDegrees.isEmpty()).isFalse();
        RelationshipGroupStore groupStore = storageEngine.testAccessNeoStores().getRelationshipGroupStore();
        long highId = groupStore.getHighId();
        assertThat(highId).isGreaterThan(1);
        for (int i = 10; i < highId; i++) {
            RelationshipGroupRecord record = groupStore.getRecord(i, new RelationshipGroupRecord(i), RecordLoad.ALWAYS, NULL);
            record.setInUse(false);
            groupStore.updateRecord(record, NULL);
        }
        storageEngine.flushAndForce(NULL);
    }
    // when
    directory.getFileSystem().deleteFile(layout.relationshipGroupDegreesStore());
    try (Lifespan life = new Lifespan()) {
        RecordStorageEngine storageEngine = assertDoesNotThrow(() -> life.add(openStorageEngine(layout, denseThreshold)));
        // then
        storageEngine.relationshipGroupDegreesStore().accept((groupId, direction, degree) -> {
            long key = combinedKeyOnGroupAndDirection(groupId, direction);
            assertThat(expectedDegrees.containsKey(key)).isTrue();
            long expectedDegree = expectedDegrees.get(key);
            expectedDegrees.remove(key);
            assertThat(degree).isEqualTo(expectedDegree);
        }, NULL);
        assertThat(expectedDegrees.size()).isGreaterThan(0);
    }
}
Also used : RelationshipGroupRecord(org.neo4j.kernel.impl.store.record.RelationshipGroupRecord) RecordStorageEngine(org.neo4j.internal.recordstorage.RecordStorageEngine) DatabaseLayout(org.neo4j.io.layout.DatabaseLayout) RelationshipGroupStore(org.neo4j.kernel.impl.store.RelationshipGroupStore) MutableLongLongMap(org.eclipse.collections.api.map.primitive.MutableLongLongMap) Lifespan(org.neo4j.kernel.lifecycle.Lifespan) Test(org.junit.jupiter.api.Test)

Example 7 with RelationshipGroupStore

use of org.neo4j.kernel.impl.store.RelationshipGroupStore in project neo4j by neo4j.

the class RelationshipGroupChecker method checkToOwner.

/**
 * Check relationship group to owner node
 */
private void checkToOwner(LongRange nodeIdRange, PageCacheTracer pageCacheTracer) {
    ProgressListener localProgress = progress.threadLocalReporter();
    RelationshipGroupStore groupStore = neoStores.getRelationshipGroupStore();
    CacheAccess.Client client = context.cacheAccess.client();
    final long highId = groupStore.getHighId();
    try (var cursorContext = new CursorContext(pageCacheTracer.createPageCursorTracer(RELATIONSHIP_GROUPS_CHECKER_TAG));
        RecordReader<RelationshipGroupRecord> groupReader = new RecordReader<>(neoStores.getRelationshipGroupStore(), true, cursorContext)) {
        for (long id = 0; id < highId && !context.isCancelled(); id++) {
            localProgress.add(1);
            RelationshipGroupRecord record = groupReader.read(id);
            if (!record.inUse()) {
                continue;
            }
            long owningNode = record.getOwningNode();
            if (nodeIdRange.isWithinRangeExclusiveTo(owningNode)) {
                long cachedOwnerNextRel = client.getFromCache(owningNode, CacheSlots.NodeLink.SLOT_RELATIONSHIP_ID);
                boolean nodeIsInUse = client.getBooleanFromCache(owningNode, CacheSlots.NodeLink.SLOT_IN_USE);
                if (!nodeIsInUse) {
                    reporter.forRelationshipGroup(record).ownerNotInUse();
                } else if (cachedOwnerNextRel == id) {
                    // The old checker only verified that the relationship group that node.nextGroup pointed to had this node as its owner
                    client.putToCacheSingle(owningNode, CacheSlots.NodeLink.SLOT_CHECK_MARK, 0);
                }
                if (NULL_REFERENCE.is(record.getNext())) {
                    // This is the last group in the chain for this node. Verify that there's only one such last group.
                    boolean hasAlreadySeenLastGroup = client.getBooleanFromCache(owningNode, CacheSlots.NodeLink.SLOT_HAS_LAST_GROUP);
                    if (hasAlreadySeenLastGroup) {
                        reporter.forRelationshipGroup(record).multipleLastGroups(context.recordLoader.node(owningNode, cursorContext));
                    }
                    client.putToCacheSingle(owningNode, CacheSlots.NodeLink.SLOT_HAS_LAST_GROUP, 1);
                }
            }
        }
    }
    localProgress.done();
}
Also used : RelationshipGroupRecord(org.neo4j.kernel.impl.store.record.RelationshipGroupRecord) ProgressListener(org.neo4j.internal.helpers.progress.ProgressListener) CacheAccess(org.neo4j.consistency.checking.cache.CacheAccess) RelationshipGroupStore(org.neo4j.kernel.impl.store.RelationshipGroupStore) CursorContext(org.neo4j.io.pagecache.context.CursorContext)

Example 8 with RelationshipGroupStore

use of org.neo4j.kernel.impl.store.RelationshipGroupStore in project neo4j by neo4j.

the class WriteTransactionCommandOrderingTest method injectAllPossibleCommands.

private static TransactionRecordState injectAllPossibleCommands() {
    RecordChangeSet recordChangeSet = mock(RecordChangeSet.class);
    RecordChanges<LabelTokenRecord, Void> labelTokenChanges = mock(RecordChanges.class);
    RecordChanges<RelationshipTypeTokenRecord, Void> relationshipTypeTokenChanges = mock(RecordChanges.class);
    RecordChanges<PropertyKeyTokenRecord, Void> propertyKeyTokenChanges = mock(RecordChanges.class);
    RecordChanges<NodeRecord, Void> nodeRecordChanges = mock(RecordChanges.class);
    RecordChanges<RelationshipRecord, Void> relationshipRecordChanges = mock(RecordChanges.class);
    RecordChanges<PropertyRecord, PrimitiveRecord> propertyRecordChanges = mock(RecordChanges.class);
    RecordChanges<RelationshipGroupRecord, Integer> relationshipGroupChanges = mock(RecordChanges.class);
    RecordChanges<SchemaRecord, SchemaRule> schemaRuleChanges = mock(RecordChanges.class);
    when(recordChangeSet.getLabelTokenChanges()).thenReturn(labelTokenChanges);
    when(recordChangeSet.getRelationshipTypeTokenChanges()).thenReturn(relationshipTypeTokenChanges);
    when(recordChangeSet.getPropertyKeyTokenChanges()).thenReturn(propertyKeyTokenChanges);
    when(recordChangeSet.getNodeRecords()).thenReturn(nodeRecordChanges);
    when(recordChangeSet.getRelRecords()).thenReturn(relationshipRecordChanges);
    when(recordChangeSet.getPropertyRecords()).thenReturn(propertyRecordChanges);
    when(recordChangeSet.getRelGroupRecords()).thenReturn(relationshipGroupChanges);
    when(recordChangeSet.getSchemaRuleChanges()).thenReturn(schemaRuleChanges);
    List<RecordProxy<NodeRecord, Void>> nodeChanges = new LinkedList<>();
    RecordChange<NodeRecord, Void> deletedNode = mock(RecordChange.class);
    when(deletedNode.getBefore()).thenReturn(inUseNode());
    when(deletedNode.forReadingLinkage()).thenReturn(missingNode());
    nodeChanges.add(deletedNode);
    RecordChange<NodeRecord, Void> createdNode = mock(RecordChange.class);
    when(createdNode.getBefore()).thenReturn(missingNode());
    when(createdNode.forReadingLinkage()).thenReturn(createdNode());
    nodeChanges.add(createdNode);
    RecordChange<NodeRecord, Void> updatedNode = mock(RecordChange.class);
    when(updatedNode.getBefore()).thenReturn(inUseNode());
    when(updatedNode.forReadingLinkage()).thenReturn(inUseNode());
    nodeChanges.add(updatedNode);
    when(nodeRecordChanges.changes()).thenReturn(nodeChanges);
    when(nodeRecordChanges.changeSize()).thenReturn(3);
    when(recordChangeSet.changeSize()).thenReturn(3);
    when(labelTokenChanges.changes()).thenReturn(Collections.emptyList());
    when(relationshipTypeTokenChanges.changes()).thenReturn(Collections.emptyList());
    when(propertyKeyTokenChanges.changes()).thenReturn(Collections.emptyList());
    when(relationshipRecordChanges.changes()).thenReturn(Collections.emptyList());
    when(propertyRecordChanges.changes()).thenReturn(Collections.emptyList());
    when(relationshipGroupChanges.changes()).thenReturn(Collections.emptyList());
    when(schemaRuleChanges.changes()).thenReturn(Collections.emptyList());
    NeoStores neoStores = mock(NeoStores.class);
    NodeStore store = mock(NodeStore.class);
    when(neoStores.getNodeStore()).thenReturn(store);
    RelationshipGroupStore relationshipGroupStore = mock(RelationshipGroupStore.class);
    when(neoStores.getRelationshipGroupStore()).thenReturn(relationshipGroupStore);
    RelationshipStore relationshipStore = mock(RelationshipStore.class);
    when(neoStores.getRelationshipStore()).thenReturn(relationshipStore);
    return new TransactionRecordState(neoStores, mock(IntegrityValidator.class), recordChangeSet, 0, null, LockTracer.NONE, null, null, null, NULL, INSTANCE, LATEST_LOG_SERIALIZATION);
}
Also used : RelationshipTypeTokenRecord(org.neo4j.kernel.impl.store.record.RelationshipTypeTokenRecord) RelationshipRecord(org.neo4j.kernel.impl.store.record.RelationshipRecord) SchemaRule(org.neo4j.internal.schema.SchemaRule) PropertyKeyTokenRecord(org.neo4j.kernel.impl.store.record.PropertyKeyTokenRecord) NodeRecord(org.neo4j.kernel.impl.store.record.NodeRecord) PropertyRecord(org.neo4j.kernel.impl.store.record.PropertyRecord) NodeStore(org.neo4j.kernel.impl.store.NodeStore) SchemaRecord(org.neo4j.kernel.impl.store.record.SchemaRecord) LabelTokenRecord(org.neo4j.kernel.impl.store.record.LabelTokenRecord) PrimitiveRecord(org.neo4j.kernel.impl.store.record.PrimitiveRecord) RecordProxy(org.neo4j.internal.recordstorage.RecordAccess.RecordProxy) RelationshipGroupRecord(org.neo4j.kernel.impl.store.record.RelationshipGroupRecord) RelationshipGroupStore(org.neo4j.kernel.impl.store.RelationshipGroupStore) LinkedList(java.util.LinkedList) NeoStores(org.neo4j.kernel.impl.store.NeoStores) RelationshipStore(org.neo4j.kernel.impl.store.RelationshipStore)

Example 9 with RelationshipGroupStore

use of org.neo4j.kernel.impl.store.RelationshipGroupStore in project neo4j by neo4j.

the class DegreesRebuildFromStore method rebuild.

@Override
public void rebuild(RelationshipGroupDegreesStore.Updater updater, CursorContext cursorContext, MemoryTracker memoryTracker) {
    // === sketch of a more performant version
    // - Read all groups and for every group make a mark in a memory-structure like so:
    // (node) -> (type,active directions,out,in,loop)
    // - Read all relationships and for every matching node go into the memory-structure
    // if it's there then look up the type
    // if it's there then see if the direction matches any active direction
    // if it does then increment the counter in the correct slot
    // - Go though the memory-structure and write to the updater
    // 
    // If not all data can fit in memory then do multiple passes (node id range)
    RelationshipGroupStore groupStore = neoStores.getRelationshipGroupStore();
    try (RecordStorageReader storageReader = new RecordStorageReader(neoStores);
        StorageRelationshipTraversalCursor traversalCursor = storageReader.allocateRelationshipTraversalCursor(cursorContext);
        PageCursor groupCursor = groupStore.openPageCursorForReadingWithPrefetching(0, cursorContext)) {
        RelationshipGroupRecord groupRecord = groupStore.newRecord();
        long highGroupId = groupStore.getHighId();
        for (long id = groupStore.getNumberOfReservedLowIds(); id < highGroupId; id++) {
            groupStore.getRecordByCursor(id, groupRecord, RecordLoad.LENIENT_CHECK, groupCursor);
            if (groupRecord.inUse() && (groupRecord.hasExternalDegreesOut() || groupRecord.hasExternalDegreesIn() || groupRecord.hasExternalDegreesLoop())) {
                updateDegree(groupRecord.hasExternalDegreesOut(), groupRecord.getFirstOut(), groupRecord, OUTGOING, traversalCursor, updater);
                updateDegree(groupRecord.hasExternalDegreesIn(), groupRecord.getFirstIn(), groupRecord, INCOMING, traversalCursor, updater);
                updateDegree(groupRecord.hasExternalDegreesLoop(), groupRecord.getFirstLoop(), groupRecord, LOOP, traversalCursor, updater);
            }
        }
    }
}
Also used : RelationshipGroupRecord(org.neo4j.kernel.impl.store.record.RelationshipGroupRecord) RecordStorageReader(org.neo4j.internal.recordstorage.RecordStorageReader) RelationshipGroupStore(org.neo4j.kernel.impl.store.RelationshipGroupStore) StorageRelationshipTraversalCursor(org.neo4j.storageengine.api.StorageRelationshipTraversalCursor) PageCursor(org.neo4j.io.pagecache.PageCursor)

Example 10 with RelationshipGroupStore

use of org.neo4j.kernel.impl.store.RelationshipGroupStore in project neo4j by neo4j.

the class RecordNodeCursorTest method shouldChooseFastTotalDegreeLookupWhenPossible.

@Test
void shouldChooseFastTotalDegreeLookupWhenPossible() {
    // given
    NodeStore nodeStore = mock(NodeStore.class);
    long relationshipId = 99;
    long nextRelationshipId = relationshipId + 1;
    long nodeId = 5;
    int degree = 123;
    when(nodeStore.getHighestPossibleIdInUse(NULL)).thenReturn(nodeId + 1);
    doAnswer(invocationOnMock -> {
        long id = invocationOnMock.getArgument(0);
        NodeRecord record = invocationOnMock.getArgument(1);
        record.setId(id);
        record.initialize(true, NULL_REFERENCE.longValue(), false, relationshipId, NO_LABELS_FIELD.longValue());
        return null;
    }).when(nodeStore).getRecordByCursor(eq(nodeId), any(), any(), any());
    RelationshipStore relationshipStore = mock(RelationshipStore.class);
    doAnswer(invocationOnMock -> {
        long id = invocationOnMock.getArgument(0);
        RelationshipRecord record = invocationOnMock.getArgument(1);
        record.setId(id);
        record.initialize(true, NULL_REFERENCE.longValue(), nodeId, nodeId + 10, 1, degree, nextRelationshipId, 33, 44, true, false);
        return null;
    }).when(relationshipStore).getRecordByCursor(eq(relationshipId), any(), any(), any());
    RelationshipGroupStore groupStore = mock(RelationshipGroupStore.class);
    RelationshipGroupDegreesStore groupDegreesStore = mock(RelationshipGroupDegreesStore.class);
    RecordNodeCursor nodeCursor = new RecordNodeCursor(nodeStore, relationshipStore, groupStore, groupDegreesStore, NULL);
    // when
    nodeCursor.single(nodeId);
    assertThat(nodeCursor.next()).isTrue();
    SingleDegree mutator = new SingleDegree();
    nodeCursor.degrees(RelationshipSelection.ALL_RELATIONSHIPS, mutator, true);
    // then
    assertThat(mutator.getTotal()).isEqualTo(degree);
    verifyNoInteractions(groupStore);
    verify(relationshipStore).getRecordByCursor(eq(relationshipId), any(), any(), any());
    verify(relationshipStore, never()).getRecordByCursor(eq(nextRelationshipId), any(), any(), any());
}
Also used : NodeRecord(org.neo4j.kernel.impl.store.record.NodeRecord) NodeStore(org.neo4j.kernel.impl.store.NodeStore) RelationshipGroupStore(org.neo4j.kernel.impl.store.RelationshipGroupStore) RelationshipGroupDegreesStore(org.neo4j.internal.counts.RelationshipGroupDegreesStore) RelationshipStore(org.neo4j.kernel.impl.store.RelationshipStore) RelationshipRecord(org.neo4j.kernel.impl.store.record.RelationshipRecord) SingleDegree(org.neo4j.storageengine.util.SingleDegree) Test(org.junit.jupiter.api.Test)

Aggregations

RelationshipGroupStore (org.neo4j.kernel.impl.store.RelationshipGroupStore)11 RelationshipGroupRecord (org.neo4j.kernel.impl.store.record.RelationshipGroupRecord)7 NodeStore (org.neo4j.kernel.impl.store.NodeStore)6 RelationshipStore (org.neo4j.kernel.impl.store.RelationshipStore)5 Test (org.junit.jupiter.api.Test)4 NodeRecord (org.neo4j.kernel.impl.store.record.NodeRecord)4 NeoStores (org.neo4j.kernel.impl.store.NeoStores)3 RelationshipRecord (org.neo4j.kernel.impl.store.record.RelationshipRecord)3 PageCursor (org.neo4j.io.pagecache.PageCursor)2 DynamicArrayStore (org.neo4j.kernel.impl.store.DynamicArrayStore)2 DynamicStringStore (org.neo4j.kernel.impl.store.DynamicStringStore)2 PropertyStore (org.neo4j.kernel.impl.store.PropertyStore)2 LinkedList (java.util.LinkedList)1 MutableLongLongMap (org.eclipse.collections.api.map.primitive.MutableLongLongMap)1 CacheAccess (org.neo4j.consistency.checking.cache.CacheAccess)1 RelationshipGroupDegreesStore (org.neo4j.internal.counts.RelationshipGroupDegreesStore)1 ProgressListener (org.neo4j.internal.helpers.progress.ProgressListener)1 RecordProxy (org.neo4j.internal.recordstorage.RecordAccess.RecordProxy)1 RecordStorageEngine (org.neo4j.internal.recordstorage.RecordStorageEngine)1 RecordStorageReader (org.neo4j.internal.recordstorage.RecordStorageReader)1