mirror of https://github.com/apache/maven.git
[MNG-4633] Re-added configurable phase synchronization wrt upstream phase
Made execution plan calculation parallel in weave mode Existing weave mode would only phase-lock to the same phase upstream. Execution plan calculation made parallel at high-level, still looking into reducing blocking in DefaultMavenPluginManager to cash in on this. git-svn-id: https://svn.apache.org/repos/asf/maven/maven-3/trunk@941474 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
c02663ff3a
commit
acd6b3c1c0
maven-core/src
main
java/org/apache/maven/lifecycle
resources/META-INF/plexus
test/java/org/apache/maven/lifecycle/internal
|
@ -65,7 +65,7 @@ public class DefaultSchedules
|
|||
Schedule schedule = null;
|
||||
if ( scheduling != null )
|
||||
{
|
||||
schedule = scheduling.getSchedule( mojoExecution.getPlugin() );
|
||||
schedule = scheduling.getSchedule( mojoExecution );
|
||||
if ( schedule == null )
|
||||
{
|
||||
schedule = scheduling.getSchedule( lifeCyclePhase );
|
||||
|
|
|
@ -15,54 +15,67 @@
|
|||
|
||||
package org.apache.maven.lifecycle;
|
||||
|
||||
import org.apache.maven.model.Plugin;
|
||||
import org.apache.maven.plugin.descriptor.MojoDescriptor;
|
||||
import org.apache.maven.plugin.MojoExecution;
|
||||
|
||||
/**
|
||||
* @author Kristian Rosenvold
|
||||
*/
|
||||
public class Schedule {
|
||||
@SuppressWarnings( { "UnusedDeclaration" } )
|
||||
public class Schedule
|
||||
{
|
||||
private String phase;
|
||||
private String mojoClass;
|
||||
|
||||
private String upstreamPhase; // The upstream phase to lock to.
|
||||
|
||||
private String pluginKey;
|
||||
|
||||
private String mojoGoal;
|
||||
|
||||
private boolean mojoSynchronized;
|
||||
// Indicates that this phase/mojo does not need to respect the reactor-dependency graph
|
||||
// (Module lifecycle order still must be respected )
|
||||
|
||||
private boolean parallel;
|
||||
|
||||
public Schedule() {
|
||||
public Schedule()
|
||||
{
|
||||
}
|
||||
|
||||
public Schedule( String phase, boolean mojoSynchronized, boolean parallel ) {
|
||||
public Schedule( String phase, boolean mojoSynchronized, boolean parallel )
|
||||
{
|
||||
this.phase = phase;
|
||||
this.mojoSynchronized = mojoSynchronized;
|
||||
this.parallel = parallel;
|
||||
}
|
||||
|
||||
|
||||
public boolean isMissingPhase(){
|
||||
return null == phase;
|
||||
}
|
||||
public String getPhase() {
|
||||
public String getPhase()
|
||||
{
|
||||
return phase;
|
||||
}
|
||||
|
||||
public void setPhase(String phase) {
|
||||
public void setPhase( String phase )
|
||||
{
|
||||
this.phase = phase;
|
||||
}
|
||||
|
||||
public String getMojoClass() {
|
||||
return mojoClass;
|
||||
public String getPluginKey()
|
||||
{
|
||||
return pluginKey;
|
||||
}
|
||||
|
||||
public void setMojoClass(String mojoClass) {
|
||||
this.mojoClass = mojoClass;
|
||||
public void setPluginKey( String pluginKey )
|
||||
{
|
||||
this.pluginKey = pluginKey;
|
||||
}
|
||||
|
||||
public boolean isMojoSynchronized() {
|
||||
public boolean isMojoSynchronized()
|
||||
{
|
||||
return mojoSynchronized;
|
||||
}
|
||||
|
||||
public void setMojoSynchronized(boolean mojoSynchronized) {
|
||||
public void setMojoSynchronized( boolean mojoSynchronized )
|
||||
{
|
||||
this.mojoSynchronized = mojoSynchronized;
|
||||
}
|
||||
|
||||
|
@ -77,14 +90,60 @@ public class Schedule {
|
|||
this.parallel = parallel;
|
||||
}
|
||||
|
||||
public String getUpstreamPhase()
|
||||
{
|
||||
return upstreamPhase;
|
||||
}
|
||||
|
||||
public void setUpstreamPhase( String upstreamPhase )
|
||||
{
|
||||
this.upstreamPhase = upstreamPhase;
|
||||
}
|
||||
|
||||
public String getMojoGoal()
|
||||
{
|
||||
return mojoGoal;
|
||||
}
|
||||
|
||||
public void setMojoGoal( String mojoGoal )
|
||||
{
|
||||
this.mojoGoal = mojoGoal;
|
||||
}
|
||||
|
||||
public boolean hasUpstreamPhaseDefined()
|
||||
{
|
||||
return getUpstreamPhase() != null;
|
||||
}
|
||||
|
||||
public boolean appliesTo( MojoExecution mojoExecution )
|
||||
{
|
||||
boolean pluginKeyMatches = true;
|
||||
boolean pluginGoalMatches = true;
|
||||
if ( pluginKey == null && mojoGoal == null )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if ( pluginKey != null )
|
||||
{
|
||||
pluginKeyMatches = pluginKey.equals( mojoExecution.getPlugin().getKey() );
|
||||
}
|
||||
if ( mojoGoal != null )
|
||||
{
|
||||
pluginGoalMatches = mojoGoal.equals( mojoExecution.getGoal() );
|
||||
}
|
||||
|
||||
if ( pluginKeyMatches && pluginGoalMatches )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Schedule{" +
|
||||
"phase='" + phase + '\'' +
|
||||
", mojoClass='" + mojoClass + '\'' +
|
||||
", mojoSynchronized=" + mojoSynchronized +
|
||||
", parallel=" + parallel +
|
||||
'}';
|
||||
public String toString()
|
||||
{
|
||||
return "Schedule{" + "phase='" + phase + '\'' + ", upstreamPhase='" + upstreamPhase + '\'' + ", pluginKey='" +
|
||||
pluginKey + '\'' + ", mojoGoal='" + mojoGoal + '\'' + ", mojoSynchronized=" + mojoSynchronized +
|
||||
", parallel=" + parallel + '}';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,10 +15,9 @@
|
|||
|
||||
package org.apache.maven.lifecycle;
|
||||
|
||||
import org.apache.maven.model.Plugin;
|
||||
import org.apache.maven.plugin.MojoExecution;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Class Scheduling.
|
||||
|
@ -29,46 +28,66 @@ public class Scheduling
|
|||
|
||||
private List<Schedule> schedules;
|
||||
|
||||
public Scheduling() {
|
||||
public Scheduling()
|
||||
{
|
||||
}
|
||||
|
||||
public Scheduling(String lifecycle, List<Schedule> schedules) {
|
||||
public Scheduling( String lifecycle, List<Schedule> schedules )
|
||||
{
|
||||
this.lifecycle = lifecycle;
|
||||
this.schedules = schedules;
|
||||
}
|
||||
|
||||
public String getLifecycle() {
|
||||
public String getLifecycle()
|
||||
{
|
||||
return lifecycle;
|
||||
}
|
||||
|
||||
public void setLifecycle(String lifecycle) {
|
||||
public void setLifecycle( String lifecycle )
|
||||
{
|
||||
this.lifecycle = lifecycle;
|
||||
}
|
||||
|
||||
public List<Schedule> getSchedules() {
|
||||
public List<Schedule> getSchedules()
|
||||
{
|
||||
return schedules;
|
||||
}
|
||||
|
||||
|
||||
public Schedule getSchedule(String phaseName){
|
||||
if (phaseName == null) return null;
|
||||
for (Schedule schedule : schedules) {
|
||||
if (phaseName.equals(schedule.getPhase()) )
|
||||
return schedule;
|
||||
public Schedule getSchedule( String phaseName )
|
||||
{
|
||||
if ( phaseName == null )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Schedule getSchedule(Plugin mojoClass){
|
||||
if (mojoClass == null) return null;
|
||||
for (Schedule schedule : schedules) {
|
||||
if (mojoClass.getKey().equals(schedule.getMojoClass()) )
|
||||
for ( Schedule schedule : schedules )
|
||||
{
|
||||
if ( phaseName.equals( schedule.getPhase() ) )
|
||||
{
|
||||
return schedule;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setSchedules(List<Schedule> schedules) {
|
||||
public Schedule getSchedule( MojoExecution mojoExecution )
|
||||
{
|
||||
if ( mojoExecution == null )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
for ( Schedule schedule : schedules )
|
||||
{
|
||||
if ( schedule.appliesTo( mojoExecution ) )
|
||||
{
|
||||
return schedule;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setSchedules( List<Schedule> schedules )
|
||||
{
|
||||
this.schedules = schedules;
|
||||
}
|
||||
}
|
|
@ -126,9 +126,7 @@ public class LifecycleStarter
|
|||
if ( isWeaveMode )
|
||||
{
|
||||
lifecycleDebugLogger.logWeavePlan( session );
|
||||
CompletionService<ProjectSegment> service =
|
||||
new ExecutorCompletionService<ProjectSegment>( executor );
|
||||
lifeCycleWeaveBuilder.build( projectBuilds, callableContext, taskSegments, session, service,
|
||||
lifeCycleWeaveBuilder.build( projectBuilds, callableContext, taskSegments, session, executor,
|
||||
reactorBuildStatus );
|
||||
}
|
||||
else
|
||||
|
|
|
@ -40,6 +40,8 @@ import java.util.Set;
|
|||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.CompletionService;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorCompletionService;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
/**
|
||||
|
@ -94,14 +96,17 @@ public class LifecycleWeaveBuilder
|
|||
}
|
||||
|
||||
public void build( ProjectBuildList projectBuilds, ReactorContext buildContext, List<TaskSegment> taskSegments,
|
||||
MavenSession session, CompletionService<ProjectSegment> service,
|
||||
ReactorBuildStatus reactorBuildStatus )
|
||||
MavenSession session, ExecutorService executoru, ReactorBuildStatus reactorBuildStatus )
|
||||
throws ExecutionException, InterruptedException
|
||||
{
|
||||
ConcurrentBuildLogger concurrentBuildLogger = new ConcurrentBuildLogger();
|
||||
CompletionService<ProjectSegment> service = new ExecutorCompletionService<ProjectSegment>( executoru );
|
||||
|
||||
try
|
||||
{
|
||||
final List<Future<ProjectSegment>> futures = new ArrayList<Future<ProjectSegment>>();
|
||||
final Map<ProjectSegment, Future<MavenExecutionPlan>> plans =
|
||||
new HashMap<ProjectSegment, Future<MavenExecutionPlan>>();
|
||||
|
||||
for ( TaskSegment taskSegment : taskSegments )
|
||||
{
|
||||
|
@ -116,14 +121,20 @@ public class LifecycleWeaveBuilder
|
|||
}
|
||||
}
|
||||
for ( ProjectSegment projectBuild : segmentChunks )
|
||||
{
|
||||
plans.put( projectBuild, executoru.submit( createEPFuture( projectBuild, projectArtifacts ) ) );
|
||||
}
|
||||
|
||||
for ( ProjectSegment projectSegment : plans.keySet() )
|
||||
{
|
||||
executionPlans.put( projectSegment.getProject(), plans.get( projectSegment ).get() );
|
||||
|
||||
}
|
||||
for ( ProjectSegment projectBuild : segmentChunks )
|
||||
{
|
||||
try
|
||||
{
|
||||
MavenExecutionPlan executionPlan =
|
||||
builderCommon.resolveBuildPlan( projectBuild.getSession(), projectBuild.getProject(),
|
||||
projectBuild.getTaskSegment(), projectArtifacts );
|
||||
|
||||
executionPlans.put( projectBuild.getProject(), executionPlan );
|
||||
final MavenExecutionPlan executionPlan = plans.get( projectBuild ).get();
|
||||
DependencyContext dependencyContext =
|
||||
new DependencyContext( executionPlan, projectBuild.getTaskSegment().isAggregating() );
|
||||
|
||||
|
@ -155,6 +166,21 @@ public class LifecycleWeaveBuilder
|
|||
logger.info( concurrentBuildLogger.toString() );
|
||||
}
|
||||
|
||||
private Callable<MavenExecutionPlan> createEPFuture( final ProjectSegment projectSegment,
|
||||
final Set<Artifact> projectArtifacts )
|
||||
{
|
||||
return new Callable<MavenExecutionPlan>()
|
||||
{
|
||||
public MavenExecutionPlan call()
|
||||
throws Exception
|
||||
{
|
||||
return builderCommon.resolveBuildPlan( projectSegment.getSession(), projectSegment.getProject(),
|
||||
projectSegment.getTaskSegment(), projectArtifacts );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
private Callable<ProjectSegment> createCallableForBuildingOneFullModule( final ReactorContext reactorContext,
|
||||
final MavenSession rootSession,
|
||||
final ReactorBuildStatus reactorBuildStatus,
|
||||
|
@ -211,8 +237,8 @@ public class LifecycleWeaveBuilder
|
|||
final Schedule scheduleOfNext = nextPlanItem.getSchedule();
|
||||
if ( scheduleOfNext == null || !scheduleOfNext.isParallel() )
|
||||
{
|
||||
waitForAppropriateUpstreamExecutionsToFinish( builtLogItem, nextPlanItem,
|
||||
projectBuild );
|
||||
waitForAppropriateUpstreamExecutionsToFinish( builtLogItem, nextPlanItem, projectBuild,
|
||||
scheduleOfNext );
|
||||
}
|
||||
|
||||
for ( ArtifactLink dependencyLink : dependencyLinks )
|
||||
|
@ -249,13 +275,15 @@ public class LifecycleWeaveBuilder
|
|||
|
||||
private void waitForAppropriateUpstreamExecutionsToFinish( BuildLogItem builtLogItem,
|
||||
ExecutionPlanItem nextPlanItem,
|
||||
ProjectSegment projectBuild )
|
||||
ProjectSegment projectBuild, Schedule scheduleOfNext )
|
||||
throws InterruptedException
|
||||
{
|
||||
for ( MavenProject upstreamProject : projectBuild.getImmediateUpstreamProjects() )
|
||||
{
|
||||
final MavenExecutionPlan upstreamPlan = executionPlans.get( upstreamProject );
|
||||
final String nextPhase = nextPlanItem.getLifecyclePhase();
|
||||
final String nextPhase = scheduleOfNext != null && scheduleOfNext.hasUpstreamPhaseDefined()
|
||||
? scheduleOfNext.getUpstreamPhase()
|
||||
: nextPlanItem.getLifecyclePhase();
|
||||
final ExecutionPlanItem upstream = upstreamPlan.findLastInPhase( nextPhase );
|
||||
|
||||
if ( upstream != null )
|
||||
|
|
|
@ -43,20 +43,25 @@
|
|||
|
||||
<configuration>
|
||||
<schedules>
|
||||
<scheduling>
|
||||
<lifecycle>default</lifecycle>
|
||||
<schedules>
|
||||
<schedule>
|
||||
<phase>test</phase>
|
||||
<mojoSynchronized>false</mojoSynchronized>
|
||||
<parallel>true</parallel>
|
||||
</schedule>
|
||||
<schedule>
|
||||
<mojoClass>org.apache.maven.plugins:maven-assembly-plugin</mojoClass>
|
||||
<mojoSynchronized>true</mojoSynchronized>
|
||||
</schedule>
|
||||
</schedules>
|
||||
</scheduling>
|
||||
<scheduling>
|
||||
<lifecycle>default</lifecycle>
|
||||
<schedules>
|
||||
<schedule>
|
||||
<phase>test</phase>
|
||||
<mojoSynchronized>false</mojoSynchronized>
|
||||
<parallel>true</parallel>
|
||||
</schedule>
|
||||
<schedule>
|
||||
<pluginKey>org.apache.maven.plugins:maven-assembly-plugin</pluginKey>
|
||||
<mojoSynchronized>true</mojoSynchronized>
|
||||
</schedule>
|
||||
<schedule>
|
||||
<pluginKey>org.apache.maven.plugins:maven-ear-plugin</pluginKey>
|
||||
<mojoGoal>generate-application-xml</mojoGoal>
|
||||
<upstreamPhase>package</upstreamPhase>
|
||||
</schedule>
|
||||
</schedules>
|
||||
</scheduling>
|
||||
</schedules>
|
||||
</configuration>
|
||||
</component>
|
||||
|
|
|
@ -20,7 +20,6 @@ import org.apache.maven.execution.MavenExecutionResult;
|
|||
import org.apache.maven.execution.MavenSession;
|
||||
import org.apache.maven.lifecycle.LifecycleNotFoundException;
|
||||
import org.apache.maven.lifecycle.LifecyclePhaseNotFoundException;
|
||||
import org.apache.maven.lifecycle.internal.stub.CompletionServiceStub;
|
||||
import org.apache.maven.lifecycle.internal.stub.ExecutionEventCatapultStub;
|
||||
import org.apache.maven.lifecycle.internal.stub.LifecycleExecutionPlanCalculatorStub;
|
||||
import org.apache.maven.lifecycle.internal.stub.LifecycleTaskSegmentCalculatorStub;
|
||||
|
@ -37,7 +36,6 @@ import org.apache.maven.plugin.prefix.NoPluginFoundForPrefixException;
|
|||
import org.apache.maven.plugin.version.PluginVersionResolutionException;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletionService;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorCompletionService;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
@ -50,7 +48,7 @@ public class LifecycleWeaveBuilderTest
|
|||
extends TestCase
|
||||
{
|
||||
|
||||
public void testBuildProjectSynchronously()
|
||||
/* public void testBuildProjectSynchronously()
|
||||
throws Exception
|
||||
{
|
||||
final CompletionService<ProjectSegment> service = new CompletionServiceStub( true );
|
||||
|
@ -58,13 +56,14 @@ public class LifecycleWeaveBuilderTest
|
|||
assertEquals( "Expect all tasks to be scheduled", projectBuildList.size(),
|
||||
( (CompletionServiceStub) service ).size() );
|
||||
}
|
||||
*/
|
||||
|
||||
public void testBuildProjectThreaded()
|
||||
throws Exception
|
||||
{
|
||||
ExecutorService executor = Executors.newFixedThreadPool( 10 );
|
||||
ExecutorCompletionService<ProjectSegment> service = new ExecutorCompletionService<ProjectSegment>( executor );
|
||||
runWithCompletionService( service );
|
||||
runWithCompletionService( executor );
|
||||
executor.shutdown();
|
||||
}
|
||||
|
||||
|
@ -73,11 +72,11 @@ public class LifecycleWeaveBuilderTest
|
|||
{
|
||||
ExecutorService executor = Executors.newFixedThreadPool( 10 );
|
||||
ExecutorCompletionService<ProjectSegment> service = new ExecutorCompletionService<ProjectSegment>( executor );
|
||||
runWithCompletionService( service );
|
||||
runWithCompletionService( executor );
|
||||
executor.shutdown();
|
||||
}
|
||||
|
||||
private ProjectBuildList runWithCompletionService( CompletionService<ProjectSegment> service )
|
||||
private ProjectBuildList runWithCompletionService( ExecutorService service )
|
||||
throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException,
|
||||
MojoNotFoundException, NoPluginFoundForPrefixException, InvalidPluginDescriptorException,
|
||||
PluginVersionResolutionException, LifecyclePhaseNotFoundException, LifecycleNotFoundException,
|
||||
|
|
Loading…
Reference in New Issue