@Override public Map<String,Object> getNodeProperties( long nodeId ) { NodeRecord record = getNodeRecord( nodeId ).forReadingData(); if ( record.getNextProp() != Record.NO_NEXT_PROPERTY.intValue() ) { return getPropertyChain( record.getNextProp() ); } return Collections.emptyMap(); }
@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() + "]"; }
@Override public Value getNodePropertyValue( long nodeId, int propertyKeyId ) { NodeRecord nodeRecord = nodeStore.newRecord(); if ( nodeStore.getRecord( nodeId, nodeRecord, FORCE ).inUse() ) { SpecificValueVisitor visitor = new SpecificValueVisitor( propertyKeyId ); try { if ( visitPropertyRecordChain( nodeRecord.getNextProp(), visitor ) ) { return visitor.foundPropertyValue; } } catch ( CircularPropertyRecordChainException e ) { // If we discover a circular reference and still haven't found the property then we won't find it. // There are other places where this circular reference will be logged as an inconsistency, // so simply catch this exception here and let this method return NO_VALUE below. } } return Values.NO_VALUE; }
private <RECEIVER extends PropertyReceiver> void nodeLoadProperties( long nodeId, RECEIVER receiver ) { NodeRecord nodeRecord = nodeStore.getRecord( nodeId, nodeStore.newRecord(), NORMAL ); loadProperties( nodeRecord.getNextProp(), receiver ); }
@Override public void setNodeProperties( long node, Map<String, Object> properties ) { NodeRecord record = getNodeRecord( node ).forChangingData(); if ( record.getNextProp() != Record.NO_NEXT_PROPERTY.intValue() ) { propertyDeletor.deletePropertyChain( record, recordAccess.getPropertyRecords() ); } record.setNextProp( propertyCreator.createPropertyChain( record, propertiesIterator( properties ), recordAccess.getPropertyRecords() ) ); flushStrategy.flush(); }
@Override public void check( NodeRecord record, CheckerEngine<NodeRecord, ConsistencyReport.NodeConsistencyReport> engine, RecordAccess records ) { try { Collection<PropertyRecord> properties = propertyReader.getPropertyRecordChain( record.getNextProp() ); cacheAccess.client().putPropertiesToCache(properties); if ( indexes != null ) { matchIndexesToNode( record, engine, records, properties ); } checkProperty( record, engine, properties ); } catch ( PropertyReader.CircularPropertyRecordChainException e ) { engine.report().propertyChainContainsCircularReference( e.propertyRecordClosingTheCircle() ); } }
Collection<PropertyRecord> props ) if ( !Record.NO_NEXT_PROPERTY.is( record.getNextProp() ) )
@Override public Value getNodePropertyValue( long nodeId, int propertyKeyId ) throws EntityNotFoundException { NodeRecord node = nodeStore.getRecord( nodeId, nodeStore.newRecord(), FORCE ); if ( !node.inUse() ) { throw new EntityNotFoundException( EntityType.NODE, nodeId ); } long firstPropertyId = node.getNextProp(); if ( firstPropertyId == Record.NO_NEXT_PROPERTY.intValue() ) { return Values.NO_VALUE; } for ( PropertyRecord propertyRecord : propertyStore.getPropertyRecordChain( firstPropertyId ) ) { PropertyBlock propertyBlock = propertyRecord.getPropertyBlock( propertyKeyId ); if ( propertyBlock != null ) { return propertyBlock.newPropertyValue( propertyStore ); } } return Values.NO_VALUE; }
@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() ); }; }
private void assertChain( ExpectedRecord... expectedRecords ) { long nextProp = primitive.forReadingLinkage().getNextProp(); int expectedRecordCursor = 0; while ( !Record.NO_NEXT_PROPERTY.is( nextProp ) ) { PropertyRecord record = records.getIfLoaded( nextProp ).forReadingData(); assertRecord( record, expectedRecords[expectedRecordCursor++] ); nextProp = record.getNextProp(); } }
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() ); }
@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 EntityUpdates nodeAsUpdates( long nodeId ) { NodeRecord node = nodeStore.getRecord( nodeId, nodeStore.newRecord(), FORCE ); if ( !node.inUse() ) { return null; } long firstPropertyId = node.getNextProp(); if ( firstPropertyId == Record.NO_NEXT_PROPERTY.intValue() ) { return null; // no properties => no updates (it's not going to be in any index) } long[] labels = parseLabelsField( node ).get( nodeStore ); if ( labels.length == 0 ) { return null; // no labels => no updates (it's not going to be in any index) } EntityUpdates.Builder update = EntityUpdates.forEntity( nodeId ).withTokens( labels ); for ( PropertyRecord propertyRecord : propertyStore.getPropertyRecordChain( firstPropertyId ) ) { for ( PropertyBlock property : propertyRecord ) { Value value = property.getType().value( property, propertyStore ); update.added( property.getKeyIndexId(), value ); } } return update.build(); }
@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 ); } } );
@Test void shouldReportNodeStoreReferencingSameChainAsNode() { // 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.NodeConsistencyReport nodeReport = check( ConsistencyReport.NodeConsistencyReport.class, nodeChecker, node, records ); ConsistencyReport.NeoStoreConsistencyReport masterReport = check( ConsistencyReport.NeoStoreConsistencyReport.class, neoStoreCheck, master, records ); // then verifyZeroInteractions( nodeReport ); verify( masterReport ).multipleOwners( 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 ); }
@Test void shouldReportRelationshipWithSamePropertyChainAsNode() { // given OwnerCheck decorator = new OwnerCheck( true ); RecordCheck<NodeRecord, ConsistencyReport.NodeConsistencyReport> nodeChecker = decorator.decorateNodeChecker( dummyNodeCheck() ); RecordCheck<RelationshipRecord, ConsistencyReport.RelationshipConsistencyReport> relationshipChecker = decorator.decorateRelationshipChecker( dummyRelationshipChecker() ); RecordAccessStub records = new RecordAccessStub(); NodeRecord node = records.add( inUse( new NodeRecord( 1, false, NONE, 7 ) ) ); RelationshipRecord relationship = records.add( inUse( new RelationshipRecord( 1, 0, 1, 0 ) ) ); relationship.setNextProp( node.getNextProp() ); // when ConsistencyReport.NodeConsistencyReport nodeReport = check( ConsistencyReport.NodeConsistencyReport.class, nodeChecker, node, records ); ConsistencyReport.RelationshipConsistencyReport relationshipReport = check( ConsistencyReport.RelationshipConsistencyReport.class, relationshipChecker, relationship, records ); // then verifyZeroInteractions( nodeReport ); verify( relationshipReport ).multipleOwners( node ); }
@Test void shouldReportNodeWithSamePropertyChainAsRelationship() { // given OwnerCheck decorator = new OwnerCheck( true ); RecordCheck<NodeRecord, ConsistencyReport.NodeConsistencyReport> nodeChecker = decorator.decorateNodeChecker( dummyNodeCheck() ); RecordCheck<RelationshipRecord, ConsistencyReport.RelationshipConsistencyReport> relationshipChecker = decorator.decorateRelationshipChecker( dummyRelationshipChecker() ); RecordAccessStub records = new RecordAccessStub(); NodeRecord node = records.add( inUse( new NodeRecord( 1, false, NONE, 7 ) ) ); RelationshipRecord relationship = records.add( inUse( new RelationshipRecord( 1, 0, 1, 0 ) ) ); relationship.setNextProp( node.getNextProp() ); // when ConsistencyReport.RelationshipConsistencyReport relationshipReport = check( ConsistencyReport.RelationshipConsistencyReport.class, relationshipChecker, relationship, records ); ConsistencyReport.NodeConsistencyReport nodeReport = check( ConsistencyReport.NodeConsistencyReport.class, nodeChecker, node, records ); // then verifyZeroInteractions( relationshipReport ); verify( nodeReport ).multipleOwners( relationship ); }
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() ); } }
NodeRecord record = stores.getNodeStore().newRecord(); record = stores.getNodeStore().getRecord( nodeId, record, RecordLoad.NORMAL ); long propId = record.getNextProp(); record.setNextProp( AbstractBaseRecord.NO_ID ); stores.getNodeStore().updateRecord( record );