public static NodeLabelUpdate labelChanges( long nodeId, long[] labelsBeforeChange, long[] labelsAfterChange ) { return labelChanges( nodeId, labelsBeforeChange, labelsAfterChange, -1 ); }
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 ); }
private void flushPendingChanges() throws IOException { Arrays.sort( pendingUpdates, 0, pendingUpdatesCursor, UPDATE_SORTER ); monitor.flushPendingUpdates(); long currentLabelId = lowestLabelId; value.clear(); key.clear(); while ( currentLabelId != Long.MAX_VALUE ) { long nextLabelId = Long.MAX_VALUE; for ( int i = 0; i < pendingUpdatesCursor; i++ ) { NodeLabelUpdate update = pendingUpdates[i]; long nodeId = update.getNodeId(); nextLabelId = extractChange( update.getLabelsAfter(), currentLabelId, nodeId, nextLabelId, true, update.getTxId() ); nextLabelId = extractChange( update.getLabelsBefore(), currentLabelId, nodeId, nextLabelId, false, update.getTxId() ); } currentLabelId = nextLabelId; } flushPendingRange(); pendingUpdatesCursor = 0; }
int beforeLength = update.getLabelsBefore().length; int afterLength = update.getLabelsAfter().length; long[] before = update.getLabelsBefore(); long[] after = update.getLabelsAfter(); for ( int bi = 0, ai = 0; bi < beforeLength || ai < afterLength; ) update.getLabelsBefore()[bc++] = beforeId; bi++; beforeId = bi < beforeLength ? before[bi] : -1; update.getLabelsAfter()[ac++] = afterId; ai++; afterId = ai < afterLength ? after[ai] : -1; terminateWithMinusOneIfNeeded( update.getLabelsBefore(), bc ); terminateWithMinusOneIfNeeded( update.getLabelsAfter(), ac );
@Override public void write( NodeLabelUpdate update ) { assertEquals( expectedNodeIds[cursor], update.getNodeId() ); cursor++; }
public static NodeLabelUpdate labelChanges( long nodeId, long[] labelsBeforeChange, long[] labelsAfterChange, long txId ) { return new NodeLabelUpdate( nodeId, labelsBeforeChange, labelsAfterChange, txId ); }
/** * Queues a {@link NodeLabelUpdate} to this writer for applying when batch gets full, * or when {@link #close() closing}. */ @Override public void write( NodeLabelUpdate update ) throws IOException { if ( pendingUpdatesCursor == pendingUpdates.length ) { flushPendingChanges(); } pendingUpdates[pendingUpdatesCursor++] = update; PhysicalToLogicalLabelChanges.convertToAdditionsAndRemovals( update ); checkNextLabelId( update.getLabelsBefore() ); checkNextLabelId( update.getLabelsAfter() ); }
public static NodeLabelUpdate labelChanges( long nodeId, long[] labelsBeforeChange, long[] labelsAfterChange, long txId ) { return new NodeLabelUpdate( nodeId, labelsBeforeChange, labelsAfterChange, txId ); }
@Override protected NodeLabelUpdate fetchNextOrNull() { return ++i < nodeCount ? labelChanges( i, NO_LABELS, new long[]{labelId} ) : null; } } );
private void flushPendingChanges() throws IOException { Arrays.sort( pendingUpdates, 0, pendingUpdatesCursor, UPDATE_SORTER ); monitor.flushPendingUpdates(); long currentLabelId = lowestLabelId; value.clear(); key.clear(); while ( currentLabelId != Long.MAX_VALUE ) { long nextLabelId = Long.MAX_VALUE; for ( int i = 0; i < pendingUpdatesCursor; i++ ) { NodeLabelUpdate update = pendingUpdates[i]; long nodeId = update.getNodeId(); nextLabelId = extractChange( update.getLabelsAfter(), currentLabelId, nodeId, nextLabelId, true, update.getTxId() ); nextLabelId = extractChange( update.getLabelsBefore(), currentLabelId, nodeId, nextLabelId, false, update.getTxId() ); } currentLabelId = nextLabelId; } flushPendingRange(); pendingUpdatesCursor = 0; }
int beforeLength = update.getLabelsBefore().length; int afterLength = update.getLabelsAfter().length; long[] before = update.getLabelsBefore(); long[] after = update.getLabelsAfter(); for ( int bi = 0, ai = 0; bi < beforeLength || ai < afterLength; ) update.getLabelsBefore()[bc++] = beforeId; bi++; beforeId = bi < beforeLength ? before[bi] : -1; update.getLabelsAfter()[ac++] = afterId; ai++; afterId = ai < afterLength ? after[ai] : -1; terminateWithMinusOneIfNeeded( update.getLabelsBefore(), bc ); terminateWithMinusOneIfNeeded( update.getLabelsAfter(), ac );
@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 ); }
/** * Queues a {@link NodeLabelUpdate} to this writer for applying when batch gets full, * or when {@link #close() closing}. */ @Override public void write( NodeLabelUpdate update ) throws IOException { if ( pendingUpdatesCursor == pendingUpdates.length ) { flushPendingChanges(); } pendingUpdates[pendingUpdatesCursor++] = update; PhysicalToLogicalLabelChanges.convertToAdditionsAndRemovals( update ); checkNextLabelId( update.getLabelsBefore() ); checkNextLabelId( update.getLabelsAfter() ); }
@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 ); }
labelChanges( 2, EMPTY_LONG_ARRAY, new long[] {labelId1, labelId2} ), labelChanges( 1, EMPTY_LONG_ARRAY, new long[] {labelId1} ), labelChanges( 4, EMPTY_LONG_ARRAY, new long[] {labelId1, labelId3} ), labelChanges( 5, EMPTY_LONG_ARRAY, new long[] {labelId1, labelId2, labelId3} ), labelChanges( 3, EMPTY_LONG_ARRAY, new long[] {labelId1} ), labelChanges( 7, EMPTY_LONG_ARRAY, new long[] { labelId2} ), labelChanges( 8, EMPTY_LONG_ARRAY, new long[] { labelId3} ), labelChanges( 6, EMPTY_LONG_ARRAY, new long[] { labelId2} ), labelChanges( 9, EMPTY_LONG_ARRAY, new long[] { labelId3} ) ) );
labelChanges( 5, EMPTY_LONG_ARRAY, new long[] {labelId1, labelId2, labelId3} ), labelChanges( 8, EMPTY_LONG_ARRAY, new long[] { labelId3} ), labelChanges( 3, EMPTY_LONG_ARRAY, new long[] {labelId1} ), labelChanges( 6, EMPTY_LONG_ARRAY, new long[] { labelId2} ), labelChanges( 1, EMPTY_LONG_ARRAY, new long[] {labelId1} ), labelChanges( 7, EMPTY_LONG_ARRAY, new long[] { labelId2} ), labelChanges( 4, EMPTY_LONG_ARRAY, new long[] {labelId1, labelId3} ), labelChanges( 2, EMPTY_LONG_ARRAY, new long[] {labelId1, labelId2} ), labelChanges( 9, EMPTY_LONG_ARRAY, new long[] { labelId3} ) ) );
@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 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 ); }
@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 ); }