@Override public boolean labelField( long labelField ) { hasLabelField = true; nodeRecord.setLabelField( labelField, Collections.emptyList() ); return true; }
public void ensureHeavy( NodeRecord node, long firstDynamicLabelRecord ) { if ( !node.isLight() ) { return; } // Load any dynamic labels and populate the node record node.setLabelField( node.getLabelField(), dynamicLabelStore.getRecords( firstDynamicLabelRecord, RecordLoad.NORMAL ) ); }
private NodeRecord nodeRecordWithInlinedLabels( long... labels ) { NodeRecord node = new NodeRecord( 0, false, 0, 0 ); if ( labels.length > 0 ) { node.setLabelField( inlinedLabelsLongRepresentation( labels ), Collections.emptyList() ); } return node; }
static boolean tryInlineInNodeRecord( NodeRecord node, long[] ids, Collection<DynamicRecord> changedDynamicRecords ) { // We reserve the high header bit for future extensions of the format of the in-lined label bits // i.e. the 0-valued high header bit can allow for 0-7 in-lined labels in the bit-packed format. if ( ids.length > 7 ) { return false; } byte bitsPerLabel = (byte) (ids.length > 0 ? (LABEL_BITS / ids.length) : LABEL_BITS); Bits bits = bits( 5 ); if ( !inlineValues( ids, bitsPerLabel, bits ) ) { return false; } node.setLabelField( combineLabelCountAndLabelStorage( (byte) ids.length, bits.getLongs()[0] ), changedDynamicRecords ); return true; }
@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 ); } } );
/** * Deletes a node by its id, returning its properties which are now removed. * * @param nodeId The id of the node to delete. */ public void nodeDelete( long nodeId ) { NodeRecord nodeRecord = recordChangeSet.getNodeRecords().getOrLoad( nodeId, null ).forChangingData(); if ( !nodeRecord.inUse() ) { throw new IllegalStateException( "Unable to delete Node[" + nodeId + "] since it has already been deleted." ); } nodeRecord.setInUse( false ); nodeRecord.setLabelField( Record.NO_LABELS_FIELD.intValue(), markNotInUse( nodeRecord.getDynamicLabelRecords() ) ); getAndDeletePropertyChain( nodeRecord ); }
@Test public void shouldApplyNodeCommandToTheStoreAndInvalidateTheCache() throws Exception { // given final BatchTransactionApplier applier = newApplier( false ); final NodeRecord before = new NodeRecord( 11 ); before.setLabelField( 42, asList( one, two ) ); final NodeRecord after = new NodeRecord( 12 ); after.setInUse( false ); after.setLabelField( 42, asList( one, two, three ) ); final Command.NodeCommand command = new Command.NodeCommand( before, after ); // when boolean result = apply( applier, command::handle, transactionToApply ); // then assertFalse( result ); verify( lockService, times( 1 ) ).acquireNodeLock( command.getKey(), LockService.LockType.WRITE_LOCK ); verify( nodeStore, times( 1 ) ).updateRecord( after ); }
private NodeRecord nodeRecordWithDynamicLabels( long nodeId, NodeStore nodeStore, long... labels ) { NodeRecord node = new NodeRecord( nodeId, false, 0, 0 ); Collection<DynamicRecord> initialRecords = allocateAndApply( nodeStore, node.getId(), labels ); node.setLabelField( dynamicLabelsLongRepresentation( initialRecords ), initialRecords ); return node; }
@Test public void shouldKeepRecordLightWhenSettingLabelFieldWithoutDynamicRecords() { // GIVEN NodeRecord record = new NodeRecord( 0, false, NO_NEXT_RELATIONSHIP.intValue(), NO_NEXT_PROPERTY.intValue() ); // WHEN record.setLabelField( 0, Collections.emptyList() ); // THEN assertTrue( record.isLight() ); }
@Override protected void transactionData( GraphStoreFixture.TransactionDataBuilder tx, GraphStoreFixture.IdGenerator next ) { NodeRecord node = new NodeRecord( 42, false, -1, -1 ); node.setInUse( true ); List<DynamicRecord> dynamicRecords; dynamicRecords = pair.first(); labels.addAll( pair.other() ); node.setLabelField( dynamicPointer( dynamicRecords ), dynamicRecords ); tx.create( node ); } } );
private static NodeRecord withDynamicLabels( RecordAccessStub recordAccess, NodeRecord nodeRecord, long... labelIds ) { List<DynamicRecord> preAllocatedRecords = new ArrayList<>(); for ( int i = 0; i < 10; i++ ) { preAllocatedRecords.add( inUse( new DynamicRecord( i ) ) ); } Collection<DynamicRecord> dynamicRecords = new ArrayList<>(); DynamicArrayStore.allocateFromNumbers( dynamicRecords, prependNodeId( nodeRecord.getId(), labelIds ), new ReusableRecordsAllocator( 4, preAllocatedRecords ) ); for ( DynamicRecord dynamicRecord : dynamicRecords ) { recordAccess.addNodeDynamicLabels( dynamicRecord ); } nodeRecord.setLabelField( dynamicPointer( dynamicRecords ), dynamicRecords ); return nodeRecord; }
@Test public void shouldListLabelRecordsInUse() { // Given NodeRecord node = new NodeRecord( 1, false, -1, -1 ); long inlinedLabels = 12L; DynamicRecord dynamic1 = dynamicRecord( 1L, true ); DynamicRecord dynamic2 = dynamicRecord( 2L, true ); DynamicRecord dynamic3 = dynamicRecord( 3L, true ); node.setLabelField( inlinedLabels, asList( dynamic1, dynamic2, dynamic3 ) ); dynamic3.setInUse( false ); // When Iterable<DynamicRecord> usedRecords = node.getUsedDynamicLabelRecords(); // Then assertThat( asList( usedRecords ), equalTo( asList( dynamic1, dynamic2 ) ) ); }
@Test public void shouldMarkRecordHeavyWhenSettingLabelFieldWithDynamicRecords() { // GIVEN NodeRecord record = new NodeRecord( 0, false, NO_NEXT_RELATIONSHIP.intValue(), NO_NEXT_PROPERTY.intValue() ); // WHEN DynamicRecord dynamicRecord = new DynamicRecord( 1 ); record.setLabelField( 0x8000000001L, asList( dynamicRecord ) ); // THEN assertFalse( record.isLight() ); }
@Override protected void transactionData( GraphStoreFixture.TransactionDataBuilder tx, GraphStoreFixture.IdGenerator next ) { long nodeId = ((long[]) getRightArray( readFullByteArrayFromHeavyRecords( chain, ARRAY ) ).asObject())[0]; NodeRecord before = inUse( new NodeRecord( nodeId, false, -1, -1 ) ); NodeRecord after = inUse( new NodeRecord( nodeId, false, -1, -1 ) ); DynamicRecord record1 = chain.get( 0 ).clone(); DynamicRecord record2 = chain.get( 1 ).clone(); DynamicRecord record3 = chain.get( 2 ).clone(); record3.setNextBlock( record2.getId() ); before.setLabelField( dynamicPointer( chain ), chain ); after.setLabelField( dynamicPointer( chain ), asList( record1, record2, record3 ) ); tx.update( before, after ); } } );
@Override public Collection<DynamicRecord> add( long labelId, NodeStore nodeStore, DynamicRecordAllocator allocator ) { nodeStore.ensureHeavy( node, firstDynamicLabelRecordId( node.getLabelField() ) ); long[] existingLabelIds = getDynamicLabelsArray( node.getUsedDynamicLabelRecords(), nodeStore.getDynamicLabelStore() ); long[] newLabelIds = LabelIdArray.concatAndSort( existingLabelIds, labelId ); Collection<DynamicRecord> existingRecords = node.getDynamicLabelRecords(); Collection<DynamicRecord> changedDynamicRecords = allocateRecordsForDynamicLabels( node.getId(), newLabelIds, new ReusableRecordsCompositeAllocator( existingRecords, allocator ) ); node.setLabelField( dynamicPointer( changedDynamicRecords ), changedDynamicRecords ); return changedDynamicRecords; }
@Override protected void transactionData( GraphStoreFixture.TransactionDataBuilder tx, GraphStoreFixture.IdGenerator next ) { NodeRecord node = new NodeRecord( nodeId, false, -1, -1 ); node.setInUse( true ); List<DynamicRecord> labelRecords = labels.first(); node.setLabelField( dynamicPointer( labelRecords ), labelRecords ); tx.create( node ); Integer labelId = labels.other().get( 0 ); DynamicRecord record = inUse( new DynamicRecord( labelId ) ); allocateFromNumbers( duplicatedLabel, new long[]{nodeId, labelId, labelId}, new ReusableRecordsAllocator( 60, record ) ); } } );
public static NodeCommand createNode( long id, long... dynamicLabelRecordIds ) { NodeRecord record = new NodeRecord( id ); record.setInUse( true ); record.setCreated(); if ( dynamicLabelRecordIds.length > 0 ) { Collection<DynamicRecord> dynamicRecords = dynamicRecords( dynamicLabelRecordIds ); record.setLabelField( DynamicNodeLabels.dynamicPointer( dynamicRecords ), dynamicRecords ); } return new NodeCommand( new NodeRecord( id ), record ); }
@Override protected void transactionData( GraphStoreFixture.TransactionDataBuilder tx, GraphStoreFixture.IdGenerator next ) { NodeRecord nodeRecord = new NodeRecord( next.node(), false, -1, -1 ); DynamicRecord record = inUse( new DynamicRecord( next.nodeLabel() ) ); Collection<DynamicRecord> newRecords = new ArrayList<>(); allocateFromNumbers( newRecords, prependNodeId( nodeRecord.getId(), new long[]{42L} ), new ReusableRecordsAllocator( 60, record ) ); nodeRecord.setLabelField( dynamicPointer( newRecords ), newRecords ); tx.create( nodeRecord ); } } );
@Override protected void transactionData( GraphStoreFixture.TransactionDataBuilder tx, GraphStoreFixture.IdGenerator next ) { tx.nodeLabel( 42, "Label" ); NodeRecord nodeRecord = new NodeRecord( next.node(), false, -1, -1 ); DynamicRecord record = inUse( new DynamicRecord( next.nodeLabel() ) ); Collection<DynamicRecord> newRecords = new ArrayList<>(); allocateFromNumbers( newRecords, prependNodeId( next.node(), new long[]{42L} ), new ReusableRecordsAllocator( 60, record ) ); nodeRecord.setLabelField( dynamicPointer( newRecords ), newRecords ); tx.create( nodeRecord ); } } );
@Override protected void transactionData( GraphStoreFixture.TransactionDataBuilder tx, GraphStoreFixture.IdGenerator next ) { NodeRecord nodeRecord = new NodeRecord( next.node(), false, -1, -1 ); DynamicRecord record1 = inUse( new DynamicRecord( next.nodeLabel() ) ); DynamicRecord record2 = inUse( new DynamicRecord( next.nodeLabel() ) ); DynamicRecord record3 = inUse( new DynamicRecord( next.nodeLabel() ) ); labels[0] = nodeRecord.getId(); // the first id should not be a label id, but the id of the node ReusableRecordsAllocator allocator = new ReusableRecordsAllocator( 60, record1, record2, record3 ); allocateFromNumbers( chain, labels, allocator ); nodeRecord.setLabelField( dynamicPointer( chain ), chain ); tx.create( nodeRecord ); } } );