@Override public long valueFrom( RelationshipGroupRecord record ) { return record.getNext(); }
@Override public long getNextRecordReference( RelationshipGroupRecord record ) { return record.getNext(); } }
@Override public void checkConsistency( RelationshipGroupRecord record, CheckerEngine<RelationshipGroupRecord, RelationshipGroupConsistencyReport> engine, RecordAccess records ) { if ( record.getNext() != Record.NO_NEXT_RELATIONSHIP.intValue() ) { engine.comparativeCheck( records.relationshipGroup( record.getNext() ), this ); } }
long count = group.getNext(); boolean lastInChain = count == 0;
long nextMod = record.getNext() == Record.NO_NEXT_RELATIONSHIP.intValue() ? 0 : (record.getNext() & 0x700000000L) >> 31; long nextOutMod = record.getFirstOut() == Record.NO_NEXT_RELATIONSHIP.intValue() ? 0 : (record.getFirstOut() & 0x700000000L) >> 28; cursor.putInt( (int) record.getNext() ); cursor.putInt( (int) record.getFirstOut() ); cursor.putInt( (int) record.getFirstIn() );
private void deleteGroup( RecordProxy<NodeRecord, Void> nodeChange, RelationshipGroupRecord group, RecordAccess<RelationshipGroupRecord, Integer> relGroupRecords ) { long previous = group.getPrev(); long next = group.getNext(); if ( previous == Record.NO_NEXT_RELATIONSHIP.intValue() ) { // This is the first one, just point the node to the next group nodeChange.forChangingLinkage().setNextRel( next ); } else { // There are others before it, point the previous to the next group RelationshipGroupRecord previousRecord = relGroupRecords.getOrLoad( previous, null ).forChangingLinkage(); previousRecord.setNext( next ); } if ( next != Record.NO_NEXT_RELATIONSHIP.intValue() ) { // There are groups after this one, point that next group to the previous of the group to be deleted RelationshipGroupRecord nextRecord = relGroupRecords.getOrLoad( next, null ).forChangingLinkage(); nextRecord.setPrev( previous ); } group.setInUse( false ); }
public RelationshipGroupPosition getRelationshipGroup( NodeRecord node, int type, RecordAccess<RelationshipGroupRecord, Integer> relGroupRecords ) { long groupId = node.getNextRel(); long previousGroupId = Record.NO_NEXT_RELATIONSHIP.intValue(); RecordProxy<RelationshipGroupRecord, Integer> previous = null; RecordProxy<RelationshipGroupRecord, Integer> current; while ( groupId != Record.NO_NEXT_RELATIONSHIP.intValue() ) { current = relGroupRecords.getOrLoad( groupId, null ); RelationshipGroupRecord record = current.forReadingData(); record.setPrev( previousGroupId ); // not persistent so not a "change" if ( record.getType() == type ) { return new RelationshipGroupPosition( previous, current ); } else if ( record.getType() > type ) { // The groups are sorted in the chain, so if we come too far we can return // empty handed right away return new RelationshipGroupPosition( previous, null ); } previousGroupId = groupId; groupId = record.getNext(); previous = current; } return new RelationshipGroupPosition( previous, null ); }
private String diff( RelationshipGroupRecord expected, RelationshipGroupRecord actual ) { if ( actual.getId() == expected.getId() && actual.getType() == expected.getType() && actual.getNext() == expected.getNext() && actual.getFirstOut() == expected.getFirstOut() && actual.getFirstIn() == expected.getFirstIn() && actual.getFirstLoop() == expected.getFirstLoop() && actual.getOwningNode() == expected.getOwningNode() ) { return null; } return describeDiff( expected.toString(), actual.toString() ); }
@Override public RecordKey<RelationshipGroupRecord> relationshipGroup() { return ( written, read ) -> { assertEquals( written.getType(), read.getType() ); assertEquals( written.getFirstOut(), read.getFirstOut() ); assertEquals( written.getFirstIn(), read.getFirstIn() ); assertEquals( written.getFirstLoop(), read.getFirstLoop() ); assertEquals( written.getNext(), read.getNext() ); assertEquals( written.getOwningNode(), read.getOwningNode() ); }; }
private void assertRelationshipGroupsInOrder( NeoStores neoStores, long nodeId, int... types ) { NodeStore nodeStore = neoStores.getNodeStore(); NodeRecord node = nodeStore.getRecord( nodeId, nodeStore.newRecord(), NORMAL ); assertTrue( "Node should be dense, is " + node, node.isDense() ); long groupId = node.getNextRel(); int cursor = 0; List<RelationshipGroupRecord> seen = new ArrayList<>(); while ( groupId != Record.NO_NEXT_RELATIONSHIP.intValue() ) { RecordStore<RelationshipGroupRecord> relationshipGroupStore = neoStores.getRelationshipGroupStore(); RelationshipGroupRecord group = relationshipGroupStore.getRecord( groupId, relationshipGroupStore.newRecord(), NORMAL ); seen.add( group ); assertEquals( "Invalid type, seen groups so far " + seen, types[cursor++], group.getType() ); groupId = group.getNext(); } assertEquals( "Not enough relationship group records found in chain for " + node, types.length, cursor ); }
private void markRelGroupNotInUse( long nodeId, TestRelType... types ) { NodeRecord node = getNodeRecord( nodeId ); assertTrue( node.isDense() ); Set<TestRelType> typesToRemove = asSet( types ); long relGroupId = node.getNextRel(); while ( relGroupId != NO_NEXT_RELATIONSHIP.intValue() ) { RelationshipGroupRecord relGroup = getRelGroupRecord( relGroupId ); TestRelType type = relTypeForId( relGroup.getType() ); if ( typesToRemove.contains( type ) ) { relGroup.setInUse( false ); update( relGroup ); } relGroupId = relGroup.getNext(); } }
private static void assertValidRelGroupCommand( StorageCommand command ) { assertThat( command, instanceOf( RelationshipGroupCommand.class ) ); RelationshipGroupCommand relGroupCommand = (RelationshipGroupCommand) command; RelationshipGroupRecord record = relGroupCommand.getAfter(); assertEquals( ID, record.getId() ); if ( IN_USE_FLAG == Record.IN_USE.byteValue() ) { assertTrue( record.inUse() ); } else if ( IN_USE_FLAG == Record.NOT_IN_USE.byteValue() ) { assertFalse( record.inUse() ); } else { throw new IllegalStateException( "Illegal inUse flag: " + IN_USE_FLAG ); } assertEquals( TYPE_AS_INT, record.getType() ); assertEquals( NEXT, record.getNext() ); assertEquals( FIRST_OUT, record.getFirstOut() ); assertEquals( FIRST_IN, record.getFirstIn() ); assertEquals( FIRST_LOOP, record.getNext() ); assertEquals( OWNING_NODE, record.getOwningNode() ); }
private static RecordProxy<RelationshipGroupRecord, Integer> getRelationshipGroup( RecordChangeSet recordChangeSet, NodeRecord node, int type ) { long groupId = node.getNextRel(); long previousGroupId = Record.NO_NEXT_RELATIONSHIP.intValue(); while ( groupId != Record.NO_NEXT_RELATIONSHIP.intValue() ) { RecordProxy<RelationshipGroupRecord, Integer> change = recordChangeSet.getRelGroupRecords().getOrLoad( groupId, type ); RelationshipGroupRecord record = change.forReadingData(); record.setPrev( previousGroupId ); // not persistent so not a "change" if ( record.getType() == type ) { return change; } previousGroupId = groupId; groupId = record.getNext(); } return null; }
private void markRandomRelsInGroupNotInUse( long nodeId, TestRelType type ) { NodeRecord node = getNodeRecord( nodeId ); assertTrue( node.isDense() ); long relGroupId = node.getNextRel(); while ( relGroupId != NO_NEXT_RELATIONSHIP.intValue() ) { RelationshipGroupRecord relGroup = getRelGroupRecord( relGroupId ); if ( type == relTypeForId( relGroup.getType() ) ) { markRandomRelsInChainNotInUse( relGroup.getFirstOut() ); markRandomRelsInChainNotInUse( relGroup.getFirstIn() ); markRandomRelsInChainNotInUse( relGroup.getFirstLoop() ); return; } relGroupId = relGroup.getNext(); } throw new IllegalStateException( "No relationship group with type: " + type + " found" ); }
private void assertBatch( RelationshipGroupRecord[] batch, long lastOwningNodeLastBatch ) { for ( int i = 0; i < batch.length; i++ ) { RelationshipGroupRecord record = batch[i]; assertTrue( record.getId() > Record.NULL_REFERENCE.longValue() ); assertTrue( record.getOwningNode() > lastOwningNodeLastBatch ); assertEquals( 1, record.getFirstOut() ); // the mark our store mock sets when preparing if ( record.getNext() == Record.NULL_REFERENCE.longValue() ) { // This is the last in the chain, verify that this is either: assertTrue( // - the last one in the batch, or i == batch.length - 1 || // - the last one for this node batch[i + 1].getOwningNode() > record.getOwningNode() ); } } }
private void writeRelationshipGroupRecord( WritableChannel channel, RelationshipGroupRecord record ) throws IOException { byte flags = bitFlags( bitFlag( record.inUse(), Record.IN_USE.byteValue() ), 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 ); channel.putShort( (short) record.getType() ); channel.putLong( record.getNext() ); channel.putLong( record.getFirstOut() ); channel.putLong( record.getFirstIn() ); channel.putLong( record.getFirstLoop() ); channel.putLong( record.getOwningNode() ); if ( record.hasSecondaryUnitId() ) { channel.putLong( record.getSecondaryUnitId() ); } } }
@Test public void verifyGroupIsDeletedWhenNeeded() { // TODO test on a lower level instead newDb( 2 ); Transaction tx = db.beginTx(); Node node = db.createNode(); Relationship rel1 = node.createRelationshipTo( db.createNode(), MyRelTypes.TEST ); Relationship rel2 = node.createRelationshipTo( db.createNode(), MyRelTypes.TEST ); Relationship rel3 = node.createRelationshipTo( db.createNode(), MyRelTypes.TEST ); Relationship rel4 = node.createRelationshipTo( db.createNode(), MyRelTypes.TEST2 ); Relationship rel5 = node.createRelationshipTo( db.createNode(), MyRelTypes.TEST2 ); Relationship rel6 = node.createRelationshipTo( db.createNode(), MyRelTypes.TEST2 ); tx.success(); tx.close(); NeoStores neoStores = db.getDependencyResolver().resolveDependency( RecordStorageEngine.class ).testAccessNeoStores(); NodeStore nodeStore = neoStores.getNodeStore(); NodeRecord nodeRecord = getRecord( nodeStore, node.getId() ); long group = nodeRecord.getNextRel(); RecordStore<RelationshipGroupRecord> groupStore = neoStores.getRelationshipGroupStore(); RelationshipGroupRecord groupRecord = getRecord( groupStore, group ); assertNotEquals( groupRecord.getNext(), -1 ); RelationshipGroupRecord otherGroupRecord = groupStore.getRecord( groupRecord.getNext(), groupStore.newRecord(), NORMAL ); assertEquals( -1, otherGroupRecord.getNext() ); // TODO Delete all relationships of one type and see to that the correct group is deleted. }
record.setNext( closestPrevious.getNext() ); record.setPrev( closestPrevious.getId() ); closestPrevious.setNext( id );
assertNotEquals( groupRecord.getNext(), -1 ); assertRelationshipChain( neoStores.getRelationshipStore(), node, groupRecord.getFirstOut(), rel1.getId(), rel2.getId(), rel3.getId() ); RelationshipGroupRecord otherGroupRecord = RecordStore.getRecord( groupStore, groupRecord.getNext() ); assertEquals( -1, otherGroupRecord.getNext() ); assertRelationshipChain( neoStores.getRelationshipStore(), node, otherGroupRecord.getFirstOut(), rel4.getId(), rel5.getId(), rel6.getId() );
RecordStore<RelationshipGroupRecord> groupStore = neoStores.getRelationshipGroupStore(); RelationshipGroupRecord groupRecord = getRecord( groupStore, group ); assertEquals( -1, groupRecord.getNext() ); assertEquals( -1, groupRecord.getPrev() ); assertRelationshipChain( neoStores.getRelationshipStore(), node, groupRecord.getFirstOut(), rel1.getId(), rel4.getId() );