mirror of https://github.com/apache/maven.git
[MNG-7476] Display a warning when an aggregator mojo is locking other mojos executions
This commit is contained in:
parent
0b0a96782e
commit
0a94ff769c
|
@ -24,6 +24,7 @@ import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
|
||||||
import org.apache.maven.artifact.resolver.filter.CumulativeScopeArtifactFilter;
|
import org.apache.maven.artifact.resolver.filter.CumulativeScopeArtifactFilter;
|
||||||
import org.apache.maven.execution.ExecutionEvent;
|
import org.apache.maven.execution.ExecutionEvent;
|
||||||
import org.apache.maven.execution.MavenSession;
|
import org.apache.maven.execution.MavenSession;
|
||||||
|
import org.apache.maven.internal.MultilineMessageHelper;
|
||||||
import org.apache.maven.lifecycle.LifecycleExecutionException;
|
import org.apache.maven.lifecycle.LifecycleExecutionException;
|
||||||
import org.apache.maven.lifecycle.MissingProjectException;
|
import org.apache.maven.lifecycle.MissingProjectException;
|
||||||
import org.apache.maven.plugin.BuildPluginManager;
|
import org.apache.maven.plugin.BuildPluginManager;
|
||||||
|
@ -44,6 +45,8 @@ import org.codehaus.plexus.component.annotations.Requirement;
|
||||||
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
|
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
|
||||||
import org.codehaus.plexus.util.StringUtils;
|
import org.codehaus.plexus.util.StringUtils;
|
||||||
import org.eclipse.aether.SessionData;
|
import org.eclipse.aether.SessionData;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -56,7 +59,6 @@ import java.util.TreeSet;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
import java.util.concurrent.locks.Lock;
|
import java.util.concurrent.locks.Lock;
|
||||||
import java.util.concurrent.locks.ReadWriteLock;
|
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
|
|
||||||
|
@ -75,6 +77,8 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
public class MojoExecutor
|
public class MojoExecutor
|
||||||
{
|
{
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger( MojoExecutor.class );
|
||||||
|
|
||||||
@Requirement
|
@Requirement
|
||||||
private BuildPluginManager pluginManager;
|
private BuildPluginManager pluginManager;
|
||||||
|
|
||||||
|
@ -87,7 +91,7 @@ public class MojoExecutor
|
||||||
@Requirement
|
@Requirement
|
||||||
private ExecutionEventCatapult eventCatapult;
|
private ExecutionEventCatapult eventCatapult;
|
||||||
|
|
||||||
private final ReadWriteLock aggregatorLock = new ReentrantReadWriteLock();
|
private final OwnerReentrantReadWriteLock aggregatorLock = new OwnerReentrantReadWriteLock();
|
||||||
|
|
||||||
@Requirement
|
@Requirement
|
||||||
private PlexusContainer container;
|
private PlexusContainer container;
|
||||||
|
@ -244,7 +248,7 @@ public class MojoExecutor
|
||||||
private class ProjectLock implements AutoCloseable
|
private class ProjectLock implements AutoCloseable
|
||||||
{
|
{
|
||||||
final Lock acquiredAggregatorLock;
|
final Lock acquiredAggregatorLock;
|
||||||
final Lock acquiredProjectLock;
|
final OwnerReentrantLock acquiredProjectLock;
|
||||||
|
|
||||||
ProjectLock( MavenSession session, MojoDescriptor mojoDescriptor )
|
ProjectLock( MavenSession session, MojoDescriptor mojoDescriptor )
|
||||||
{
|
{
|
||||||
|
@ -254,8 +258,31 @@ public class MojoExecutor
|
||||||
boolean aggregator = mojoDescriptor.isAggregator();
|
boolean aggregator = mojoDescriptor.isAggregator();
|
||||||
acquiredAggregatorLock = aggregator ? aggregatorLock.writeLock() : aggregatorLock.readLock();
|
acquiredAggregatorLock = aggregator ? aggregatorLock.writeLock() : aggregatorLock.readLock();
|
||||||
acquiredProjectLock = getProjectLock( session );
|
acquiredProjectLock = getProjectLock( session );
|
||||||
acquiredAggregatorLock.lock();
|
if ( !acquiredAggregatorLock.tryLock() )
|
||||||
acquiredProjectLock.lock();
|
{
|
||||||
|
Thread owner = aggregatorLock.getOwner();
|
||||||
|
MojoDescriptor ownerMojo = owner != null ? mojos.get( owner ) : null;
|
||||||
|
String str = ownerMojo != null ? " The " + ownerMojo.getId() : "An";
|
||||||
|
String msg = str + " aggregator mojo is already being executed "
|
||||||
|
+ "in this parallel build, those kind of mojos require exclusive access to "
|
||||||
|
+ "reactor to prevent race conditions. This mojo execution will be blocked "
|
||||||
|
+ "until the aggregator mojo is done.";
|
||||||
|
warn( msg );
|
||||||
|
acquiredAggregatorLock.lock();
|
||||||
|
}
|
||||||
|
if ( !acquiredProjectLock.tryLock() )
|
||||||
|
{
|
||||||
|
Thread owner = acquiredProjectLock.getOwner();
|
||||||
|
MojoDescriptor ownerMojo = owner != null ? mojos.get( owner ) : null;
|
||||||
|
String str = ownerMojo != null ? " The " + ownerMojo.getId() : "A";
|
||||||
|
String msg = str + " mojo is already being executed "
|
||||||
|
+ "on the project " + session.getCurrentProject().getGroupId()
|
||||||
|
+ ":" + session.getCurrentProject().getArtifactId() + ". "
|
||||||
|
+ "This mojo execution will be blocked "
|
||||||
|
+ "until the mojo is done.";
|
||||||
|
warn( msg );
|
||||||
|
acquiredProjectLock.lock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -280,10 +307,10 @@ public class MojoExecutor
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings( { "unchecked", "rawtypes" } )
|
@SuppressWarnings( { "unchecked", "rawtypes" } )
|
||||||
private Lock getProjectLock( MavenSession session )
|
private OwnerReentrantLock getProjectLock( MavenSession session )
|
||||||
{
|
{
|
||||||
SessionData data = session.getRepositorySession().getData();
|
SessionData data = session.getRepositorySession().getData();
|
||||||
ConcurrentMap<MavenProject, Lock> locks = ( ConcurrentMap ) data.get( ProjectLock.class );
|
ConcurrentMap<MavenProject, OwnerReentrantLock> locks = ( ConcurrentMap ) data.get( ProjectLock.class );
|
||||||
// initialize the value if not already done (in case of a concurrent access) to the method
|
// initialize the value if not already done (in case of a concurrent access) to the method
|
||||||
if ( locks == null )
|
if ( locks == null )
|
||||||
{
|
{
|
||||||
|
@ -291,11 +318,11 @@ public class MojoExecutor
|
||||||
data.set( ProjectLock.class, null, new ConcurrentHashMap<>() );
|
data.set( ProjectLock.class, null, new ConcurrentHashMap<>() );
|
||||||
locks = ( ConcurrentMap ) data.get( ProjectLock.class );
|
locks = ( ConcurrentMap ) data.get( ProjectLock.class );
|
||||||
}
|
}
|
||||||
Lock acquiredProjectLock = locks.get( session.getCurrentProject() );
|
OwnerReentrantLock acquiredProjectLock = locks.get( session.getCurrentProject() );
|
||||||
if ( acquiredProjectLock == null )
|
if ( acquiredProjectLock == null )
|
||||||
{
|
{
|
||||||
acquiredProjectLock = new ReentrantLock();
|
acquiredProjectLock = new OwnerReentrantLock();
|
||||||
Lock prev = locks.putIfAbsent( session.getCurrentProject(), acquiredProjectLock );
|
OwnerReentrantLock prev = locks.putIfAbsent( session.getCurrentProject(), acquiredProjectLock );
|
||||||
if ( prev != null )
|
if ( prev != null )
|
||||||
{
|
{
|
||||||
acquiredProjectLock = prev;
|
acquiredProjectLock = prev;
|
||||||
|
@ -305,6 +332,32 @@ public class MojoExecutor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static class OwnerReentrantLock extends ReentrantLock
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public Thread getOwner()
|
||||||
|
{
|
||||||
|
return super.getOwner();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class OwnerReentrantReadWriteLock extends ReentrantReadWriteLock
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public Thread getOwner()
|
||||||
|
{
|
||||||
|
return super.getOwner();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void warn( String msg )
|
||||||
|
{
|
||||||
|
for ( String s : MultilineMessageHelper.format( msg ) )
|
||||||
|
{
|
||||||
|
LOGGER.warn( s );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void doExecute( MavenSession session, MojoExecution mojoExecution, ProjectIndex projectIndex,
|
private void doExecute( MavenSession session, MojoExecution mojoExecution, ProjectIndex projectIndex,
|
||||||
DependencyContext dependencyContext )
|
DependencyContext dependencyContext )
|
||||||
throws LifecycleExecutionException
|
throws LifecycleExecutionException
|
||||||
|
|
Loading…
Reference in New Issue