1 | package org.apache.continuum.buildmanager; |
2 | |
3 | /* |
4 | * Licensed to the Apache Software Foundation (ASF) under one |
5 | * or more contributor license agreements. See the NOTICE file |
6 | * distributed with this work for additional information |
7 | * regarding copyright ownership. The ASF licenses this file |
8 | * to you under the Apache License, Version 2.0 (the |
9 | * "License"); you may not use this file except in compliance |
10 | * with the License. You may obtain a copy of the License at |
11 | * |
12 | * http://www.apache.org/licenses/LICENSE-2.0 |
13 | * |
14 | * Unless required by applicable law or agreed to in writing, |
15 | * software distributed under the License is distributed on an |
16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
17 | * KIND, either express or implied. See the License for the |
18 | * specific language governing permissions and limitations |
19 | * under the License. |
20 | */ |
21 | |
22 | import java.io.File; |
23 | import java.util.Collections; |
24 | import java.util.HashMap; |
25 | import java.util.List; |
26 | import java.util.Map; |
27 | import java.util.Set; |
28 | |
29 | import javax.annotation.Resource; |
30 | |
31 | import org.apache.commons.lang.ArrayUtils; |
32 | import org.apache.continuum.buildqueue.BuildQueueService; |
33 | import org.apache.continuum.buildqueue.BuildQueueServiceException; |
34 | import org.apache.continuum.dao.BuildDefinitionDao; |
35 | import org.apache.continuum.dao.ProjectDao; |
36 | import org.apache.continuum.taskqueue.BuildProjectTask; |
37 | import org.apache.continuum.taskqueue.CheckOutTask; |
38 | import org.apache.continuum.taskqueue.OverallBuildQueue; |
39 | import org.apache.continuum.taskqueue.PrepareBuildProjectsTask; |
40 | import org.apache.continuum.taskqueueexecutor.ParallelBuildsThreadedTaskQueueExecutor; |
41 | import org.apache.maven.continuum.configuration.ConfigurationService; |
42 | import org.apache.maven.continuum.model.project.BuildDefinition; |
43 | import org.apache.maven.continuum.model.project.BuildQueue; |
44 | import org.apache.maven.continuum.model.project.Project; |
45 | import org.apache.maven.continuum.model.scm.ScmResult; |
46 | import org.apache.maven.continuum.store.ContinuumStoreException; |
47 | import org.codehaus.plexus.PlexusConstants; |
48 | import org.codehaus.plexus.PlexusContainer; |
49 | import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException; |
50 | import org.codehaus.plexus.component.repository.exception.ComponentLookupException; |
51 | import org.codehaus.plexus.context.Context; |
52 | import org.codehaus.plexus.context.ContextException; |
53 | import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable; |
54 | import org.codehaus.plexus.personality.plexus.lifecycle.phase.StoppingException; |
55 | import org.codehaus.plexus.taskqueue.Task; |
56 | import org.codehaus.plexus.taskqueue.TaskQueue; |
57 | import org.codehaus.plexus.taskqueue.TaskQueueException; |
58 | import org.codehaus.plexus.taskqueue.execution.TaskQueueExecutor; |
59 | import org.codehaus.plexus.util.StringUtils; |
60 | import org.slf4j.Logger; |
61 | import org.slf4j.LoggerFactory; |
62 | |
63 | /** |
64 | * Parallel builds manager. |
65 | * |
66 | * @author <a href="mailto:oching@apache.org">Maria Odea Ching</a> |
67 | * @version $Id$ |
68 | */ |
69 | public class ParallelBuildsManager |
70 | implements BuildsManager, Contextualizable |
71 | { |
72 | private static final Logger log = LoggerFactory.getLogger( ParallelBuildsManager.class ); |
73 | |
74 | // map must be synchronized! |
75 | private Map<Integer, OverallBuildQueue> overallBuildQueues = |
76 | Collections.synchronizedMap( new HashMap<Integer, OverallBuildQueue>() ); |
77 | |
78 | private static final int BUILD_QUEUE = 1; |
79 | |
80 | private static final int CHECKOUT_QUEUE = 2; |
81 | |
82 | @Resource |
83 | private BuildDefinitionDao buildDefinitionDao; |
84 | |
85 | @Resource |
86 | private ProjectDao projectDao; |
87 | |
88 | private TaskQueue prepareBuildQueue; |
89 | |
90 | @Resource |
91 | private ConfigurationService configurationService; |
92 | |
93 | @Resource |
94 | private BuildQueueService buildQueueService; |
95 | |
96 | private PlexusContainer container; |
97 | |
98 | /** |
99 | * @see BuildsManager#buildProject(int, BuildDefinition, String, int, ScmResult, int) |
100 | */ |
101 | public void buildProject( int projectId, BuildDefinition buildDefinition, String projectName, int trigger, |
102 | ScmResult scmResult, int projectGroupId ) |
103 | throws BuildManagerException |
104 | { |
105 | try |
106 | { |
107 | if ( isInQueue( projectId, BUILD_QUEUE, -1 ) ) |
108 | { |
109 | log.warn( "Project already queued." ); |
110 | return; |
111 | } |
112 | else if ( isProjectInAnyCurrentBuild( projectId ) ) |
113 | { |
114 | log.warn( "Project is already building." ); |
115 | return; |
116 | } |
117 | } |
118 | catch ( TaskQueueException e ) |
119 | { |
120 | throw new BuildManagerException( |
121 | "Error occurred while checking if the project is already in queue: " + e.getMessage() ); |
122 | } |
123 | |
124 | OverallBuildQueue overallBuildQueue = getOverallBuildQueueWhereProjectsInGroupAreQueued( projectGroupId ); |
125 | |
126 | if ( overallBuildQueue == null ) |
127 | { |
128 | overallBuildQueue = getOverallBuildQueue( BUILD_QUEUE, buildDefinition.getSchedule().getBuildQueues() ); |
129 | } |
130 | |
131 | if ( overallBuildQueue != null ) |
132 | { |
133 | String buildDefinitionLabel = buildDefinition.getDescription(); |
134 | |
135 | if ( StringUtils.isEmpty( buildDefinitionLabel ) ) |
136 | { |
137 | buildDefinitionLabel = buildDefinition.getGoals(); |
138 | } |
139 | |
140 | BuildProjectTask buildTask = |
141 | new BuildProjectTask( projectId, buildDefinition.getId(), trigger, projectName, buildDefinitionLabel, |
142 | scmResult, projectGroupId ); |
143 | try |
144 | { |
145 | log.info( |
146 | "Project '" + projectName + "' added to overall build queue '" + overallBuildQueue.getName() + "'." ); |
147 | overallBuildQueue.addToBuildQueue( buildTask ); |
148 | } |
149 | catch ( TaskQueueException e ) |
150 | { |
151 | throw new BuildManagerException( "Error occurred while adding project to build queue: " + e.getMessage() ); |
152 | } |
153 | } |
154 | else |
155 | { |
156 | log.warn( "No build queue configured. Not building." ); |
157 | } |
158 | } |
159 | |
160 | /** |
161 | * @see BuildsManager#buildProjects(List, Map, int, Map, int) |
162 | */ |
163 | public void buildProjects( List<Project> projects, Map<Integer, BuildDefinition> projectsBuildDefinitionsMap, |
164 | int trigger, Map<Integer, ScmResult> scmResultMap, int projectGroupId ) |
165 | throws BuildManagerException |
166 | { |
167 | int firstProjectId = 0; |
168 | // get id of the first project in the list that is not yet in the build queue |
169 | for ( Project project : projects ) |
170 | { |
171 | try |
172 | { |
173 | if ( !isInQueue( project.getId(), BUILD_QUEUE, -1 ) && !isProjectInAnyCurrentBuild( project.getId() ) ) |
174 | { |
175 | firstProjectId = project.getId(); |
176 | break; |
177 | } |
178 | } |
179 | catch ( TaskQueueException e ) |
180 | { |
181 | log.warn( "Error occurred while verifying if project is already queued." ); |
182 | } |
183 | } |
184 | |
185 | if ( firstProjectId != 0 ) |
186 | { |
187 | BuildDefinition buildDef = projectsBuildDefinitionsMap.get( firstProjectId ); |
188 | OverallBuildQueue overallBuildQueue = getOverallBuildQueueWhereProjectsInGroupAreQueued( projectGroupId ); |
189 | |
190 | if ( overallBuildQueue == null ) |
191 | { |
192 | overallBuildQueue = getOverallBuildQueue( BUILD_QUEUE, buildDef.getSchedule().getBuildQueues() ); |
193 | } |
194 | |
195 | if ( overallBuildQueue != null ) |
196 | { |
197 | for ( Project project : projects ) |
198 | { |
199 | try |
200 | { |
201 | if ( isInQueue( project.getId(), BUILD_QUEUE, |
202 | projectsBuildDefinitionsMap.get( project.getId() ).getId() ) ) |
203 | { |
204 | log.warn( "Project '" + project.getId() + "' - '" + project.getName() + |
205 | "' is already in build queue." ); |
206 | continue; |
207 | } |
208 | else if ( isProjectInAnyCurrentBuild( project.getId() ) ) |
209 | { |
210 | log.warn( "Project '" + project.getId() + "' - '" + project.getName() + |
211 | "' is already building." ); |
212 | continue; |
213 | } |
214 | } |
215 | catch ( TaskQueueException e ) |
216 | { |
217 | log.warn( "Error occurred while verifying if project is already queued." ); |
218 | continue; |
219 | } |
220 | |
221 | BuildDefinition buildDefinition = projectsBuildDefinitionsMap.get( project.getId() ); |
222 | String buildDefinitionLabel = buildDefinition.getDescription(); |
223 | if ( StringUtils.isEmpty( buildDefinitionLabel ) ) |
224 | { |
225 | buildDefinitionLabel = buildDefinition.getGoals(); |
226 | } |
227 | |
228 | ScmResult scmResult = scmResultMap.get( project.getId() ); |
229 | BuildProjectTask buildTask = |
230 | new BuildProjectTask( project.getId(), buildDefinition.getId(), trigger, project.getName(), |
231 | buildDefinitionLabel, scmResult, projectGroupId ); |
232 | buildTask.setMaxExecutionTime( buildDefinition.getSchedule().getMaxJobExecutionTime() * 1000 ); |
233 | |
234 | try |
235 | { |
236 | log.info( "Project '" + project.getId() + "' - '" + project.getName() + |
237 | "' added to overall build queue '" + overallBuildQueue.getName() + "'." ); |
238 | |
239 | overallBuildQueue.addToBuildQueue( buildTask ); |
240 | } |
241 | catch ( TaskQueueException e ) |
242 | { |
243 | throw new BuildManagerException( |
244 | "Error occurred while adding project to build queue: " + e.getMessage() ); |
245 | } |
246 | } |
247 | } |
248 | else |
249 | { |
250 | log.warn( "No build queue configured. Not building" ); |
251 | } |
252 | } |
253 | else |
254 | { |
255 | log.error( "Projects are already in build queue." ); |
256 | } |
257 | } |
258 | |
259 | /** |
260 | * @see BuildsManager#cancelBuildInQueue(int) |
261 | */ |
262 | public boolean cancelBuildInQueue( int buildQueueId ) |
263 | throws BuildManagerException |
264 | { |
265 | synchronized ( overallBuildQueues ) |
266 | { |
267 | OverallBuildQueue overallBuildQueue; |
268 | overallBuildQueue = overallBuildQueues.get( buildQueueId ); |
269 | if ( overallBuildQueue != null ) |
270 | { |
271 | overallBuildQueue.cancelCurrentBuild(); |
272 | } |
273 | else |
274 | { |
275 | log.warn( "Project not found in any of the build queues." ); |
276 | } |
277 | |
278 | return true; |
279 | } |
280 | } |
281 | |
282 | /** |
283 | * @see BuildsManager#cancelAllBuilds() |
284 | */ |
285 | public boolean cancelAllBuilds() |
286 | throws BuildManagerException |
287 | { |
288 | synchronized ( overallBuildQueues ) |
289 | { |
290 | Set<Integer> keySet = overallBuildQueues.keySet(); |
291 | OverallBuildQueue overallBuildQueue = null; |
292 | for ( Integer key : keySet ) |
293 | { |
294 | overallBuildQueue = overallBuildQueues.get( key ); |
295 | overallBuildQueue.cancelCurrentBuild(); |
296 | } |
297 | |
298 | return true; |
299 | } |
300 | } |
301 | |
302 | /** |
303 | * @see BuildsManager#cancelAllCheckouts() |
304 | */ |
305 | public boolean cancelAllCheckouts() |
306 | throws BuildManagerException |
307 | { |
308 | synchronized ( overallBuildQueues ) |
309 | { |
310 | Set<Integer> keySet = overallBuildQueues.keySet(); |
311 | OverallBuildQueue overallBuildQueue; |
312 | for ( Integer key : keySet ) |
313 | { |
314 | overallBuildQueue = overallBuildQueues.get( key ); |
315 | overallBuildQueue.cancelCurrentCheckout(); |
316 | } |
317 | |
318 | return true; |
319 | } |
320 | } |
321 | |
322 | /** |
323 | * @see BuildsManager#cancelBuild(int) |
324 | */ |
325 | public boolean cancelBuild( int projectId ) |
326 | throws BuildManagerException |
327 | { |
328 | try |
329 | { |
330 | OverallBuildQueue overallBuildQueue = getOverallBuildQueueWhereProjectIsQueued( projectId, BUILD_QUEUE ); |
331 | if ( overallBuildQueue != null ) |
332 | { |
333 | overallBuildQueue.cancelBuildTask( projectId ); |
334 | } |
335 | else |
336 | { |
337 | synchronized ( overallBuildQueues ) |
338 | { |
339 | Set<Integer> keySet = overallBuildQueues.keySet(); |
340 | for ( Integer key : keySet ) |
341 | { |
342 | overallBuildQueue = overallBuildQueues.get( key ); |
343 | BuildProjectTask buildTask = |
344 | (BuildProjectTask) overallBuildQueue.getBuildTaskQueueExecutor().getCurrentTask(); |
345 | if ( buildTask != null && buildTask.getProjectId() == projectId ) |
346 | { |
347 | overallBuildQueue.cancelBuildTask( projectId ); |
348 | return true; |
349 | } |
350 | } |
351 | log.error( "Project '" + projectId + "' not found in any of the builds queues." ); |
352 | } |
353 | } |
354 | } |
355 | catch ( TaskQueueException e ) |
356 | { |
357 | throw new BuildManagerException( "Error occurred while cancelling build: " + e.getMessage() ); |
358 | } |
359 | |
360 | return true; |
361 | } |
362 | |
363 | /** |
364 | * @see BuildsManager#cancelCheckout(int) |
365 | */ |
366 | public boolean cancelCheckout( int projectId ) |
367 | throws BuildManagerException |
368 | { |
369 | try |
370 | { |
371 | OverallBuildQueue overallBuildQueue = getOverallBuildQueueWhereProjectIsQueued( projectId, CHECKOUT_QUEUE ); |
372 | if ( overallBuildQueue != null ) |
373 | { |
374 | overallBuildQueue.cancelCheckoutTask( projectId ); |
375 | } |
376 | else |
377 | { |
378 | synchronized ( overallBuildQueues ) |
379 | { |
380 | Set<Integer> keySet = overallBuildQueues.keySet(); |
381 | for ( Integer key : keySet ) |
382 | { |
383 | overallBuildQueue = overallBuildQueues.get( key ); |
384 | CheckOutTask checkoutTask = |
385 | (CheckOutTask) overallBuildQueue.getCheckoutTaskQueueExecutor().getCurrentTask(); |
386 | if ( checkoutTask != null && checkoutTask.getProjectId() == projectId ) |
387 | { |
388 | overallBuildQueue.cancelCheckoutTask( projectId ); |
389 | return true; |
390 | } |
391 | } |
392 | log.info( "Project '" + projectId + "' not found in any of the checkout queues." ); |
393 | } |
394 | } |
395 | } |
396 | catch ( TaskQueueException e ) |
397 | { |
398 | throw new BuildManagerException( "Error occurred while cancelling build: " + e.getMessage() ); |
399 | } |
400 | |
401 | return true; |
402 | } |
403 | |
404 | /** |
405 | * @see BuildsManager#checkoutProject(int, String, File, String, String, BuildDefinition) |
406 | */ |
407 | public void checkoutProject( int projectId, String projectName, File workingDirectory, String scmUsername, |
408 | String scmPassword, BuildDefinition defaultBuildDefinition ) |
409 | throws BuildManagerException |
410 | { |
411 | try |
412 | { |
413 | if ( isInQueue( projectId, CHECKOUT_QUEUE, -1 ) ) |
414 | { |
415 | log.warn( "Project already in checkout queue." ); |
416 | return; |
417 | } |
418 | } |
419 | catch ( TaskQueueException e ) |
420 | { |
421 | throw new BuildManagerException( |
422 | "Error occurred while checking if the project is already in queue: " + e.getMessage() ); |
423 | } |
424 | |
425 | OverallBuildQueue overallBuildQueue = |
426 | getOverallBuildQueue( CHECKOUT_QUEUE, defaultBuildDefinition.getSchedule().getBuildQueues() ); |
427 | CheckOutTask checkoutTask = |
428 | new CheckOutTask( projectId, workingDirectory, projectName, scmUsername, scmPassword ); |
429 | try |
430 | { |
431 | if ( overallBuildQueue != null ) |
432 | { |
433 | log.info( "Project '" + projectName + "' added to overall build queue '" + overallBuildQueue.getName() + |
434 | "'." ); |
435 | overallBuildQueue.addToCheckoutQueue( checkoutTask ); |
436 | } |
437 | else |
438 | { |
439 | throw new BuildManagerException( |
440 | "Unable to add project to checkout queue. No overall build queue configured." ); |
441 | } |
442 | } |
443 | catch ( TaskQueueException e ) |
444 | { |
445 | throw new BuildManagerException( |
446 | "Error occurred while adding project to checkout queue: " + e.getMessage() ); |
447 | } |
448 | } |
449 | |
450 | /** |
451 | * @see BuildsManager#isInAnyBuildQueue(int) |
452 | */ |
453 | public boolean isInAnyBuildQueue( int projectId ) |
454 | throws BuildManagerException |
455 | { |
456 | try |
457 | { |
458 | return isInQueue( projectId, BUILD_QUEUE, -1 ); |
459 | } |
460 | catch ( TaskQueueException e ) |
461 | { |
462 | throw new BuildManagerException( e.getMessage() ); |
463 | } |
464 | } |
465 | |
466 | /** |
467 | * @see BuildsManager#isInAnyBuildQueue(int, int) |
468 | */ |
469 | public boolean isInAnyBuildQueue( int projectId, int buildDefinitionId ) |
470 | throws BuildManagerException |
471 | { |
472 | try |
473 | { |
474 | return isInQueue( projectId, BUILD_QUEUE, buildDefinitionId ); |
475 | } |
476 | catch ( TaskQueueException e ) |
477 | { |
478 | throw new BuildManagerException( e.getMessage() ); |
479 | } |
480 | } |
481 | |
482 | /** |
483 | * @see BuildsManager#isInAnyCheckoutQueue(int) |
484 | */ |
485 | public boolean isInAnyCheckoutQueue( int projectId ) |
486 | throws BuildManagerException |
487 | { |
488 | try |
489 | { |
490 | return isInQueue( projectId, CHECKOUT_QUEUE, -1 ); |
491 | } |
492 | catch ( TaskQueueException e ) |
493 | { |
494 | throw new BuildManagerException( e.getMessage() ); |
495 | } |
496 | } |
497 | |
498 | /** |
499 | * @see BuildsManager#isAnyProjectCurrentlyBeingCheckedOut(int[]) |
500 | */ |
501 | public boolean isAnyProjectCurrentlyBeingCheckedOut( int[] projectIds ) |
502 | throws BuildManagerException |
503 | { |
504 | for ( int projectId : projectIds ) |
505 | { |
506 | Map<String, CheckOutTask> checkouts = getCurrentCheckouts(); |
507 | Set<String> keySet = checkouts.keySet(); |
508 | for ( String key : keySet ) |
509 | { |
510 | CheckOutTask task = checkouts.get( key ); |
511 | if ( task.getProjectId() == projectId ) |
512 | { |
513 | log.info( "Project " + projectId + " is currently being checked out" ); |
514 | return true; |
515 | } |
516 | } |
517 | } |
518 | return false; |
519 | } |
520 | |
521 | /** |
522 | * @see BuildsManager#isInPrepareBuildQueue(int) |
523 | */ |
524 | public boolean isInPrepareBuildQueue( int projectId ) |
525 | throws BuildManagerException |
526 | { |
527 | try |
528 | { |
529 | List<PrepareBuildProjectsTask> queue = prepareBuildQueue.getQueueSnapshot(); |
530 | for ( PrepareBuildProjectsTask task : queue ) |
531 | { |
532 | if ( task != null ) |
533 | { |
534 | Map<Integer, Integer> map = task.getProjectsBuildDefinitionsMap(); |
535 | |
536 | if ( map.size() > 0 ) |
537 | { |
538 | Set<Integer> projectIds = map.keySet(); |
539 | |
540 | if ( projectIds.contains( new Integer( projectId ) ) ) |
541 | { |
542 | log.info( "Project " + projectId + " is in prepare build queue" ); |
543 | return true; |
544 | } |
545 | } |
546 | } |
547 | } |
548 | } |
549 | catch ( TaskQueueException e ) |
550 | { |
551 | throw new BuildManagerException( e.getMessage() ); |
552 | } |
553 | |
554 | return false; |
555 | } |
556 | |
557 | /** |
558 | * @see BuildsManager#isProjectInAnyCurrentBuild(int) |
559 | */ |
560 | public boolean isProjectInAnyCurrentBuild( int projectId ) |
561 | throws BuildManagerException |
562 | { |
563 | synchronized ( overallBuildQueues ) |
564 | { |
565 | Set<Integer> keys = overallBuildQueues.keySet(); |
566 | for ( Integer key : keys ) |
567 | { |
568 | OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key ); |
569 | BuildProjectTask task = |
570 | (BuildProjectTask) overallBuildQueue.getBuildTaskQueueExecutor().getCurrentTask(); |
571 | if ( task != null && task.getProjectId() == projectId ) |
572 | { |
573 | log.info( "Project " + projectId + " is currently building in " + overallBuildQueue.getName() ); |
574 | return true; |
575 | } |
576 | } |
577 | return false; |
578 | } |
579 | } |
580 | |
581 | /** |
582 | * @see BuildsManager#prepareBuildProjects(Map, int, int, String, String, int) |
583 | */ |
584 | public void prepareBuildProjects( Map<Integer, Integer> projectsBuildDefinitionsMap, int trigger, |
585 | int projectGroupId, String projectGroupName, String scmRootAddress, |
586 | int scmRootId ) |
587 | throws BuildManagerException |
588 | { |
589 | try |
590 | { |
591 | PrepareBuildProjectsTask task = |
592 | new PrepareBuildProjectsTask( projectsBuildDefinitionsMap, trigger, projectGroupId, projectGroupName, |
593 | scmRootAddress, scmRootId ); |
594 | |
595 | log.info( "Queueing prepare-build-project task '" + task + "' to prepare-build queue." ); |
596 | prepareBuildQueue.put( task ); |
597 | } |
598 | catch ( TaskQueueException e ) |
599 | { |
600 | throw new BuildManagerException( |
601 | "Error occurred while creating prepare-build-project task: " + e.getMessage() ); |
602 | } |
603 | } |
604 | |
605 | /** |
606 | * @see BuildsManager#removeProjectFromBuildQueue(int) |
607 | */ |
608 | public void removeProjectFromBuildQueue( int projectId ) |
609 | throws BuildManagerException |
610 | { |
611 | try |
612 | { |
613 | OverallBuildQueue overallBuildQueue = getOverallBuildQueueWhereProjectIsQueued( projectId, BUILD_QUEUE ); |
614 | if ( overallBuildQueue != null ) |
615 | { |
616 | overallBuildQueue.removeProjectFromBuildQueue( projectId ); |
617 | } |
618 | else |
619 | { |
620 | log.info( "Project '" + projectId + "' not found in any of the build queues." ); |
621 | } |
622 | } |
623 | catch ( TaskQueueException e ) |
624 | { |
625 | throw new BuildManagerException( |
626 | "Error occurred while removing project from build queue: " + e.getMessage() ); |
627 | } |
628 | } |
629 | |
630 | /** |
631 | * @see BuildsManager#removeProjectFromBuildQueue(int, int, int, String) |
632 | */ |
633 | public void removeProjectFromBuildQueue( int projectId, int buildDefinitionId, int trigger, String projectName, |
634 | int projectGroupId ) |
635 | throws BuildManagerException |
636 | { |
637 | try |
638 | { |
639 | OverallBuildQueue overallBuildQueue = getOverallBuildQueueWhereProjectIsQueued( projectId, BUILD_QUEUE ); |
640 | if ( overallBuildQueue != null ) |
641 | { |
642 | overallBuildQueue.removeProjectFromBuildQueue( projectId, buildDefinitionId, trigger, projectName, |
643 | projectGroupId ); |
644 | } |
645 | else |
646 | { |
647 | log.info( "Project '" + projectId + "' not found in any of the build queues." ); |
648 | } |
649 | } |
650 | catch ( TaskQueueException e ) |
651 | { |
652 | throw new BuildManagerException( |
653 | "Error occurred while removing project from build queue: " + e.getMessage() ); |
654 | } |
655 | } |
656 | |
657 | /** |
658 | * @see BuildsManager#removeProjectFromCheckoutQueue(int) |
659 | */ |
660 | public void removeProjectFromCheckoutQueue( int projectId ) |
661 | throws BuildManagerException |
662 | { |
663 | try |
664 | { |
665 | OverallBuildQueue overallBuildQueue = getOverallBuildQueueWhereProjectIsQueued( projectId, CHECKOUT_QUEUE ); |
666 | if ( overallBuildQueue != null ) |
667 | { |
668 | overallBuildQueue.removeProjectFromCheckoutQueue( projectId ); |
669 | } |
670 | else |
671 | { |
672 | log.info( "Project '" + projectId + "' not found in any of the checkout queues." ); |
673 | } |
674 | } |
675 | catch ( TaskQueueException e ) |
676 | { |
677 | throw new BuildManagerException( |
678 | "Error occurred while removing project from checkout queue: " + e.getMessage() ); |
679 | } |
680 | } |
681 | |
682 | /** |
683 | * @see BuildsManager#removeProjectsFromBuildQueue(int[]) |
684 | */ |
685 | public void removeProjectsFromBuildQueue( int[] projectIds ) |
686 | { |
687 | for ( int projectId : projectIds ) |
688 | { |
689 | try |
690 | { |
691 | OverallBuildQueue overallBuildQueue = getOverallBuildQueueWhereProjectIsQueued( projectId, BUILD_QUEUE ) |
692 | ; |
693 | if ( overallBuildQueue != null ) |
694 | { |
695 | overallBuildQueue.removeProjectFromBuildQueue( projectId ); |
696 | } |
697 | else |
698 | { |
699 | log.error( "Project '" + projectId + "' not found in any of the build queues." ); |
700 | } |
701 | } |
702 | catch ( TaskQueueException e ) |
703 | { |
704 | log.error( "Error occurred while removing project '" + projectId + "' from build queue." ); |
705 | } |
706 | } |
707 | } |
708 | |
709 | /** |
710 | * @see BuildsManager#removeProjectsFromCheckoutQueue(int[]) |
711 | */ |
712 | public void removeProjectsFromCheckoutQueue( int[] projectIds ) |
713 | { |
714 | for ( int projectId : projectIds ) |
715 | { |
716 | try |
717 | { |
718 | OverallBuildQueue overallBuildQueue = |
719 | getOverallBuildQueueWhereProjectIsQueued( projectId, CHECKOUT_QUEUE ); |
720 | if ( overallBuildQueue != null ) |
721 | { |
722 | overallBuildQueue.removeProjectFromCheckoutQueue( projectId ); |
723 | } |
724 | else |
725 | { |
726 | log.error( "Project '" + projectId + "' not found in any of the checkout queues." ); |
727 | } |
728 | } |
729 | catch ( TaskQueueException e ) |
730 | { |
731 | log.error( "Error occurred while removing project '" + projectId + "' from checkout queue." ); |
732 | } |
733 | } |
734 | } |
735 | |
736 | /** |
737 | * @see BuildsManager#removeProjectsFromCheckoutQueueWithHashcodes(int[]) |
738 | */ |
739 | public void removeProjectsFromCheckoutQueueWithHashcodes( int[] hashcodes ) |
740 | throws BuildManagerException |
741 | { |
742 | try |
743 | { |
744 | synchronized ( overallBuildQueues ) |
745 | { |
746 | Set<Integer> keySet = overallBuildQueues.keySet(); |
747 | for ( Integer key : keySet ) |
748 | { |
749 | OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key ); |
750 | overallBuildQueue.removeTasksFromCheckoutQueueWithHashCodes( hashcodes ); |
751 | } |
752 | } |
753 | } |
754 | catch ( TaskQueueException e ) |
755 | { |
756 | throw new BuildManagerException( "Error encountered while removing project(s) from checkout queue.", e ); |
757 | } |
758 | } |
759 | |
760 | /** |
761 | * @see BuildsManager#removeProjectsFromBuildQueueWithHashcodes(int[]) |
762 | */ |
763 | public void removeProjectsFromBuildQueueWithHashcodes( int[] hashcodes ) |
764 | throws BuildManagerException |
765 | { |
766 | try |
767 | { |
768 | synchronized ( overallBuildQueues ) |
769 | { |
770 | Set<Integer> keySet = overallBuildQueues.keySet(); |
771 | for ( Integer key : keySet ) |
772 | { |
773 | OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key ); |
774 | overallBuildQueue.removeProjectsFromBuildQueueWithHashCodes( hashcodes ); |
775 | } |
776 | } |
777 | } |
778 | catch ( TaskQueueException e ) |
779 | { |
780 | throw new BuildManagerException( "Error encountered while removing project(s) from build queue.", e ); |
781 | } |
782 | } |
783 | |
784 | public boolean removeProjectGroupFromPrepareBuildQueue( int projectGroupId, String scmRootAddress ) |
785 | throws BuildManagerException |
786 | { |
787 | try |
788 | { |
789 | List<PrepareBuildProjectsTask> queue = prepareBuildQueue.getQueueSnapshot(); |
790 | |
791 | for ( PrepareBuildProjectsTask task : queue ) |
792 | { |
793 | if ( task != null && task.getProjectGroupId() == projectGroupId && |
794 | task.getScmRootAddress().equals( scmRootAddress ) ) |
795 | { |
796 | return prepareBuildQueue.remove( task ); |
797 | } |
798 | } |
799 | return false; |
800 | } |
801 | catch ( TaskQueueException e ) |
802 | { |
803 | throw new BuildManagerException( "Error while getting the prepare build projects task in queue", e ); |
804 | } |
805 | } |
806 | |
807 | /** |
808 | * @see BuildsManager#addOverallBuildQueue(BuildQueue) |
809 | */ |
810 | public void addOverallBuildQueue( BuildQueue buildQueue ) |
811 | throws BuildManagerException |
812 | { |
813 | synchronized ( overallBuildQueues ) |
814 | { |
815 | try |
816 | { |
817 | OverallBuildQueue overallBuildQueue = (OverallBuildQueue) container.lookup( OverallBuildQueue.class ); |
818 | overallBuildQueue.setId( buildQueue.getId() ); |
819 | overallBuildQueue.setName( buildQueue.getName() ); |
820 | |
821 | if ( overallBuildQueues.get( buildQueue.getId() ) == null ) |
822 | { |
823 | log.info( "Adding overall build queue to map : " + overallBuildQueue.getName() ); |
824 | overallBuildQueues.put( overallBuildQueue.getId(), overallBuildQueue ); |
825 | } |
826 | else |
827 | { |
828 | log.warn( "Overall build queue already in the map." ); |
829 | } |
830 | } |
831 | catch ( ComponentLookupException e ) |
832 | { |
833 | throw new BuildManagerException( "Error creating overall build queue.", e ); |
834 | } |
835 | } |
836 | } |
837 | |
838 | /** |
839 | * @see BuildsManager#removeOverallBuildQueue(int) |
840 | */ |
841 | public void removeOverallBuildQueue( int overallBuildQueueId ) |
842 | throws BuildManagerException |
843 | { |
844 | List<BuildProjectTask> tasks; |
845 | List<CheckOutTask> checkoutTasks; |
846 | |
847 | synchronized ( overallBuildQueues ) |
848 | { |
849 | OverallBuildQueue overallBuildQueue = overallBuildQueues.get( overallBuildQueueId ); |
850 | if ( overallBuildQueue.getName().equals( ConfigurationService.DEFAULT_BUILD_QUEUE_NAME ) ) |
851 | { |
852 | throw new BuildManagerException( "Cannot remove default build queue." ); |
853 | } |
854 | |
855 | try |
856 | { |
857 | if ( overallBuildQueue.getBuildTaskQueueExecutor().getCurrentTask() != null || |
858 | overallBuildQueue.getCheckoutTaskQueueExecutor().getCurrentTask() != null ) |
859 | { |
860 | throw new BuildManagerException( "Cannot remove build queue. A task is currently executing." ); |
861 | } |
862 | |
863 | tasks = overallBuildQueue.getProjectsInBuildQueue(); |
864 | checkoutTasks = overallBuildQueue.getProjectsInCheckoutQueue(); |
865 | |
866 | overallBuildQueue.getBuildQueue().removeAll( tasks ); |
867 | overallBuildQueue.getCheckoutQueue().removeAll( checkoutTasks ); |
868 | |
869 | ( (ParallelBuildsThreadedTaskQueueExecutor) overallBuildQueue.getBuildTaskQueueExecutor() ).stop(); |
870 | ( (ParallelBuildsThreadedTaskQueueExecutor) overallBuildQueue.getCheckoutTaskQueueExecutor() ).stop(); |
871 | container.release( overallBuildQueue ); |
872 | } |
873 | catch ( TaskQueueException e ) |
874 | { |
875 | throw new BuildManagerException( |
876 | "Cannot remove build queue. An error occurred while retrieving queued tasks." ); |
877 | } |
878 | catch ( ComponentLifecycleException e ) |
879 | { |
880 | throw new BuildManagerException( |
881 | "Cannot remove build queue. An error occurred while destroying the build queue: " + |
882 | e.getMessage() ); |
883 | } |
884 | catch ( StoppingException e ) |
885 | { |
886 | throw new BuildManagerException( |
887 | "Cannot remove build queue. An error occurred while stopping the build queue: " + e.getMessage() ); |
888 | } |
889 | |
890 | this.overallBuildQueues.remove( overallBuildQueueId ); |
891 | log.info( "Removed overall build queue '" + overallBuildQueueId + "' from build queues map." ); |
892 | } |
893 | |
894 | for ( BuildProjectTask buildTask : tasks ) |
895 | { |
896 | try |
897 | { |
898 | BuildDefinition buildDefinition = |
899 | buildDefinitionDao.getBuildDefinition( buildTask.getBuildDefinitionId() ); |
900 | |
901 | buildProject( buildTask.getProjectId(), buildDefinition, buildTask.getProjectName(), |
902 | buildTask.getTrigger(), buildTask.getScmResult(), buildTask.getProjectGroupId() ); |
903 | } |
904 | catch ( ContinuumStoreException e ) |
905 | { |
906 | log.error( "Unable to queue build task for project '" + buildTask.getProjectName() + "'" ); |
907 | } |
908 | } |
909 | |
910 | for ( CheckOutTask task : checkoutTasks ) |
911 | { |
912 | try |
913 | { |
914 | BuildDefinition buildDefinition = buildDefinitionDao.getDefaultBuildDefinition( task.getProjectId() ); |
915 | checkoutProject( task.getProjectId(), task.getProjectName(), task.getWorkingDirectory(), |
916 | task.getScmUserName(), task.getScmPassword(), buildDefinition ); |
917 | } |
918 | catch ( ContinuumStoreException e ) |
919 | { |
920 | log.error( "Unable to queue checkout task for project '" + task.getProjectName() + "'" ); |
921 | } |
922 | } |
923 | } |
924 | |
925 | public Map<Integer, OverallBuildQueue> getOverallBuildQueues() |
926 | { |
927 | return overallBuildQueues; |
928 | } |
929 | |
930 | /** |
931 | * @see BuildsManager#getCurrentBuilds() |
932 | */ |
933 | public Map<String, BuildProjectTask> getCurrentBuilds() |
934 | throws BuildManagerException |
935 | { |
936 | synchronized ( overallBuildQueues ) |
937 | { |
938 | Map<String, BuildProjectTask> currentBuilds = new HashMap<String, BuildProjectTask>(); |
939 | Set<Integer> keys = overallBuildQueues.keySet(); |
940 | for ( Integer key : keys ) |
941 | { |
942 | OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key ); |
943 | BuildProjectTask task = |
944 | (BuildProjectTask) overallBuildQueue.getBuildTaskQueueExecutor().getCurrentTask(); |
945 | if ( task != null ) |
946 | { |
947 | currentBuilds.put( overallBuildQueue.getName(), task ); |
948 | } |
949 | } |
950 | return currentBuilds; |
951 | } |
952 | } |
953 | |
954 | /** |
955 | * @see BuildsManager#getCurrentCheckouts() |
956 | */ |
957 | public Map<String, CheckOutTask> getCurrentCheckouts() |
958 | throws BuildManagerException |
959 | { |
960 | synchronized ( overallBuildQueues ) |
961 | { |
962 | Map<String, CheckOutTask> currentCheckouts = new HashMap<String, CheckOutTask>(); |
963 | Set<Integer> keys = overallBuildQueues.keySet(); |
964 | for ( Integer key : keys ) |
965 | { |
966 | OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key ); |
967 | CheckOutTask task = (CheckOutTask) overallBuildQueue.getCheckoutTaskQueueExecutor().getCurrentTask(); |
968 | if ( task != null ) |
969 | { |
970 | currentCheckouts.put( overallBuildQueue.getName(), task ); |
971 | } |
972 | } |
973 | return currentCheckouts; |
974 | } |
975 | } |
976 | |
977 | /** |
978 | * @see BuildsManager#getProjectsInBuildQueues() |
979 | */ |
980 | public Map<String, List<BuildProjectTask>> getProjectsInBuildQueues() |
981 | throws BuildManagerException |
982 | { |
983 | synchronized ( overallBuildQueues ) |
984 | { |
985 | Map<String, List<BuildProjectTask>> queuedBuilds = new HashMap<String, List<BuildProjectTask>>(); |
986 | Set<Integer> keySet = overallBuildQueues.keySet(); |
987 | for ( Integer key : keySet ) |
988 | { |
989 | OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key ); |
990 | try |
991 | { |
992 | queuedBuilds.put( overallBuildQueue.getName(), overallBuildQueue.getProjectsInBuildQueue() ); |
993 | } |
994 | catch ( TaskQueueException e ) |
995 | { |
996 | throw new BuildManagerException( |
997 | "Error occurred while getting projects in build queue '" + overallBuildQueue.getName() + "'.", |
998 | e ); |
999 | } |
1000 | } |
1001 | return queuedBuilds; |
1002 | } |
1003 | } |
1004 | |
1005 | /** |
1006 | * @see BuildsManager#getProjectsInCheckoutQueues() |
1007 | */ |
1008 | public Map<String, List<CheckOutTask>> getProjectsInCheckoutQueues() |
1009 | throws BuildManagerException |
1010 | { |
1011 | synchronized ( overallBuildQueues ) |
1012 | { |
1013 | Map<String, List<CheckOutTask>> queuedCheckouts = new HashMap<String, List<CheckOutTask>>(); |
1014 | Set<Integer> keySet = overallBuildQueues.keySet(); |
1015 | for ( Integer key : keySet ) |
1016 | { |
1017 | OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key ); |
1018 | try |
1019 | { |
1020 | queuedCheckouts.put( overallBuildQueue.getName(), overallBuildQueue.getProjectsInCheckoutQueue() ); |
1021 | } |
1022 | catch ( TaskQueueException e ) |
1023 | { |
1024 | throw new BuildManagerException( |
1025 | "Error occurred while getting projects in build queue '" + overallBuildQueue.getName() + "'.", |
1026 | e ); |
1027 | } |
1028 | } |
1029 | return queuedCheckouts; |
1030 | } |
1031 | } |
1032 | |
1033 | /** |
1034 | * @see BuildsManager#cancelAllPrepareBuilds() |
1035 | */ |
1036 | public boolean cancelAllPrepareBuilds() |
1037 | throws BuildManagerException |
1038 | { |
1039 | try |
1040 | { |
1041 | TaskQueueExecutor executor = |
1042 | (TaskQueueExecutor) container.lookup( TaskQueueExecutor.class, "prepare-build-project" ); |
1043 | Task task = executor.getCurrentTask(); |
1044 | if ( task != null ) |
1045 | { |
1046 | executor.cancelTask( task ); |
1047 | } |
1048 | } |
1049 | catch ( ComponentLookupException e ) |
1050 | { |
1051 | throw new BuildManagerException( "Error looking up prepare-build-queue.", e ); |
1052 | } |
1053 | |
1054 | return false; |
1055 | } |
1056 | |
1057 | /** |
1058 | * @see BuildsManager#isBuildInProgress() |
1059 | */ |
1060 | public boolean isBuildInProgress() |
1061 | { |
1062 | synchronized ( overallBuildQueues ) |
1063 | { |
1064 | Set<Integer> keySet = overallBuildQueues.keySet(); |
1065 | for ( Integer key : keySet ) |
1066 | { |
1067 | OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key ); |
1068 | if ( overallBuildQueue.getBuildTaskQueueExecutor().getCurrentTask() != null ) |
1069 | { |
1070 | return true; |
1071 | } |
1072 | } |
1073 | return false; |
1074 | } |
1075 | } |
1076 | |
1077 | public boolean isProjectCurrentlyPreparingBuild( int projectId ) |
1078 | throws BuildManagerException |
1079 | { |
1080 | PrepareBuildProjectsTask task = getCurrentProjectInPrepareBuild(); |
1081 | |
1082 | if ( task != null ) |
1083 | { |
1084 | Map<Integer, Integer> map = task.getProjectsBuildDefinitionsMap(); |
1085 | |
1086 | if ( map.size() > 0 ) |
1087 | { |
1088 | Set<Integer> projectIds = map.keySet(); |
1089 | |
1090 | if ( projectIds.contains( new Integer( projectId ) ) ) |
1091 | { |
1092 | log.info( "Project " + projectId + " is currently preparing build" ); |
1093 | return true; |
1094 | } |
1095 | } |
1096 | } |
1097 | |
1098 | return false; |
1099 | } |
1100 | |
1101 | public PrepareBuildProjectsTask getCurrentProjectInPrepareBuild() |
1102 | throws BuildManagerException |
1103 | { |
1104 | Task task = getPrepareBuildTaskQueueExecutor().getCurrentTask(); |
1105 | |
1106 | if ( task != null ) |
1107 | { |
1108 | return (PrepareBuildProjectsTask) task; |
1109 | } |
1110 | else |
1111 | { |
1112 | return null; |
1113 | } |
1114 | } |
1115 | |
1116 | public List<PrepareBuildProjectsTask> getProjectsInPrepareBuildQueue() |
1117 | throws BuildManagerException |
1118 | { |
1119 | try |
1120 | { |
1121 | return getPrepareBuildQueue().getQueueSnapshot(); |
1122 | } |
1123 | catch ( TaskQueueException e ) |
1124 | { |
1125 | throw new BuildManagerException( "Error occurred while retrieving projects in prepare build queue", e ); |
1126 | } |
1127 | } |
1128 | |
1129 | public boolean removeProjectFromPrepareBuildQueue( int projectGroupId, int scmRootId ) |
1130 | throws BuildManagerException |
1131 | { |
1132 | List<PrepareBuildProjectsTask> tasks = getProjectsInPrepareBuildQueue(); |
1133 | |
1134 | if ( tasks != null ) |
1135 | { |
1136 | for ( PrepareBuildProjectsTask task : tasks ) |
1137 | { |
1138 | if ( task.getProjectGroupId() == projectGroupId && task.getProjectScmRootId() == scmRootId ) |
1139 | { |
1140 | return getPrepareBuildQueue().remove( task ); |
1141 | } |
1142 | } |
1143 | } |
1144 | |
1145 | return false; |
1146 | } |
1147 | |
1148 | public void removeProjectsFromPrepareBuildQueueWithHashCodes( int[] hashCodes ) |
1149 | throws BuildManagerException |
1150 | { |
1151 | List<PrepareBuildProjectsTask> tasks = getProjectsInPrepareBuildQueue(); |
1152 | |
1153 | if ( tasks != null ) |
1154 | { |
1155 | for ( PrepareBuildProjectsTask task : tasks ) |
1156 | { |
1157 | if ( ArrayUtils.contains( hashCodes, task.getHashCode() ) ) |
1158 | { |
1159 | getPrepareBuildQueue().remove( task ); |
1160 | } |
1161 | } |
1162 | } |
1163 | } |
1164 | |
1165 | private boolean isInQueue( int projectId, int typeOfQueue, int buildDefinitionId ) |
1166 | throws TaskQueueException |
1167 | { |
1168 | synchronized ( overallBuildQueues ) |
1169 | { |
1170 | Set<Integer> keySet = overallBuildQueues.keySet(); |
1171 | for ( Integer key : keySet ) |
1172 | { |
1173 | OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key ); |
1174 | if ( typeOfQueue == BUILD_QUEUE ) |
1175 | { |
1176 | if ( buildDefinitionId < 0 ) |
1177 | { |
1178 | if ( overallBuildQueue.isInBuildQueue( projectId ) ) |
1179 | { |
1180 | log.info( "Project " + projectId + " is in build queue " + overallBuildQueue.getName() ); |
1181 | return true; |
1182 | } |
1183 | } |
1184 | else |
1185 | { |
1186 | if ( overallBuildQueue.isInBuildQueue( projectId, buildDefinitionId ) ) |
1187 | { |
1188 | log.info( "Project " + projectId + " is in build queue " + overallBuildQueue.getName() ); |
1189 | return true; |
1190 | } |
1191 | } |
1192 | } |
1193 | else if ( typeOfQueue == CHECKOUT_QUEUE ) |
1194 | { |
1195 | if ( overallBuildQueue.isInCheckoutQueue( projectId ) ) |
1196 | { |
1197 | log.info( "Project " + projectId + " is in checkout queue " + overallBuildQueue.getName() ); |
1198 | return true; |
1199 | } |
1200 | } |
1201 | } |
1202 | |
1203 | return false; |
1204 | } |
1205 | } |
1206 | |
1207 | // get overall queue where project is queued |
1208 | private OverallBuildQueue getOverallBuildQueueWhereProjectIsQueued( int projectId, int typeOfQueue ) |
1209 | throws TaskQueueException |
1210 | { |
1211 | synchronized ( overallBuildQueues ) |
1212 | { |
1213 | OverallBuildQueue whereQueued = null; |
1214 | Set<Integer> keySet = overallBuildQueues.keySet(); |
1215 | |
1216 | for ( Integer key : keySet ) |
1217 | { |
1218 | OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key ); |
1219 | if ( typeOfQueue == BUILD_QUEUE ) |
1220 | { |
1221 | if ( overallBuildQueue.isInBuildQueue( projectId ) ) |
1222 | { |
1223 | whereQueued = overallBuildQueue; |
1224 | break; |
1225 | } |
1226 | } |
1227 | else if ( typeOfQueue == CHECKOUT_QUEUE ) |
1228 | { |
1229 | if ( overallBuildQueue.isInCheckoutQueue( projectId ) ) |
1230 | { |
1231 | whereQueued = overallBuildQueue; |
1232 | break; |
1233 | } |
1234 | } |
1235 | } |
1236 | |
1237 | return whereQueued; |
1238 | } |
1239 | } |
1240 | |
1241 | // get overall queue where project will be queued |
1242 | private OverallBuildQueue getOverallBuildQueue( int typeOfQueue, List<BuildQueue> buildQueues ) |
1243 | throws BuildManagerException |
1244 | { |
1245 | OverallBuildQueue whereToBeQueued = null; |
1246 | synchronized ( overallBuildQueues ) |
1247 | { |
1248 | if ( overallBuildQueues == null || overallBuildQueues.isEmpty() ) |
1249 | { |
1250 | throw new BuildManagerException( "No build queues configured." ); |
1251 | } |
1252 | |
1253 | int size = 0; |
1254 | int idx = 0; |
1255 | int allowedBuilds = configurationService.getNumberOfBuildsInParallel(); |
1256 | |
1257 | try |
1258 | { |
1259 | int count = 1; |
1260 | for ( BuildQueue buildQueue : buildQueues ) |
1261 | { |
1262 | if ( count <= allowedBuilds ) |
1263 | { |
1264 | OverallBuildQueue overallBuildQueue = overallBuildQueues.get( buildQueue.getId() ); |
1265 | if ( overallBuildQueue != null ) |
1266 | { |
1267 | TaskQueue taskQueue = null; |
1268 | TaskQueueExecutor taskQueueExecutor = null; |
1269 | int tempSize = 0; |
1270 | if ( typeOfQueue == BUILD_QUEUE ) |
1271 | { |
1272 | taskQueue = overallBuildQueue.getBuildQueue(); |
1273 | taskQueueExecutor = overallBuildQueue.getBuildTaskQueueExecutor(); |
1274 | } |
1275 | else if ( typeOfQueue == CHECKOUT_QUEUE ) |
1276 | { |
1277 | taskQueue = overallBuildQueue.getCheckoutQueue(); |
1278 | taskQueueExecutor = overallBuildQueue.getCheckoutTaskQueueExecutor(); |
1279 | } |
1280 | |
1281 | tempSize = taskQueue.getQueueSnapshot().size(); |
1282 | if ( taskQueueExecutor.getCurrentTask() != null ) |
1283 | { |
1284 | tempSize++; |
1285 | } |
1286 | |
1287 | if ( idx == 0 ) |
1288 | { |
1289 | whereToBeQueued = overallBuildQueue; |
1290 | size = tempSize; |
1291 | } |
1292 | |
1293 | if ( tempSize < size ) |
1294 | { |
1295 | whereToBeQueued = overallBuildQueue; |
1296 | size = tempSize; |
1297 | } |
1298 | |
1299 | idx++; |
1300 | } |
1301 | else |
1302 | { |
1303 | log.error( "Build queue not found." ); |
1304 | } |
1305 | count++; |
1306 | } |
1307 | else |
1308 | { |
1309 | break; |
1310 | } |
1311 | } |
1312 | } |
1313 | catch ( TaskQueueException e ) |
1314 | { |
1315 | throw new BuildManagerException( "Error occurred while retrieving task quueue: " + e.getMessage() ); |
1316 | } |
1317 | } |
1318 | |
1319 | // use default overall build queue if none is configured |
1320 | if ( whereToBeQueued == null ) |
1321 | { |
1322 | Set<Integer> keySet = overallBuildQueues.keySet(); |
1323 | for ( Integer key : keySet ) |
1324 | { |
1325 | OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key ); |
1326 | if ( overallBuildQueue.getName().equals( ConfigurationService.DEFAULT_BUILD_QUEUE_NAME ) ) |
1327 | { |
1328 | return overallBuildQueue; |
1329 | } |
1330 | } |
1331 | } |
1332 | |
1333 | return whereToBeQueued; |
1334 | } |
1335 | |
1336 | public OverallBuildQueue getOverallBuildQueueWhereProjectsInGroupAreQueued( int projectGroupId ) |
1337 | throws BuildManagerException |
1338 | { |
1339 | OverallBuildQueue whereToBeQueued = null; |
1340 | |
1341 | try |
1342 | { |
1343 | List<Project> projects = projectDao.getProjectsInGroup( projectGroupId ); |
1344 | |
1345 | if ( projects != null ) |
1346 | { |
1347 | for ( Project project : projects ) |
1348 | { |
1349 | whereToBeQueued = getOverallBuildQueueWhereProjectIsQueued( project.getId(), BUILD_QUEUE ); |
1350 | |
1351 | if ( whereToBeQueued == null ) |
1352 | { |
1353 | whereToBeQueued = getOverallBuildQueueWhereProjectIsBuilding( project.getId() ); |
1354 | } |
1355 | |
1356 | if ( whereToBeQueued != null ) |
1357 | { |
1358 | break; |
1359 | } |
1360 | } |
1361 | } |
1362 | } |
1363 | catch ( ContinuumStoreException e ) |
1364 | { |
1365 | throw new BuildManagerException( "Error while retrieving overall build queue for project: " + e.getMessage() ); |
1366 | } |
1367 | catch ( TaskQueueException e ) |
1368 | { |
1369 | throw new BuildManagerException( "Error while retrieving overall build queue for project: " + e.getMessage() ); |
1370 | } |
1371 | |
1372 | return whereToBeQueued; |
1373 | } |
1374 | |
1375 | private OverallBuildQueue getOverallBuildQueueWhereProjectIsBuilding( int projectId ) |
1376 | { |
1377 | synchronized ( overallBuildQueues ) |
1378 | { |
1379 | for ( Integer key : overallBuildQueues.keySet() ) |
1380 | { |
1381 | OverallBuildQueue overallBuildQueue = overallBuildQueues.get( key ); |
1382 | BuildProjectTask task = |
1383 | (BuildProjectTask) overallBuildQueue.getBuildTaskQueueExecutor().getCurrentTask(); |
1384 | if ( task != null && task.getProjectId() == projectId ) |
1385 | { |
1386 | return overallBuildQueue; |
1387 | } |
1388 | } |
1389 | return null; |
1390 | } |
1391 | } |
1392 | |
1393 | public TaskQueueExecutor getPrepareBuildTaskQueueExecutor() |
1394 | throws BuildManagerException |
1395 | { |
1396 | try |
1397 | { |
1398 | return (TaskQueueExecutor) container.lookup( TaskQueueExecutor.class, "prepare-build-project" ); |
1399 | } |
1400 | catch ( ComponentLookupException e ) |
1401 | { |
1402 | throw new BuildManagerException( e.getMessage(), e ); |
1403 | } |
1404 | } |
1405 | |
1406 | public boolean isProjectCurrentlyBeingCheckedOut( int projectId ) |
1407 | throws BuildManagerException |
1408 | { |
1409 | Map<String, CheckOutTask> checkouts = getCurrentCheckouts(); |
1410 | for( String key : checkouts.keySet() ) |
1411 | { |
1412 | CheckOutTask task = checkouts.get( key ); |
1413 | if( task.getProjectId() == projectId ) |
1414 | { |
1415 | return true; |
1416 | } |
1417 | } |
1418 | |
1419 | return false; |
1420 | } |
1421 | |
1422 | public boolean isAnyProjectCurrentlyBuilding( int[] projectIds ) |
1423 | throws BuildManagerException |
1424 | { |
1425 | for ( int i = 0; i < projectIds.length; i++ ) |
1426 | { |
1427 | if ( isProjectInAnyCurrentBuild( projectIds[i] ) ) |
1428 | { |
1429 | return true; |
1430 | } |
1431 | } |
1432 | |
1433 | return false; |
1434 | } |
1435 | |
1436 | public void contextualize( Context context ) |
1437 | throws ContextException |
1438 | { |
1439 | container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY ); |
1440 | |
1441 | synchronized ( overallBuildQueues ) |
1442 | { |
1443 | try |
1444 | { |
1445 | // create all the build queues configured in the database, not just the default! |
1446 | List<BuildQueue> buildQueues = buildQueueService.getAllBuildQueues(); |
1447 | for ( BuildQueue buildQueue : buildQueues ) |
1448 | { |
1449 | createOverallBuildQueue( buildQueue ); |
1450 | } |
1451 | |
1452 | // add default overall build queue if not yet added to the map |
1453 | BuildQueue defaultBuildQueue = configurationService.getDefaultBuildQueue(); |
1454 | if ( overallBuildQueues.get( defaultBuildQueue.getId() ) == null ) |
1455 | { |
1456 | createOverallBuildQueue( defaultBuildQueue ); |
1457 | } |
1458 | } |
1459 | catch ( ComponentLookupException e ) |
1460 | { |
1461 | log.error( "Cannot create overall build queue: " + e.getMessage() ); |
1462 | } |
1463 | catch ( BuildQueueServiceException e ) |
1464 | { |
1465 | log.error( "Cannot create overall build queue: " + e.getMessage() ); |
1466 | } |
1467 | } |
1468 | } |
1469 | |
1470 | public void setContainer( PlexusContainer container ) |
1471 | { |
1472 | this.container = container; |
1473 | } |
1474 | |
1475 | private void createOverallBuildQueue( BuildQueue defaultBuildQueue ) |
1476 | throws ComponentLookupException |
1477 | { |
1478 | OverallBuildQueue overallBuildQueue = (OverallBuildQueue) container.lookup( OverallBuildQueue.class ); |
1479 | overallBuildQueue.setId( defaultBuildQueue.getId() ); |
1480 | overallBuildQueue.setName( defaultBuildQueue.getName() ); |
1481 | |
1482 | overallBuildQueues.put( overallBuildQueue.getId(), overallBuildQueue ); |
1483 | } |
1484 | |
1485 | public TaskQueue getPrepareBuildQueue() |
1486 | { |
1487 | return prepareBuildQueue; |
1488 | } |
1489 | |
1490 | public void setPrepareBuildQueue( TaskQueue prepareBuildQueue ) |
1491 | { |
1492 | this.prepareBuildQueue = prepareBuildQueue; |
1493 | } |
1494 | |
1495 | // for unit tests.. |
1496 | |
1497 | public void setOverallBuildQueues( Map<Integer, OverallBuildQueue> overallBuildQueues ) |
1498 | { |
1499 | this.overallBuildQueues = overallBuildQueues; |
1500 | } |
1501 | |
1502 | public void setConfigurationService( ConfigurationService configurationService ) |
1503 | { |
1504 | this.configurationService = configurationService; |
1505 | } |
1506 | |
1507 | public void setBuildQueueService( BuildQueueService buildQueueService ) |
1508 | { |
1509 | this.buildQueueService = buildQueueService; |
1510 | } |
1511 | |
1512 | public void setBuildDefinitionDao( BuildDefinitionDao buildDefinitionDao ) |
1513 | { |
1514 | this.buildDefinitionDao = buildDefinitionDao; |
1515 | } |
1516 | |
1517 | public void setProjectDao( ProjectDao projectDao ) |
1518 | { |
1519 | this.projectDao = projectDao; |
1520 | } |
1521 | } |