package com.ldbc.driver.client;
import com.google.common.base.Charsets;
import com.google.common.collect.Iterators;
import com.ldbc.driver.ClientException;
import com.ldbc.driver.Db;
import com.ldbc.driver.DbException;
import com.ldbc.driver.Workload;
import com.ldbc.driver.WorkloadException;
import com.ldbc.driver.control.ControlService;
import com.ldbc.driver.control.LoggingService;
import com.ldbc.driver.csv.simple.SimpleCsvFileReader;
import com.ldbc.driver.util.ClassLoaderHelper;
import com.ldbc.driver.validation.DbValidationResult;
import com.ldbc.driver.validation.DbValidator;
import com.ldbc.driver.validation.ValidationParam;
import com.ldbc.driver.validation.ValidationParamsFromCsvRows;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.Iterator;
import static java.lang.String.format;
public class ValidateDatabaseMode implements ClientMode<DbValidationResult>
{
private final ControlService controlService;
private final LoggingService loggingService;
private Workload workload = null;
private Db database = null;
public ValidateDatabaseMode( ControlService controlService ) throws ClientException
{
this.controlService = controlService;
this.loggingService = controlService.loggingServiceFactory().loggingServiceFor( getClass().getSimpleName() );
}
@Override
public void init() throws ClientException
{
try
{
workload = ClassLoaderHelper.loadWorkload( controlService.configuration().workloadClassName() );
workload.init( controlService.configuration() );
}
catch ( Exception e )
{
throw new ClientException( format( "Error loading Workload class: %s",
controlService.configuration().workloadClassName() ), e );
}
loggingService.info( format( "Loaded Workload: %s", workload.getClass().getName() ) );
try
{
database = ClassLoaderHelper.loadDb( controlService.configuration().dbClassName() );
database.init(
controlService.configuration().asMap(),
controlService.loggingServiceFactory().loggingServiceFor( database.getClass().getSimpleName() ),
workload.operationTypeToClassMapping()
);
}
catch ( DbException e )
{
throw new ClientException(
format( "Error loading DB class: %s", controlService.configuration().dbClassName() ), e );
}
loggingService.info( format( "Loaded DB: %s", database.getClass().getName() ) );
loggingService.info( "Driver Configuration" );
loggingService.info( controlService.toString() );
}
@Override
public DbValidationResult startExecutionAndAwaitCompletion() throws ClientException
{
try ( Workload w = workload; Db db = database )
{
File validationParamsFile = new File( controlService.configuration().databaseValidationFilePath() );
loggingService.info(
format( "Validating database against expected results\n * Db: %s\n * Validation Params File: %s",
db.getClass().getName(), validationParamsFile.getAbsolutePath() ) );
int validationParamsCount;
SimpleCsvFileReader validationParamsReader;
try
{
validationParamsReader = new SimpleCsvFileReader( validationParamsFile,
SimpleCsvFileReader.DEFAULT_COLUMN_SEPARATOR_REGEX_STRING );
validationParamsCount = Iterators.size( validationParamsReader );
validationParamsReader.close();
validationParamsReader = new SimpleCsvFileReader( validationParamsFile,
SimpleCsvFileReader.DEFAULT_COLUMN_SEPARATOR_REGEX_STRING );
}
catch ( IOException e )
{
throw new ClientException( "Error encountered trying to create CSV file reader", e );
}
DbValidationResult databaseValidationResult;
try
{
Iterator<ValidationParam> validationParams =
new ValidationParamsFromCsvRows( validationParamsReader, w );
DbValidator dbValidator = new DbValidator();
databaseValidationResult = dbValidator.validate(
validationParams,
db,
validationParamsCount,
w
);
}
catch ( WorkloadException e )
{
throw new ClientException( format( "Error reading validation parameters file\nFile: %s",
validationParamsFile.getAbsolutePath() ), e );
}
validationParamsReader.close();
File failedValidationOperationsFile = new File( validationParamsFile.getParentFile(),
removeExtension( validationParamsFile.getName() ) + "-failed-actual.json" );
if ( failedValidationOperationsFile.exists() )
{
FileUtils.forceDelete( failedValidationOperationsFile );
}
failedValidationOperationsFile.createNewFile();
try ( Writer writer = new OutputStreamWriter( new FileOutputStream( failedValidationOperationsFile ),
Charsets.UTF_8 ) )
{
writer.write( databaseValidationResult.actualResultsForFailedOperationsAsJsonString( w ) );
writer.flush();
writer.close();
}
catch ( Exception e )
{
throw new ClientException(
format( "Encountered error while writing to file\nFile: %s",
failedValidationOperationsFile.getAbsolutePath() ),
e
);
}
File expectedResultsForFailedValidationOperationsFile = new File( validationParamsFile.getParentFile(),
removeExtension( validationParamsFile.getName() ) + "-failed-expected.json" );
if ( expectedResultsForFailedValidationOperationsFile.exists() )
{
FileUtils.forceDelete( expectedResultsForFailedValidationOperationsFile );
}
expectedResultsForFailedValidationOperationsFile.createNewFile();
try ( Writer writer = new OutputStreamWriter(
new FileOutputStream( expectedResultsForFailedValidationOperationsFile ), Charsets.UTF_8 ) )
{
writer.write( databaseValidationResult.expectedResultsForFailedOperationsAsJsonString( w ) );
writer.flush();
writer.close();
}
catch ( Exception e )
{
throw new ClientException(
format( "Encountered error while writing to file\nFile: %s",
failedValidationOperationsFile.getAbsolutePath() ),
e
);
}
loggingService.info( databaseValidationResult.resultMessage() );
loggingService.info( format(
"For details see the following files:\n * %s\n * %s",
failedValidationOperationsFile.getAbsolutePath(),
expectedResultsForFailedValidationOperationsFile.getAbsolutePath()
) );
return databaseValidationResult;
}
catch ( IOException e )
{
throw new ClientException( "Error occurred during database validation", e );
}
}
String removeExtension( String filename )
{
return (filename.indexOf( "." ) == -1) ? filename : filename.substring( 0, filename.lastIndexOf( "." ) );
}
}