/**
* 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.store.windowpool;
import static java.lang.String.format;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.channels.FileChannel;
import org.neo4j.graphdb.factory.GraphDatabaseSettings;
import org.neo4j.kernel.configuration.Config;
import org.neo4j.kernel.impl.nioneo.store.UnderlyingStorageException;
import org.neo4j.consistency.store.paging.Cart;
import org.neo4j.kernel.impl.nioneo.store.windowpool.WindowPool;
import org.neo4j.kernel.impl.nioneo.store.windowpool.WindowPoolFactory;
import org.neo4j.kernel.impl.util.StringLogger;
public class ScanResistantWindowPoolFactory implements WindowPoolFactory
{
private final int targetBytesPerPage;
private final Cart cart;
private final int reportingInterval;
private final MappingStatisticsListener statisticsListener;
public ScanResistantWindowPoolFactory( Config configuration, StringLogger logger )
{
this.targetBytesPerPage = pageSize( configuration );
this.cart = new Cart( mappablePages( configuration, targetBytesPerPage ) );
this.reportingInterval = configuration.get( GraphDatabaseSettings.log_mapped_memory_stats_interval );
this.statisticsListener = createStatisticsListener( configuration, logger );
}
private static int pageSize( Config configuration )
{
long pageSize = configuration.get( GraphDatabaseSettings.mapped_memory_page_size );
if ( pageSize > Integer.MAX_VALUE )
{
throw new IllegalArgumentException( format( "configured page size [%d bytes] is too large", pageSize ) );
}
return (int) pageSize;
}
private static int mappablePages( Config configuration, int targetBytesPerPage )
{
long bytes = configuration.get( GraphDatabaseSettings.all_stores_total_mapped_memory_size );
long pageCount = bytes / targetBytesPerPage;
if ( pageCount > Integer.MAX_VALUE )
{
throw new IllegalArgumentException( format( "configured page size [%d bytes] and mapped memory [%d bytes]" +
" implies too many pages", targetBytesPerPage, bytes ) );
}
return (int) pageCount;
}
private MappingStatisticsListener createStatisticsListener( Config configuration, StringLogger logger )
{
if ( configuration.get( GraphDatabaseSettings.log_mapped_memory_stats ) )
{
try
{
return new LoggingStatisticsListener(
configuration.get( GraphDatabaseSettings.log_mapped_memory_stats_filename ) );
}
catch ( FileNotFoundException e )
{
logger.logMessage( "Unable to create logger for mapped memory statistics; will be silent", e );
}
}
return new MappingStatisticsListener()
{
@Override
public void onStatistics( String storeFileName, int acquiredPages, int mappedPages, long samplePeriod )
{
// silent
}
};
}
@Override
public WindowPool create( String storageFileName, int recordSize, FileChannel fileChannel,
Config configuration, StringLogger log )
{
try
{
return new ScanResistantWindowPool( storageFileName, recordSize, targetBytesPerPage,
new FileMapper( fileChannel ), cart, reportingInterval, statisticsListener );
}
catch ( IOException e )
{
throw new UnderlyingStorageException( e );
}
}
}