/**
* Copyright (c) 2002-2012 "Neo Technology,"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.neo4j.consistency.checking;
import org.neo4j.consistency.report.ConsistencyReport;
import org.neo4j.consistency.store.DiffRecordAccess;
import org.neo4j.consistency.store.RecordAccess;
import org.neo4j.kernel.impl.nioneo.store.Record;
import org.neo4j.kernel.impl.nioneo.store.RelationshipRecord;
import org.neo4j.kernel.impl.nioneo.store.RelationshipTypeRecord;
class RelationshipRecordCheck
extends PrimitiveRecordCheck<RelationshipRecord, ConsistencyReport.RelationshipConsistencyReport>
{
RelationshipRecordCheck()
{
super( Label.LABEL,
RelationshipNodeField.SOURCE, RelationshipField.SOURCE_PREV, RelationshipField.SOURCE_NEXT,
RelationshipNodeField.TARGET, RelationshipField.TARGET_PREV, RelationshipField.TARGET_NEXT );
}
private enum Label implements
RecordField<RelationshipRecord, ConsistencyReport.RelationshipConsistencyReport>,
ComparativeRecordChecker<RelationshipRecord, RelationshipTypeRecord, ConsistencyReport.RelationshipConsistencyReport>
{
LABEL;
@Override
public void checkConsistency( RelationshipRecord record, ConsistencyReport.RelationshipConsistencyReport report,
RecordAccess records )
{
if ( record.getType() < 0 )
{
report.illegalLabel();
}
else
{
report.forReference( records.relationshipLabel( record.getType() ), this );
}
}
@Override
public long valueFrom( RelationshipRecord record )
{
return record.getType();
}
@Override
public void checkChange( RelationshipRecord oldRecord, RelationshipRecord newRecord,
ConsistencyReport.RelationshipConsistencyReport report, DiffRecordAccess records )
{
// nothing to check
}
@Override
public void checkReference( RelationshipRecord record, RelationshipTypeRecord referred,
ConsistencyReport.RelationshipConsistencyReport report, RecordAccess records )
{
if ( !referred.inUse() )
{
report.labelNotInUse( referred );
}
}
}
private enum RelationshipField implements
RecordField<RelationshipRecord, ConsistencyReport.RelationshipConsistencyReport>,
ComparativeRecordChecker<RelationshipRecord, RelationshipRecord, ConsistencyReport.RelationshipConsistencyReport>
{
SOURCE_PREV( RelationshipNodeField.SOURCE, Record.NO_PREV_RELATIONSHIP )
{
@Override
public long valueFrom( RelationshipRecord relationship )
{
return relationship.getFirstPrevRel();
}
@Override
long other( RelationshipNodeField field, RelationshipRecord relationship )
{
return field.next( relationship );
}
@Override
void otherNode( ConsistencyReport.RelationshipConsistencyReport report, RelationshipRecord relationship )
{
report.sourcePrevReferencesOtherNodes( relationship );
}
@Override
void noBackReference( ConsistencyReport.RelationshipConsistencyReport report,
RelationshipRecord relationship )
{
report.sourcePrevDoesNotReferenceBack( relationship );
}
@Override
void notUpdated( ConsistencyReport.RelationshipConsistencyReport report )
{
report.sourcePrevNotUpdated();
}
},
SOURCE_NEXT( RelationshipNodeField.SOURCE, Record.NO_NEXT_RELATIONSHIP )
{
@Override
public long valueFrom( RelationshipRecord relationship )
{
return relationship.getFirstNextRel();
}
@Override
long other( RelationshipNodeField field, RelationshipRecord relationship )
{
return field.prev( relationship );
}
@Override
void otherNode( ConsistencyReport.RelationshipConsistencyReport report, RelationshipRecord relationship )
{
report.sourceNextReferencesOtherNodes( relationship );
}
@Override
void noBackReference( ConsistencyReport.RelationshipConsistencyReport report,
RelationshipRecord relationship )
{
report.sourceNextDoesNotReferenceBack( relationship );
}
@Override
void notUpdated( ConsistencyReport.RelationshipConsistencyReport report )
{
report.sourceNextNotUpdated();
}
},
TARGET_PREV( RelationshipNodeField.TARGET, Record.NO_PREV_RELATIONSHIP )
{
@Override
public long valueFrom( RelationshipRecord relationship )
{
return relationship.getSecondPrevRel();
}
@Override
long other( RelationshipNodeField field, RelationshipRecord relationship )
{
return field.next( relationship );
}
@Override
void otherNode( ConsistencyReport.RelationshipConsistencyReport report, RelationshipRecord relationship )
{
report.targetPrevReferencesOtherNodes( relationship );
}
@Override
void noBackReference( ConsistencyReport.RelationshipConsistencyReport report,
RelationshipRecord relationship )
{
report.targetPrevDoesNotReferenceBack( relationship );
}
@Override
void notUpdated( ConsistencyReport.RelationshipConsistencyReport report )
{
report.targetPrevNotUpdated();
}
},
TARGET_NEXT( RelationshipNodeField.TARGET, Record.NO_NEXT_RELATIONSHIP )
{
@Override
public long valueFrom( RelationshipRecord relationship )
{
return relationship.getSecondNextRel();
}
@Override
long other( RelationshipNodeField field, RelationshipRecord relationship )
{
return field.prev( relationship );
}
@Override
void otherNode( ConsistencyReport.RelationshipConsistencyReport report, RelationshipRecord relationship )
{
report.targetNextReferencesOtherNodes( relationship );
}
@Override
void noBackReference( ConsistencyReport.RelationshipConsistencyReport report,
RelationshipRecord relationship )
{
report.targetNextDoesNotReferenceBack( relationship );
}
@Override
void notUpdated( ConsistencyReport.RelationshipConsistencyReport report )
{
report.targetNextNotUpdated();
}
};
private final RelationshipNodeField NODE;
private final Record NONE;
private RelationshipField( RelationshipNodeField node, Record none )
{
this.NODE = node;
this.NONE = none;
}
@Override
public void checkConsistency( RelationshipRecord relationship,
ConsistencyReport.RelationshipConsistencyReport report, RecordAccess records )
{
if ( !NONE.is( valueFrom( relationship ) ) )
{
report.forReference( records.relationship( valueFrom( relationship ) ), this );
}
}
@Override
public void checkReference( RelationshipRecord record, RelationshipRecord referred,
ConsistencyReport.RelationshipConsistencyReport report, RecordAccess records )
{
RelationshipNodeField field = RelationshipNodeField.select( referred, node( record ) );
if ( field == null )
{
otherNode( report, referred );
}
else
{
if ( other( field, referred ) != record.getId() )
{
noBackReference( report, referred );
}
}
}
@Override
public void checkChange( RelationshipRecord oldRecord, RelationshipRecord newRecord,
ConsistencyReport.RelationshipConsistencyReport report, DiffRecordAccess records )
{
if ( !newRecord.inUse() || valueFrom( oldRecord ) != valueFrom( newRecord ) )
{
if ( !NONE.is( valueFrom( oldRecord ) )
&& records.changedRelationship( valueFrom( oldRecord ) ) == null )
{
notUpdated( report );
}
}
}
abstract void notUpdated( ConsistencyReport.RelationshipConsistencyReport report );
abstract long other( RelationshipNodeField field, RelationshipRecord relationship );
abstract void otherNode( ConsistencyReport.RelationshipConsistencyReport report,
RelationshipRecord relationship );
abstract void noBackReference( ConsistencyReport.RelationshipConsistencyReport report,
RelationshipRecord relationship );
private long node( RelationshipRecord relationship )
{
return NODE.valueFrom( relationship );
}
}
}