Skip to content

Commit

Permalink
MWEBSTART-70 - make plugin run faster (use now a threadExecutor for e…
Browse files Browse the repository at this point in the history
…ach request)

git-svn-id: file:///home/tiste/MOJOHAUS-TO-GIT/SVN-MOJO-WIP/trunk/mojo/webstart@19190 52ab4f32-60fc-0310-b215-8acea882cd1b
  • Loading branch information
Tony Chemit committed Jan 7, 2014
1 parent 217cb36 commit 6ffe2f7
Show file tree
Hide file tree
Showing 9 changed files with 331 additions and 137 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,14 @@ public void init( JnlpDependencyGlobalConfig globalConfig )
this.globalConfig = globalConfig;
}

/**
* {@inheritDoc}
*/
public JnlpDependencyRequests createRequests()
{
return new JnlpDependencyRequests( globalConfig );
}

/**
* {@inheritDoc}
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,18 @@
* under the License.
*/

import org.apache.maven.artifact.Artifact;
import org.apache.maven.plugin.MojoExecutionException;
import org.codehaus.mojo.webstart.dependency.task.JnlpDependencyTask;
import org.codehaus.mojo.webstart.dependency.task.JnlpDependencyTaskException;
import org.codehaus.mojo.webstart.util.IOUtil;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
import org.codehaus.plexus.logging.AbstractLogEnabled;
import org.codehaus.plexus.logging.Logger;

import java.io.File;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
* Created on 1/4/14.
Expand All @@ -46,157 +47,194 @@ public class DefaultJnlpDependencyRequestConsumer
@Requirement
private IOUtil ioUtil;

private int maxThreads;

private boolean failFast;

/**
* {@inheritDoc}
*/
public void setMaxThreads( int maxThreads )
public JnlpDependencyResults execute( JnlpDependencyRequestConsumerConfig config, JnlpDependencyRequests requests )
{
this.maxThreads = maxThreads;
}

/**
* {@inheritDoc}
*/
public void setFailFast( boolean failFast )
{
this.failFast = failFast;
getLogger().info( "Process " + requests.getNbRequests() + " dependencies." );

RequestExecutor executor = new RequestExecutor( getLogger(), ioUtil, config );

executor.registerRequests( requests.getRequests() );

JnlpDependencyResults results = executor.terminatesAndWaits();

return results;
}

/**
* {@inheritDoc}
*/
public JnlpDependencyResults execute( JnlpDependencyRequests requests )
private static class RequestExecutor
extends ThreadPoolExecutor
{

List<JnlpDependencyRequest> dependencyRequests = requests.getRequests();
private final JnlpDependencyRequestConsumerConfig config;

private final Logger logger;

getLogger().info( "Process " + dependencyRequests.size() + " requests." );
private final IOUtil ioUtil;

JnlpDependencyResults results = new JnlpDependencyResults();
private final JnlpDependencyResults results;

for ( JnlpDependencyRequest request : dependencyRequests )
public RequestExecutor( Logger logger, IOUtil ioUtil, JnlpDependencyRequestConsumerConfig config )
{
JnlpDependencyResult result = execute( request );
results.registerResult( request, result );
if ( failFast && result.isError() )
{
getLogger().warn( "Fail fast after first dependency processing error." );
break;
}
super( config.getMaxThreads(), config.getMaxThreads(), 1L, TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>() );
this.logger = logger;
this.ioUtil = ioUtil;
this.config = config;
this.results = new JnlpDependencyResults();
}
return results;
}

