public static NodeLabelUpdate labelChanges( long nodeId, long[] labelsBeforeChange, long[] labelsAfterChange ) { return labelChanges( nodeId, labelsBeforeChange, labelsAfterChange, -1 ); }
@Override protected NodeLabelUpdate fetchNextOrNull() { return ++i < nodeCount ? labelChanges( i, NO_LABELS, new long[]{labelId} ) : null; } } );
@Override protected void process( NodeRecord[] batch, BatchSender sender ) throws Throwable { for ( NodeRecord node : batch ) { if ( node.inUse() ) { writer.write( labelChanges( node.getId(), EMPTY_LONG_ARRAY, get( node, nodeStore ) ) ); } } sender.send( batch ); }
@Test public void rebuildCorruptedIndexIndexOnStartup() throws Exception { // GIVEN a start of the store with existing data in it List<NodeLabelUpdate> data = asList( labelChanges( 1, NO_LABELS, new long[]{1} ), labelChanges( 2, NO_LABELS, new long[]{1, 2} ) ); start( data, true, false ); // WHEN the index is corrupted and then started again scrambleIndexFilesAndRestart( data, true, false ); assertTrue( "Index corruption should be detected", monitor.corruptedIndex ); assertTrue( "Index should be rebuild", monitor.rebuildingCalled ); }
@Test public void shouldRebuildFromScratchIfIndexMissing() { // GIVEN a start of the store with existing data in it start( asList( labelChanges( 1, NO_LABELS, new long[]{1} ), labelChanges( 2, NO_LABELS, new long[]{1, 2} ) ) ); // THEN assertTrue( "Didn't rebuild the store on startup", monitor.noIndexCalled & monitor.rebuildingCalled & monitor.rebuiltCalled ); assertNodesForLabel( 1, 1, 2 ); assertNodesForLabel( 2, 2 ); }
@Test public void shouldWorkWithAFullRange() { // given long labelId = 0; List<NodeLabelUpdate> updates = new ArrayList<>(); Set<Long> nodes = new HashSet<>(); for ( int i = 0; i < 34; i++ ) { updates.add( NodeLabelUpdate.labelChanges( i, new long[]{}, new long[]{labelId} ) ); nodes.add( (long) i ); } start( updates ); // when LabelScanReader reader = store.newReader(); Set<Long> nodesWithLabel = PrimitiveLongCollections.toSet( reader.nodesWithLabel( (int) labelId ) ); // then assertEquals( nodes, nodesWithLabel ); }
@Test public void shouldUpdateAFullRange() throws Exception { // given long label0Id = 0; List<NodeLabelUpdate> label0Updates = new ArrayList<>(); Set<Long> nodes = new HashSet<>(); for ( int i = 0; i < 34; i++ ) { label0Updates.add( NodeLabelUpdate.labelChanges( i, new long[]{}, new long[]{label0Id} ) ); nodes.add( (long) i ); } start( label0Updates ); // when write( Collections.emptyIterator() ); // then LabelScanReader reader = store.newReader(); Set<Long> nodesWithLabel0 = PrimitiveLongCollections.toSet( reader.nodesWithLabel( (int) label0Id ) ); assertEquals( nodes, nodesWithLabel0 ); }
@Test public void shouldDeleteFromIndexWhenDeletedNode() throws Exception { // GIVEN int labelId = 1; long nodeId = 10; start(); write( iterator( labelChanges( nodeId, NO_LABELS, new long[]{labelId} ) ) ); // WHEN write( iterator( labelChanges( nodeId, new long[]{labelId}, NO_LABELS ) ) ); // THEN assertNodesForLabel( labelId ); }
private void prepareIndex() throws IOException { start(); try ( LabelScanWriter labelScanWriter = store.newWriter() ) { labelScanWriter.write( NodeLabelUpdate.labelChanges( 1, new long[]{}, new long[]{1} ) ); } store.shutdown(); }
@Test public void shouldUpdateIndexOnLabelChange() throws Exception { // GIVEN int labelId = 1; long nodeId = 10; start(); // WHEN write( iterator( labelChanges( nodeId, NO_LABELS, new long[]{labelId} ) ) ); // THEN assertNodesForLabel( labelId, nodeId ); }
@Test public void shouldUpdateIndexOnAddedLabels() throws Exception { // GIVEN int labelId1 = 1; int labelId2 = 2; long nodeId = 10; start(); write( iterator( labelChanges( nodeId, NO_LABELS, new long[]{labelId1} ) ) ); assertNodesForLabel( labelId2 ); // WHEN write( iterator( labelChanges( nodeId, NO_LABELS, new long[]{labelId1, labelId2} ) ) ); // THEN assertNodesForLabel( labelId1, nodeId ); assertNodesForLabel( labelId2, nodeId ); }
@Test public void shouldUpdateIndexOnRemovedLabels() throws Exception { // GIVEN int labelId1 = 1; int labelId2 = 2; long nodeId = 10; start(); write( iterator( labelChanges( nodeId, NO_LABELS, new long[]{labelId1, labelId2} ) ) ); assertNodesForLabel( labelId1, nodeId ); assertNodesForLabel( labelId2, nodeId ); // WHEN write( iterator( labelChanges( nodeId, new long[]{labelId1, labelId2}, new long[]{labelId2} ) ) ); // THEN assertNodesForLabel( labelId1 ); assertNodesForLabel( labelId2, nodeId ); }
@Test public void shouldSeeEntriesWhenOnlyLowestIsPresent() { // given long labelId = 0; List<NodeLabelUpdate> labelUpdates = new ArrayList<>(); labelUpdates.add( NodeLabelUpdate.labelChanges( 0L, new long[]{}, new long[]{labelId} ) ); start( labelUpdates ); // when MutableInt count = new MutableInt(); AllEntriesLabelScanReader nodeLabelRanges = store.allNodeLabelRanges(); nodeLabelRanges.forEach( nlr -> { for ( long nodeId : nlr.nodes() ) { count.add( nlr.labels( nodeId ).length ); } } ); assertThat( count.intValue(), is( 1 ) ); }
private static void checkLabelScanStoreAccessible( LabelScanStore labelScanStore ) throws IOException { int labelId = 1; try ( LabelScanWriter labelScanWriter = labelScanStore.newWriter() ) { labelScanWriter.write( NodeLabelUpdate.labelChanges( 1, new long[]{}, new long[]{labelId} ) ); } try ( LabelScanReader labelScanReader = labelScanStore.newReader() ) { assertEquals( 1, labelScanReader.nodesWithLabel( labelId ).next() ); } } }
private void initializeNativeLabelScanStoreWithContent( DatabaseLayout databaseLayout ) throws IOException { try ( Lifespan lifespan = new Lifespan() ) { NativeLabelScanStore nativeLabelScanStore = getNativeLabelScanStore( databaseLayout, false ); lifespan.add( nativeLabelScanStore ); try ( LabelScanWriter labelScanWriter = nativeLabelScanStore.newWriter() ) { labelScanWriter.write( NodeLabelUpdate.labelChanges( 1, new long[0], new long[]{1} ) ); } nativeLabelScanStore.force( IOLimiter.UNLIMITED ); } }
private NodeLabelUpdate randomUpdate( long[] expected ) { int nodeId = random.nextInt( expected.length ); long labels = expected[nodeId]; long[] before = getLabels( labels ); int changeCount = random.nextInt( 4 ) + 1; for ( int i = 0; i < changeCount; i++ ) { labels = flipRandom( labels, LABEL_COUNT, random.random() ); } expected[nodeId] = labels; return NodeLabelUpdate.labelChanges( nodeId, before, getLabels( labels ) ); }
private void convertAndAssert( long[] before, long[] after, long[] expectedRemoved, long[] expectedAdded ) { NodeLabelUpdate update = NodeLabelUpdate.labelChanges( 0, before, after ); PhysicalToLogicalLabelChanges.convertToAdditionsAndRemovals( update ); assertArrayEquals( terminate( update.getLabelsBefore() ), expectedRemoved ); assertArrayEquals( terminate( update.getLabelsAfter() ), expectedAdded ); }
@Test public void shouldScanSingleRange() { // GIVEN int labelId1 = 1; int labelId2 = 2; long nodeId1 = 10; long nodeId2 = 11; start( asList( labelChanges( nodeId1, NO_LABELS, new long[]{labelId1} ), labelChanges( nodeId2, NO_LABELS, new long[]{labelId1, labelId2} ) ) ); // WHEN BoundedIterable<NodeLabelRange> reader = store.allNodeLabelRanges(); NodeLabelRange range = single( reader.iterator() ); // THEN assertArrayEquals( new long[]{nodeId1, nodeId2}, reducedNodes( range ) ); assertArrayEquals( new long[]{labelId1}, sorted( range.labels( nodeId1 ) ) ); assertArrayEquals( new long[]{labelId1, labelId2}, sorted( range.labels( nodeId2 ) ) ); }
@Test public void shouldReportMismatchedInlinedLabels() throws Exception { // given fixture.apply( new GraphStoreFixture.Transaction() { @Override protected void transactionData( GraphStoreFixture.TransactionDataBuilder tx, GraphStoreFixture.IdGenerator next ) { NodeRecord node = new NodeRecord( 42, false, -1, -1 ); node.setInUse( true ); node.setLabelField( inlinedLabelsLongRepresentation( label1, label2 ), Collections.emptySet() ); tx.create( node ); } } ); write( fixture.directStoreAccess().labelScanStore(), asList( labelChanges( 42, new long[]{label1, label2}, new long[]{label1} ) ) ); // when ConsistencySummaryStatistics stats = check(); // then on( stats ).verify( RecordType.LABEL_SCAN_DOCUMENT, 1 ) .andThatsAllFolks(); }
@Test public void shouldReportLabelScanStoreInconsistencies() throws Exception { // given GraphStoreFixture.IdGenerator idGenerator = fixture.idGenerator(); long nodeId1 = idGenerator.node(); long labelId = idGenerator.label() - 1; LabelScanStore labelScanStore = fixture.directStoreAccess().labelScanStore(); Iterable<NodeLabelUpdate> nodeLabelUpdates = asIterable( labelChanges( nodeId1, new long[]{}, new long[]{labelId} ) ); write( labelScanStore, nodeLabelUpdates ); // when ConsistencySummaryStatistics stats = check(); // then on( stats ).verify( RecordType.LABEL_SCAN_DOCUMENT, 1 ) .andThatsAllFolks(); }