1 package org.apache.maven.lifecycle.internal.builder.multithreaded;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.util.List;
23 import java.util.Map;
24 import java.util.concurrent.Callable;
25 import java.util.concurrent.CompletionService;
26 import java.util.concurrent.ExecutionException;
27 import java.util.concurrent.ExecutorCompletionService;
28 import java.util.concurrent.ExecutorService;
29 import java.util.concurrent.Executors;
30 import java.util.concurrent.Future;
31
32 import org.apache.maven.execution.MavenSession;
33 import org.apache.maven.lifecycle.internal.BuildThreadFactory;
34 import org.apache.maven.lifecycle.internal.LifecycleModuleBuilder;
35 import org.apache.maven.lifecycle.internal.ProjectBuildList;
36 import org.apache.maven.lifecycle.internal.ProjectSegment;
37 import org.apache.maven.lifecycle.internal.ReactorBuildStatus;
38 import org.apache.maven.lifecycle.internal.ReactorContext;
39 import org.apache.maven.lifecycle.internal.TaskSegment;
40 import org.apache.maven.lifecycle.internal.builder.Builder;
41 import org.apache.maven.project.MavenProject;
42 import org.codehaus.plexus.component.annotations.Component;
43 import org.codehaus.plexus.component.annotations.Requirement;
44 import org.codehaus.plexus.logging.Logger;
45
46
47
48
49
50
51
52
53
54
55 @Component( role = Builder.class, hint = "multithreaded" )
56 public class MultiThreadedBuilder
57 implements Builder
58 {
59
60 @Requirement
61 private Logger logger;
62
63 @Requirement
64 private LifecycleModuleBuilder lifecycleModuleBuilder;
65
66
67 public MultiThreadedBuilder()
68 {
69 }
70
71 @Override
72 public void build( MavenSession session, ReactorContext reactorContext, ProjectBuildList projectBuilds,
73 List<TaskSegment> taskSegments, ReactorBuildStatus reactorBuildStatus )
74 throws ExecutionException, InterruptedException
75 {
76 ExecutorService executor =
77 Executors.newFixedThreadPool( Math.min( session.getRequest().getDegreeOfConcurrency(),
78 session.getProjects().size() ), new BuildThreadFactory() );
79 CompletionService<ProjectSegment> service = new ExecutorCompletionService<>( executor );
80 ConcurrencyDependencyGraph analyzer =
81 new ConcurrencyDependencyGraph( projectBuilds, session.getProjectDependencyGraph() );
82
83
84 ThreadOutputMuxer muxer = null;
85
86 for ( TaskSegment taskSegment : taskSegments )
87 {
88 Map<MavenProject, ProjectSegment> projectBuildMap = projectBuilds.selectSegment( taskSegment );
89 try
90 {
91 multiThreadedProjectTaskSegmentBuild( analyzer, reactorContext, session, service, taskSegment,
92 projectBuildMap, muxer );
93 if ( reactorContext.getReactorBuildStatus().isHalted() )
94 {
95 break;
96 }
97 }
98 catch ( Exception e )
99 {
100 session.getResult().addException( e );
101 break;
102 }
103
104 }
105 }
106
107 private void multiThreadedProjectTaskSegmentBuild( ConcurrencyDependencyGraph analyzer,
108 ReactorContext reactorContext, MavenSession rootSession,
109 CompletionService<ProjectSegment> service,
110 TaskSegment taskSegment,
111 Map<MavenProject, ProjectSegment> projectBuildList,
112 ThreadOutputMuxer muxer )
113 {
114
115
116 for ( MavenProject mavenProject : analyzer.getRootSchedulableBuilds() )
117 {
118 ProjectSegment projectSegment = projectBuildList.get( mavenProject );
119 logger.debug( "Scheduling: " + projectSegment.getProject() );
120 Callable<ProjectSegment> cb =
121 createBuildCallable( rootSession, projectSegment, reactorContext, taskSegment, muxer );
122 service.submit( cb );
123 }
124
125
126 for ( int i = 0; i < analyzer.getNumberOfBuilds(); i++ )
127 {
128 try
129 {
130 ProjectSegment projectBuild = service.take().get();
131 if ( reactorContext.getReactorBuildStatus().isHalted() )
132 {
133 break;
134 }
135 final List<MavenProject> newItemsThatCanBeBuilt =
136 analyzer.markAsFinished( projectBuild.getProject() );
137 for ( MavenProject mavenProject : newItemsThatCanBeBuilt )
138 {
139 ProjectSegment scheduledDependent = projectBuildList.get( mavenProject );
140 logger.debug( "Scheduling: " + scheduledDependent );
141 Callable<ProjectSegment> cb =
142 createBuildCallable( rootSession, scheduledDependent, reactorContext, taskSegment, muxer );
143 service.submit( cb );
144 }
145 }
146 catch ( InterruptedException e )
147 {
148 rootSession.getResult().addException( e );
149 break;
150 }
151 catch ( ExecutionException e )
152 {
153
154 rootSession.getResult().addException( e );
155 break;
156 }
157 }
158
159
160
161 Future<ProjectSegment> unprocessed;
162 while ( ( unprocessed = service.poll() ) != null )
163 {
164 try
165 {
166 unprocessed.get();
167 }
168 catch ( InterruptedException | ExecutionException e )
169 {
170 throw new RuntimeException( e );
171 }
172 }
173 }
174
175 private Callable<ProjectSegment> createBuildCallable( final MavenSession rootSession,
176 final ProjectSegment projectBuild,
177 final ReactorContext reactorContext,
178 final TaskSegment taskSegment, final ThreadOutputMuxer muxer )
179 {
180 return new Callable<ProjectSegment>()
181 {
182 public ProjectSegment call()
183 {
184
185 lifecycleModuleBuilder.buildProject( projectBuild.getSession(), rootSession, reactorContext,
186 projectBuild.getProject(), taskSegment );
187
188
189 return projectBuild;
190 }
191 };
192 }
193 }