protected JnlpDependencyResult execute( JnlpDependencyRequest request )
{

JnlpDependencyConfig config = request.getConfig();
@Override
protected void afterExecute( Runnable r, Throwable t )
{
super.afterExecute( r, t );
RequestTask task = (RequestTask) r;

JnlpDependencyResult result = prepareResult( config );
JnlpDependencyResult result = task.result;

File workingDirectory = config.getWorkingDirectory();
results.registerResult( task.request, result );

File workingFile = result.getOriginalfile();
boolean withError = t != null;

JnlpDependencyTask[] tasks = request.getTasks();
if ( withError )
{
result.setError( t );

for ( int i = 0, length = tasks.length; i < length; i++ )
{
if ( config.isFailFast() )
{
logger.warn( "Fail fast after first dependency processing error." );

JnlpDependencyTask task = tasks[i];
//TODO Stop the executor
shutdownNow();
}
}


}

/**
* Ask the thread to stop.
* <p/>
* It will finish all incoming files (but will not accept more files to
* parse)
* <p/>
* <b>Note:</b> The method does not return until all files are not consumed.
*/
public JnlpDependencyResults terminatesAndWaits()
{
// ask executor to terminate
shutdown();

// copy previous file to a new task isolated directory
File newDirectory = new File( workingDirectory, i + "_" + task.getClass().getSimpleName() );
try
{
ioUtil.copyFileToDirectoryIfNecessary( workingFile, newDirectory );
// wait until all submited jobs are terminated
// i don't want timeout, i think 2 days is good :)
awaitTermination( 2 * 60 * 60 * 24, TimeUnit.SECONDS );
}
catch ( MojoExecutionException e )
catch ( InterruptedException e )
{
result.setError( e );
break;
logger.error( "Could not stop the executor after two days...", e );
}
workingFile = new File( newDirectory, workingFile.getName() );

getLogger().debug( String.format( "[task %s] (%s): workingFile: %s", i, task, workingFile ) );
try
{
workingFile = task.execute( config, workingFile );
}
catch ( JnlpDependencyTaskException e )
return results;
}

public void registerRequests( List<JnlpDependencyRequest> dependencyRequests )
{

for ( JnlpDependencyRequest dependencyRequest : dependencyRequests )
{
result.setError( e );
break;
RequestTask newtask = new RequestTask( logger, ioUtil, dependencyRequest );

JnlpDependencyResult result = newtask.result;
if ( result.isUptodate() )
{
if ( config.isVerbose() )
{
logger.info(
"Skip up-to-date dependency: " + dependencyRequest.getConfig().getArtifact().getId() );
}
results.registerResult( newtask.request, result );
}
else
{
if ( config.isVerbose() )
{
logger.info( "Process dependency: " + dependencyRequest.getConfig().getArtifact().getId() );
}
execute( newtask );
}
}
}
}

// copy to final destination

finalizeResult( config, workingFile, result );
private static class RequestTask
implements Runnable
{

getLogger().info( "Dependency " + config.getArtifact().getId() + " treated." );
private final Logger logger;

return result;
}
private final IOUtil ioUtil;

private JnlpDependencyResult prepareResult( JnlpDependencyConfig config )
{
private final JnlpDependencyRequest request;

File workingDirectory = config.getWorkingDirectory();
private JnlpDependencyResult result;

Artifact artifact = config.getArtifact();
private RequestTask( Logger logger, IOUtil ioUtil, JnlpDependencyRequest request )
{
this.logger = logger;
this.ioUtil = ioUtil;
this.request = request;
this.result = new JnlpDependencyResult( request );
}

File incomingFile = artifact.getFile();
/**
* {@inheritDoc}
*/
public void run()
{
JnlpDependencyConfig config = request.getConfig();

String fileName = config.getDependencyFilenameStrategy().getDependencyFilename( artifact, false );
File workingFile = request.getOriginalFile();

File workingFile = new File( workingDirectory, fileName );
try
{
// copy artifact file to original file
ioUtil.copyFile( config.getArtifact().getFile(), workingFile );

JnlpDependencyResult result = new JnlpDependencyResult( artifact, workingFile );
File workingDirectory = config.getWorkingDirectory();

copyFile( incomingFile, workingFile, result );
return result;
}
JnlpDependencyTask[] tasks = request.getTasks();

private void finalizeResult( JnlpDependencyConfig config, File workingFile, JnlpDependencyResult result )
{
for ( int i = 0, length = tasks.length; i < length; i++ )
{

// copy to final destination
JnlpDependencyTask task = tasks[i];

File finalDirectory = config.getFinalDirectory();
String filename = config.getDependencyFilenameStrategy().getDependencyFilename( config.getArtifact(),
config.isOutputJarVersion() );
// copy previous file to a new task isolated directory
File newDirectory = new File( workingDirectory, i + "_" + task.getClass().getSimpleName() );
ioUtil.copyFileToDirectoryIfNecessary( workingFile, newDirectory );

if ( config.isPack200() )
{
filename += ".pack";
}
workingFile = new File( newDirectory, workingFile.getName() );

if ( config.isGzip() )
{
filename += ".gz";
}
logger.debug( String.format( "[task %s] (%s): workingFile: %s", i, task, workingFile ) );

File finalFile = new File( finalDirectory, filename );
workingFile = task.execute( config, workingFile );
}

copyFile( workingFile, finalFile, result );
result.setFinalFile( finalFile );
}
// copy to final destination
ioUtil.copyFile( workingFile, request.getFinalFile() );
}
catch ( Exception e )
{
result.setError( e );
}

private void copyFile( File source, File destination, JnlpDependencyResult result )
{
getLogger().debug( "Copy " + source.getName() + " to " + destination );
try
{
ioUtil.copyFile( source, destination );
}
catch ( MojoExecutionException e )
{
result.setError( e );
logger.info( "Dependency " + config.getArtifact().getId() + " treated." );
}
}
}
Loading

0 comments on commit 6ffe2f7

Please sign in to comment.