private void writeNodeRecord( WritableChannel channel, NodeRecord record ) throws IOException { byte flags = bitFlags( bitFlag( record.inUse(), Record.IN_USE.byteValue() ), bitFlag( record.isCreated(), Record.CREATED_IN_TX ), bitFlag( record.requiresSecondaryUnit(), Record.REQUIRE_SECONDARY_UNIT ), bitFlag( record.hasSecondaryUnitId(), Record.HAS_SECONDARY_UNIT ), bitFlag( record.isUseFixedReferences(), Record.USES_FIXED_REFERENCE_FORMAT ) ); channel.put( flags ); if ( record.inUse() ) { channel.put( record.isDense() ? (byte) 1 : (byte) 0 ); channel.putLong( record.getNextRel() ).putLong( record.getNextProp() ); channel.putLong( record.getLabelField() ); if ( record.hasSecondaryUnitId() ) { channel.putLong( record.getSecondaryUnitId() ); } } // Always write dynamic label records because we want to know which ones have been deleted // especially if the node has been deleted. writeDynamicRecords( channel, record.getDynamicLabelRecords() ); } }
private NodeRecord getNodeRecord() { NodeRecord nodeRecord = new NodeRecord( 0L ); nodeRecord.initialize( true, 1L, false, 1L, 0L ); return nodeRecord; }
private String diff( NodeRecord expected, NodeRecord actual ) { if ( actual.getId() == expected.getId() && actual.getNextRel() == expected.getNextRel() && actual.getLabelField() == expected.getLabelField() && actual.getNextProp() == expected.getNextProp() && actual.isDense() == expected.isDense() && actual.isLight() == expected.isLight() ) { return null; } return describeDiff( expected.toString(), actual.toString() ); }
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 void connect( NodeRecord node, RelationshipRecord rel, RecordAccess<RelationshipRecord, Void> relRecords, ResourceLocker locks ) { connect( node.getId(), node.getNextRel(), rel, relRecords, locks ); }
@Override public boolean process( NodeRecord node ) { long nodeId = node.getId(); long firstRel = cache.getFirstRel( nodeId, NodeRelationshipCache.NO_GROUP_VISITOR ); if ( firstRel != -1 ) { node.setNextRel( firstRel ); } return true; }
@Test public void cloneShouldProduceExactCopy() { // Given long relId = 1337L; long propId = 1338L; long inlinedLabels = 12L; NodeRecord node = new NodeRecord( 1L, false, relId, propId ); node.setLabelField( inlinedLabels, asList( new DynamicRecord( 1L ), new DynamicRecord( 2L ) ) ); node.setInUse( true ); // When NodeRecord clone = node.clone(); // Then assertEquals( node.inUse(), clone.inUse() ); assertEquals( node.getLabelField(), clone.getLabelField() ); assertEquals( node.getNextProp(), clone.getNextProp() ); assertEquals( node.getNextRel(), clone.getNextRel() ); assertThat( clone.getDynamicLabelRecords(), equalTo( node.getDynamicLabelRecords() ) ); }
@Override public RecordKey<NodeRecord> node() { return ( written, read ) -> { assertEquals( written.getNextProp(), read.getNextProp() ); assertEquals( written.getNextRel(), read.getNextRel() ); assertEquals( written.getLabelField(), read.getLabelField() ); assertEquals( written.isDense(), read.isDense() ); }; }
@Override public NodeRecord clone() { NodeRecord clone = new NodeRecord( getId() ).initialize( inUse(), nextProp, dense, nextRel, labels ); clone.isLight = isLight; if ( dynamicLabelRecords.size() > 0 ) { List<DynamicRecord> clonedLabelRecords = new ArrayList<>( dynamicLabelRecords.size() ); for ( DynamicRecord labelRecord : dynamicLabelRecords ) { clonedLabelRecords.add( labelRecord.clone() ); } clone.dynamicLabelRecords = clonedLabelRecords; } clone.setSecondaryUnitId( getSecondaryUnitId() ); return clone; } }
@Override public void checkConsistency( RelationshipRecord relationship, CheckerEngine<RelationshipRecord, ConsistencyReport.RelationshipConsistencyReport> engine, RecordAccess records ) { if ( valueFrom( relationship ) < 0 ) { illegalNode( engine.report() ); } else { // build the node record from cached values with only valid fields as id, inUse, and nextRel. NodeRecord node = new NodeRecord( valueFrom( relationship ) ); CacheAccess.Client client = records.cacheAccess().client(); node.setInUse( client.getFromCache( node.getId(), SLOT_SOURCE_OR_TARGET ) != RelationshipLink.SOURCE ); node.setNextRel( client.getFromCache( node.getId(), SLOT_RELATIONSHIP_ID ) ); // We use "created" flag here. Consistency checking code revolves around records and so // even in scenarios where records are built from other sources, f.ex half-and-purpose-built from cache, // this flag is used to signal that the real record needs to be read in order to be used as a general // purpose record. node.setCreated(); if ( records.shouldCheck( node.getId(), MultiPassStore.NODES ) ) { engine.comparativeCheck( new DirectRecordReference<>( node, records ), this ); } } }
private NodeRecord newUsedNodeRecord( long id ) { NodeRecord node = new NodeRecord( id ); node.setInUse( true ); return node; } }
@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 ); } } );
@Test void shouldReportNodeWithReferenceToTheGraphGlobalChain() { // given OwnerCheck decorator = new OwnerCheck( true ); RecordCheck<NodeRecord, ConsistencyReport.NodeConsistencyReport> nodeChecker = decorator.decorateNodeChecker( dummyNodeCheck() ); RecordCheck<NeoStoreRecord, ConsistencyReport.NeoStoreConsistencyReport> neoStoreCheck = decorator.decorateNeoStoreChecker( dummyNeoStoreCheck() ); RecordAccessStub records = new RecordAccessStub(); NodeRecord node = records.add( inUse( new NodeRecord( 1, false, NONE, 7 ) ) ); NeoStoreRecord master = records.add( new NeoStoreRecord() ); master.setNextProp( node.getNextProp() ); // when ConsistencyReport.NeoStoreConsistencyReport masterReport = check( ConsistencyReport.NeoStoreConsistencyReport.class, neoStoreCheck, master, records ); ConsistencyReport.NodeConsistencyReport nodeReport = check( ConsistencyReport.NodeConsistencyReport.class, nodeChecker, node, records ); // then verifyZeroInteractions( masterReport ); verify( nodeReport ).multipleOwners( master ); }
@Override protected void transactionData( GraphStoreFixture.TransactionDataBuilder tx, GraphStoreFixture.IdGenerator next ) { // structurally correct, but does not have the 'mandatory' property with the 'draconian' label NodeRecord node = new NodeRecord( next.node(), false, -1, next.property() ); node.setInUse( true ); node.setLabelField( inlinedLabelsLongRepresentation( draconian ), Collections.emptySet() ); PropertyRecord property = new PropertyRecord( node.getNextProp(), node ); property.setInUse( true ); PropertyBlock block = new PropertyBlock(); block.setSingleBlock( key1 | (((long) PropertyType.INT.intValue()) << 24) | (1337L << 28) ); property.addPropertyBlock( block ); tx.create( node ); tx.create( property ); } } );
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 public String toString() { String denseInfo = (dense ? "group" : "rel") + "=" + nextRel; String lightHeavyInfo = isLight ? "light" : dynamicLabelRecords.isEmpty() ? "heavy" : "heavy,dynlabels=" + dynamicLabelRecords; return "Node[" + getId() + ",used=" + inUse() + "," + denseInfo + ",prop=" + getNextProp() + ",labels=" + parseLabelsField( this ) + "," + lightHeavyInfo + ",secondaryUnitId=" + getSecondaryUnitId() + "]"; }
public void create( NodeRecord node ) { node.setCreated(); update( new NodeRecord( node.getId(), false, NO_PREV_RELATIONSHIP.intValue(), NO_NEXT_PROPERTY.intValue() ), node ); }
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; }
HighIdTransactionApplier tracker = new HighIdTransactionApplier( neoStores ); NodeRecord node = new NodeRecord( 5 ).initialize( true, 123, true, 456, 0 ); node.setSecondaryUnitId( 6 ); node.setRequiresSecondaryUnit( true ); tracker.visitNodeCommand( new NodeCommand( new NodeRecord( node.getId() ), node ) ); tracker.visitRelationshipCommand( new RelationshipCommand( new RelationshipRecord( relationship.getId() ), relationship ) ); assertEquals( node.getSecondaryUnitId() + 1, neoStores.getNodeStore().getHighId() ); assertEquals( relationship.getSecondaryUnitId() + 1, neoStores.getRelationshipStore().getHighId() ); assertEquals( relationshipGroup.getSecondaryUnitId() + 1, neoStores.getRelationshipGroupStore().getHighId() );
@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; }