/** * 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.full; import static org.neo4j.consistency.checking.full.MultiPassStore.ARRAYS; import static org.neo4j.consistency.checking.full.MultiPassStore.NODES; import static org.neo4j.consistency.checking.full.MultiPassStore.PROPERTIES; import static org.neo4j.consistency.checking.full.MultiPassStore.RELATIONSHIPS; import static org.neo4j.consistency.checking.full.MultiPassStore.STRINGS; import java.lang.reflect.Array; import java.util.ArrayList; import java.util.List; import org.neo4j.consistency.ConsistencyCheckSettings; import org.neo4j.consistency.checking.CheckDecorator; import org.neo4j.consistency.report.ConsistencyLogger; import org.neo4j.consistency.report.ConsistencyReporter; import org.neo4j.consistency.report.ConsistencySummaryStatistics; import org.neo4j.consistency.report.MessageConsistencyLogger; import org.neo4j.consistency.store.CacheSmallStoresRecordAccess; import org.neo4j.consistency.store.DiffRecordAccess; import org.neo4j.consistency.store.DirectRecordAccess; import org.neo4j.graphdb.factory.GraphDatabaseSettings; import org.neo4j.helpers.progress.ProgressMonitorFactory; import org.neo4j.kernel.configuration.Config; import org.neo4j.kernel.impl.nioneo.store.AbstractBaseRecord; import org.neo4j.kernel.impl.nioneo.store.DynamicRecord; import org.neo4j.kernel.impl.nioneo.store.NodeRecord; import org.neo4j.kernel.impl.nioneo.store.PropertyIndexRecord; import org.neo4j.kernel.impl.nioneo.store.PropertyRecord; import org.neo4j.kernel.impl.nioneo.store.RecordStore; import org.neo4j.kernel.impl.nioneo.store.RelationshipRecord; import org.neo4j.kernel.impl.nioneo.store.RelationshipTypeRecord; import org.neo4j.kernel.impl.nioneo.store.StoreAccess; import org.neo4j.kernel.impl.util.StringLogger; public class FullCheck { private final boolean checkPropertyOwners; private final TaskExecutionOrder order; private final ProgressMonitorFactory progressFactory; private final Long totalMappedMemory; public FullCheck( Config tuningConfiguration, ProgressMonitorFactory progressFactory ) { this.checkPropertyOwners = tuningConfiguration.get( ConsistencyCheckSettings.consistency_check_property_owners ); this.order = tuningConfiguration.get( ConsistencyCheckSettings.consistency_check_execution_order ); this.totalMappedMemory = tuningConfiguration.get( GraphDatabaseSettings.all_stores_total_mapped_memory_size ); this.progressFactory = progressFactory; } public ConsistencySummaryStatistics execute( StoreAccess store, StringLogger logger ) throws ConsistencyCheckIncompleteException { ConsistencySummaryStatistics summary = new ConsistencySummaryStatistics(); OwnerCheck ownerCheck = new OwnerCheck( checkPropertyOwners ); execute( store, ownerCheck, recordAccess( store ), new MessageConsistencyLogger( logger ), summary ); ownerCheck.scanForOrphanChains( progressFactory ); if ( !summary.isConsistent() ) { logger.logMessage( "Inconsistencies found: " + summary ); } return summary; } void execute( StoreAccess store, CheckDecorator decorator, DiffRecordAccess recordAccess, ConsistencyLogger logger, ConsistencySummaryStatistics summary ) throws ConsistencyCheckIncompleteException { StoreProcessor processEverything = new StoreProcessor( decorator, new ConsistencyReporter( logger, recordAccess, summary ) ); ProgressMonitorFactory.MultiPartBuilder progress = progressFactory.multipleParts( "Full consistency check" ); List<StoreProcessorTask> tasks = new ArrayList<StoreProcessorTask>( 9 ); MultiPassStore.Factory processorFactory = new MultiPassStore.Factory( decorator, logger, totalMappedMemory, store, recordAccess, summary ); tasks.add( new StoreProcessorTask<NodeRecord>( store.getNodeStore(), progress, order, processEverything, processorFactory.createAll( PROPERTIES, RELATIONSHIPS ) ) ); tasks.add( new StoreProcessorTask<RelationshipRecord>( store.getRelationshipStore(), progress, order, processEverything, processorFactory.createAll( NODES, PROPERTIES, RELATIONSHIPS ) ) ); tasks.add( new StoreProcessorTask<PropertyRecord>( store.getPropertyStore(), progress, order, processEverything, processorFactory.createAll( PROPERTIES, STRINGS, ARRAYS ) ) ); tasks.add( new StoreProcessorTask<DynamicRecord>( store.getStringStore(), progress, order, processEverything, processorFactory.createAll( STRINGS ) ) ); tasks.add( new StoreProcessorTask<DynamicRecord>( store.getArrayStore(), progress, order, processEverything, processorFactory.createAll( ARRAYS ) ) ); tasks.add( new StoreProcessorTask<RelationshipTypeRecord>( store.getRelationshipTypeStore(), progress, order, processEverything, processEverything ) ); tasks.add( new StoreProcessorTask<PropertyIndexRecord>( store.getPropertyIndexStore(), progress, order, processEverything, processEverything ) ); tasks.add( new StoreProcessorTask<DynamicRecord>( store.getTypeNameStore(), progress, order, processEverything, processEverything ) ); tasks.add( new StoreProcessorTask<DynamicRecord>( store.getPropertyKeyStore(), progress, order, processEverything, processEverything ) ); order.execute( tasks, progress.build() ); } static DiffRecordAccess recordAccess( StoreAccess store ) { return new CacheSmallStoresRecordAccess( new DirectRecordAccess( store ), readAllRecords( PropertyIndexRecord.class, store.getPropertyIndexStore() ), readAllRecords( RelationshipTypeRecord.class, store.getRelationshipTypeStore() ) ); } private static <T extends AbstractBaseRecord> T[] readAllRecords( Class<T> type, RecordStore<T> store ) { @SuppressWarnings("unchecked") T[] records = (T[]) Array.newInstance( type, (int) store.getHighId() ); for ( int i = 0; i < records.length; i++ ) { records[i] = store.forceGetRecord( i ); } return records; } }