1 package org.apache.continuum.buildmanager;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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
65
66
67
68
69 public class ParallelBuildsManager
70 implements BuildsManager, Contextualizable
71 {
72 private static final Logger log = LoggerFactory.getLogger( ParallelBuildsManager.class );
73
74
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
1446 List<BuildQueue> buildQueues = buildQueueService.getAllBuildQueues();
1447 for ( BuildQueue buildQueue : buildQueues )
1448 {
1449 createOverallBuildQueue( buildQueue );
1450 }
1451
1452
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
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 }