@Test void scanForHighIdOnlyOnceWhenProcessCache() { NeoStores neoStores = mock( NeoStores.class, Mockito.RETURNS_MOCKS ); NodeStore nodeStore = mock( NodeStore.class ); NodeRecord nodeRecord = mock( NodeRecord.class ); StoreProcessor storeProcessor = mock( StoreProcessor.class ); when( neoStores.getNodeStore() ).thenReturn( nodeStore ); when( nodeStore.getHighId() ).thenReturn( 10L ); when( nodeStore.getRecord( anyLong(), any( NodeRecord.class ), any( RecordLoad.class ) ) ).thenReturn( nodeRecord ); when( nodeStore.newRecord() ).thenReturn( nodeRecord ); StoreAccess storeAccess = new StoreAccess( neoStores ); storeAccess.initialize(); CacheTask.CheckNextRel cacheTask = new CacheTask.CheckNextRel( Stage.SEQUENTIAL_FORWARD, new DefaultCacheAccess( Counts.NONE, 1 ), storeAccess, storeProcessor ); cacheTask.processCache(); verify( nodeStore, times( 1 ) ).getHighId(); } }
@Test public void shouldBeAbleToForceStoreScan() throws Exception { when( labelScanStore.newReader() ).thenThrow( new RuntimeException( "Should not be used" ) ); when( nodeStore.getHighestPossibleIdInUse() ).thenReturn( 200L ); when( nodeStore.getHighId() ).thenReturn( 20L ); when( nodeStore.openPageCursorForReading( anyLong() ) ).thenReturn( mock( PageCursor.class ) ); mockLabelNodeCount( countStore, 2 ); mockLabelNodeCount( countStore, 6 ); DynamicIndexStoreView storeView = dynamicIndexStoreView(); StoreScan<Exception> storeScan = storeView .visitNodes( new int[]{2, 6}, propertyKeyIdFilter, propertyUpdateVisitor, labelUpdateVisitor, true ); storeScan.run(); Mockito.verify( nodeStore, times( 1 ) ) .getRecordByCursor( anyLong(), any( NodeRecord.class ), any( RecordLoad.class ), any( PageCursor.class ) ); Mockito.verify( nodeStore, times( 200 ) ) .nextRecordByCursor( any( NodeRecord.class ), any( RecordLoad.class ), any( PageCursor.class ) ); }
@Override public void createNode( long id, Map<String, Object> properties, Label... labels ) { IdValidator.assertValidId( IdType.NODE, id, maxNodeId ); if ( nodeStore.isInUse( id ) ) { throw new IllegalArgumentException( "id=" + id + " already in use" ); } long highId = nodeStore.getHighId(); if ( highId <= id ) { nodeStore.setHighestPossibleIdInUse( id ); } internalCreateNode( id, properties, labels ); }
private Collection<DynamicRecord> allocateAndApply( NodeStore nodeStore, long nodeId, long[] longs ) { Collection<DynamicRecord> records = DynamicNodeLabels.allocateRecordsForDynamicLabels( nodeId, longs, nodeStore.getDynamicLabelStore() ); nodeStore.updateDynamicLabelRecords( records ); return records; }
NodeStore store = new NodeStore( storeFile, idFile, config, new DefaultIdGeneratorFactory( fs ), pageCacheRule.getPageCache( fs ), NullLogProvider.getInstance(), labelStore, RecordFormatSelector.defaultFormat() ); store.initialise( true ); store.makeStoreOk(); for ( int i = 0; i < highestId; i++ ) assertThat( store.nextId(), is( (long) i ) ); record.setId( i ); store.updateRecord( record ); store.setHighestPossibleIdInUse( highestId ); store.updateRecord( record ); store.rebuildIdGenerator(); store.closeIdGenerator(); store.openIdGenerator(); // simulate a restart to allow id reuse nextIds.add( store.nextId() ); // 2 nextIds.add( store.nextId() ); // 3 nextIds.add( store.nextId() ); // 5 nextIds.add( store.nextId() ); // 7 nextIds.add( store.nextId() ); // 51 assertThat( nextIds, contains( 2L, 3L, 5L, 7L, 50L ) ); store.close();
@Test public void shouldCombineProperFiveByteLabelField() throws Exception { // GIVEN // -- a store EphemeralFileSystemAbstraction fs = efs.get(); nodeStore = newNodeStore( fs ); // -- a record with the msb carrying a negative value long nodeId = 0; long labels = 0x8000000001L; NodeRecord record = new NodeRecord( nodeId, false, NO_NEXT_RELATIONSHIP.intValue(), NO_NEXT_PROPERTY.intValue() ); record.setInUse( true ); record.setLabelField( labels, Collections.emptyList() ); nodeStore.updateRecord( record ); // WHEN // -- reading that record back NodeRecord readRecord = nodeStore.getRecord( nodeId, nodeStore.newRecord(), NORMAL ); // THEN // -- the label field must be the same assertEquals( labels, readRecord.getLabelField() ); }
@Override protected void process() NodeRecord nodeRecord = nodeStore.newRecord(); PropertyRecord propertyRecord = propertyStore.newRecord(); try ( PageCursor cursor = nodeStore.openPageCursorForReading( 0 ); PageCursor propertyCursor = propertyStore.openPageCursorForReading( 0 ) ) nodeStore.getRecordByCursor( duplicateNodeId, nodeRecord, NORMAL, cursor ); assert nodeRecord.inUse() : nodeRecord; nodeStore.ensureHeavy( nodeRecord ); nodeStore.updateRecord( nodeRecord ); nodesRemoved++;
private Ids createNode( DataImporter.Monitor monitor, NeoStores neoStores, int propertyCount, int labelCount ) { PropertyStore propertyStore = neoStores.getPropertyStore(); RecordAccess<PropertyRecord,PrimitiveRecord> propertyRecordAccess = new DirectRecordAccess<>( propertyStore, new Loaders( neoStores ).propertyLoader() ); NodeStore nodeStore = neoStores.getNodeStore(); NodeRecord nodeRecord = nodeStore.newRecord(); nodeRecord.setId( nodeStore.nextId() ); nodeRecord.setInUse( true ); NodeLabelsField.parseLabelsField( nodeRecord ).put( labelIds( labelCount ), nodeStore, nodeStore.getDynamicLabelStore() ); long nextProp = new PropertyCreator( propertyStore, new PropertyTraverser() ) .createPropertyChain( nodeRecord, properties( propertyStore, propertyCount ), propertyRecordAccess ); nodeRecord.setNextProp( nextProp ); nodeStore.updateRecord( nodeRecord ); PropertyRecord[] propertyRecords = extractPropertyRecords( propertyRecordAccess, nextProp ); propertyRecordAccess.close(); monitor.nodesImported( 1 ); monitor.propertiesImported( propertyCount ); return new Ids( nodeRecord, propertyRecords ); }
long startingId = nodeStore.nextId(); long nodeId = startingId; for ( int i = 0; i < iterations; i++ ) nodeStore.updateRecord( record ); nodeId = nodeStore.nextId(); nodeStore.getRecord( i, record, NORMAL ); assertTrue( "record[" + i + "] should be in use", record.inUse() ); assertThat( "record[" + i + "] should have nextRelId of " + i,
@Before public void setUp() { NodeRecord nodeRecord = getNodeRecord(); when( labelScanStore.allNodeLabelRanges()).thenReturn( nodeLabelRanges ); when( neoStores.getCounts() ).thenReturn( countStore ); when( neoStores.getNodeStore() ).thenReturn( nodeStore ); when( nodeStore.newRecord() ).thenReturn( nodeRecord ); doAnswer( invocation -> { NodeRecord record = invocation.getArgument( 1 ); record.initialize( true, 1L, false, 1L, 0L ); record.setId( invocation.getArgument( 0 ) ); return null; } ).when( nodeStore ).getRecordByCursor( anyLong(), any( NodeRecord.class ), any( RecordLoad.class ), any( PageCursor.class ) ); doAnswer( invocation -> { NodeRecord record = invocation.getArgument( 0 ); record.initialize( true, 1L, false, 1L, 0L ); record.setId( record.getId() + 1 ); return null; } ).when( nodeStore ).nextRecordByCursor( any( NodeRecord.class ), any( RecordLoad.class ), any( PageCursor.class ) ); }
@Override public long createNode( Map<String, Object> properties, Label... labels ) { return internalCreateNode( nodeStore.nextId(), properties, labels ); }
public NodeImporter( BatchingNeoStores stores, IdMapper idMapper, Monitor monitor ) { super( stores, monitor ); this.labelTokenRepository = stores.getLabelRepository(); this.idMapper = idMapper; this.nodeStore = stores.getNodeStore(); this.nodeRecord = nodeStore.newRecord(); this.nodeIds = new BatchingIdGetter( nodeStore ); this.idPropertyStore = stores.getTemporaryPropertyStore(); this.idPropertyRecord = idPropertyStore.newRecord(); nodeRecord.setInUse( true ); }
@Test public void shouldFreeSecondaryUnitIdOfShrunkRecord() throws Exception { // GIVEN EphemeralFileSystemAbstraction fs = efs.get(); nodeStore = newNodeStore( fs ); NodeRecord record = new NodeRecord( 5L ); record.setRequiresSecondaryUnit( true ); record.setSecondaryUnitId( 10L ); record.setInUse( true ); nodeStore.updateRecord( record ); nodeStore.setHighestPossibleIdInUse( 10L ); // WHEN record.setRequiresSecondaryUnit( false ); nodeStore.updateRecord( record ); // THEN IdGenerator idGenerator = idGeneratorFactory.get( IdType.NODE ); verify( idGenerator, never() ).freeId( 5L ); verify( idGenerator ).freeId( 10L ); }
@Test public void shouldTellNodeInUse() throws Exception { // Given EphemeralFileSystemAbstraction fs = efs.get(); NodeStore store = newNodeStore( fs ); long exists = store.nextId(); store.updateRecord( new NodeRecord( exists, false, 10, 20, true ) ); long deleted = store.nextId(); store.updateRecord( new NodeRecord( deleted, false, 10, 20, true ) ); store.updateRecord( new NodeRecord( deleted, false, 10, 20, false ) ); // When & then assertTrue( store.isInUse( exists ) ); assertFalse( store.isInUse( deleted ) ); assertFalse( store.isInUse( nodeStore.recordFormat.getMaxId() ) ); }
private RecordProxy<NodeRecord,Void> getNodeRecord( long id ) { if ( id < 0 || id >= nodeStore.getHighId() ) { throw new NotFoundException( "id=" + id ); } return recordAccess.getNodeRecords().getOrLoad( id, null ); }
@Override protected void process( RelationshipGroupRecord[] batch, BatchSender sender ) { for ( RelationshipGroupRecord group : batch ) { if ( !group.inUse() ) { continue; } long nodeId = group.getOwningNode(); if ( cache.getByte( nodeId, 0 ) == 0 ) { cache.setByte( nodeId, 0, (byte) 1 ); NodeRecord nodeRecord = nodeStore.newRecord(); nodeStore.getRecordByCursor( nodeId, nodeRecord, NORMAL, nodeCursor ); nodeRecord.setNextRel( group.getId() ); nodeRecord.setDense( true ); current[cursor++] = nodeRecord; if ( cursor == batchSize ) { sender.send( current ); newBatch(); } } } control.recycle( batch ); }
private long nodeHighMark() { return read.getHighestPossibleIdInUse(); }
private void setNodeLabels( NodeRecord nodeRecord, Label... labels ) { NodeLabels nodeLabels = parseLabelsField( nodeRecord ); nodeLabels.put( getOrCreateLabelIds( labels ), nodeStore, nodeStore.getDynamicLabelStore() ); labelsTouched = true; }
@Override public void endOfEntity() { // Make sure we have an ID if ( nodeRecord.getId() == NULL_REFERENCE.longValue() ) { nodeRecord.setId( nodeIds.next() ); } // Compose the labels if ( !hasLabelField ) { long[] labelIds = labelTokenRepository.getOrCreateIds( labels, labelsCursor ); InlineNodeLabels.putSorted( nodeRecord, labelIds, null, nodeStore.getDynamicLabelStore() ); } labelsCursor = 0; // Write data to stores nodeRecord.setNextProp( createAndWritePropertyChain() ); nodeRecord.setInUse( true ); nodeStore.updateRecord( nodeRecord ); nodeCount++; nodeRecord.clear(); nodeRecord.setId( NULL_REFERENCE.longValue() ); hasLabelField = false; super.endOfEntity(); }