1 package org.apache.continuum.builder.distributed.manager;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.net.MalformedURLException;
23 import java.net.URL;
24 import java.util.ArrayList;
25 import java.util.Collections;
26 import java.util.HashMap;
27 import java.util.List;
28 import java.util.Map;
29
30 import org.apache.continuum.builder.distributed.executor.ThreadedDistributedBuildTaskQueueExecutor;
31 import org.apache.continuum.builder.distributed.util.DistributedBuildUtil;
32 import org.apache.continuum.builder.utils.ContinuumBuildConstant;
33 import org.apache.continuum.configuration.BuildAgentConfiguration;
34 import org.apache.continuum.configuration.BuildAgentGroupConfiguration;
35 import org.apache.continuum.dao.BuildDefinitionDao;
36 import org.apache.continuum.dao.BuildResultDao;
37 import org.apache.continuum.dao.ProjectDao;
38 import org.apache.continuum.distributed.transport.slave.SlaveBuildAgentTransportClient;
39 import org.apache.continuum.taskqueue.BuildProjectTask;
40 import org.apache.continuum.taskqueue.OverallDistributedBuildQueue;
41 import org.apache.continuum.taskqueue.PrepareBuildProjectsTask;
42 import org.apache.continuum.utils.ContinuumUtils;
43 import org.apache.continuum.utils.ProjectSorter;
44 import org.apache.maven.continuum.ContinuumException;
45 import org.apache.maven.continuum.configuration.ConfigurationService;
46 import org.apache.maven.continuum.model.project.BuildDefinition;
47 import org.apache.maven.continuum.model.project.BuildResult;
48 import org.apache.maven.continuum.model.project.Project;
49 import org.apache.maven.continuum.model.system.Installation;
50 import org.apache.maven.continuum.model.system.Profile;
51 import org.apache.maven.continuum.store.ContinuumStoreException;
52 import org.codehaus.plexus.PlexusConstants;
53 import org.codehaus.plexus.PlexusContainer;
54 import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException;
55 import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
56 import org.codehaus.plexus.context.Context;
57 import org.codehaus.plexus.context.ContextException;
58 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
59 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
60 import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
61 import org.codehaus.plexus.personality.plexus.lifecycle.phase.StoppingException;
62 import org.codehaus.plexus.taskqueue.Task;
63 import org.codehaus.plexus.taskqueue.TaskQueueException;
64 import org.codehaus.plexus.util.StringUtils;
65 import org.slf4j.Logger;
66 import org.slf4j.LoggerFactory;
67
68
69
70
71
72 public class DefaultDistributedBuildManager
73 implements DistributedBuildManager, Contextualizable, Initializable
74 {
75 private static final Logger log = LoggerFactory.getLogger( DefaultDistributedBuildManager.class );
76
77 private Map<String, OverallDistributedBuildQueue> overallDistributedBuildQueues =
78 Collections.synchronizedMap( new HashMap<String, OverallDistributedBuildQueue>() );
79
80
81
82
83 private ConfigurationService configurationService;
84
85
86
87
88 private ProjectDao projectDao;
89
90
91
92
93 private BuildDefinitionDao buildDefinitionDao;
94
95
96
97
98 private BuildResultDao buildResultDao;
99
100
101
102
103 private DistributedBuildUtil distributedBuildUtil;
104
105 private PlexusContainer container;
106
107
108
109
110 public void contextualize( Context context )
111 throws ContextException
112 {
113 container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
114 }
115
116 public void initialize()
117 throws InitializationException
118 {
119 List<BuildAgentConfiguration> agents = configurationService.getBuildAgents();
120
121 if ( agents != null )
122 {
123 synchronized( overallDistributedBuildQueues )
124 {
125 for ( BuildAgentConfiguration agent : agents )
126 {
127 if ( agent.isEnabled() )
128 {
129 try
130 {
131 SlaveBuildAgentTransportClient client =
132 new SlaveBuildAgentTransportClient( new URL( agent.getUrl() ) );
133
134 if ( client.ping() )
135 {
136 log.info(
137 "agent is enabled, create distributed build queue for build agent '" + agent.getUrl() + "'" );
138 createDistributedBuildQueueForAgent( agent.getUrl() );
139 }
140 else
141 {
142 log.info( "unable to ping build agent '" + agent.getUrl() + "'" );
143 }
144 }
145 catch ( MalformedURLException e )
146 {
147
148 log.info( "Invalid build agent URL " + agent.getUrl() + ", not creating distributed build queue" );
149 }
150 catch ( ContinuumException e )
151 {
152 throw new InitializationException(
153 "Error while initializing distributed build queues", e );
154 }
155 catch ( Exception e )
156 {
157 agent.setEnabled( false );
158 log.info( "unable to ping build agent '" + agent.getUrl() + "': " +
159 ContinuumUtils.throwableToString( e ) );
160 }
161 }
162 }
163 }
164 }
165 }
166
167 public void reload()
168 throws ContinuumException
169 {
170 List<BuildAgentConfiguration> agents = configurationService.getBuildAgents();
171
172 synchronized( overallDistributedBuildQueues )
173 {
174 for ( BuildAgentConfiguration agent : agents )
175 {
176 if ( agent.isEnabled() && !overallDistributedBuildQueues.containsKey( agent.getUrl() ) )
177 {
178 try
179 {
180 SlaveBuildAgentTransportClient client =
181 new SlaveBuildAgentTransportClient( new URL( agent.getUrl() ) );
182
183 if ( client.ping() )
184 {
185 log.info( "agent is enabled, create distributed build queue for build agent '" + agent.getUrl() + "'" );
186 createDistributedBuildQueueForAgent( agent.getUrl() );
187 }
188 else
189 {
190 log.info( "unable to ping build agent '" + agent.getUrl() + "'" );
191 }
192 }
193 catch ( MalformedURLException e )
194 {
195
196 log.info( "Invalid build agent URL " + agent.getUrl() + ", not creating distributed build queue" );
197 }
198 catch ( Exception e )
199 {
200 agent.setEnabled( false );
201 log.info( "unable to ping build agent '" + agent.getUrl() + "': " +
202 ContinuumUtils.throwableToString( e ) );
203 }
204 }
205 else if ( !agent.isEnabled() && overallDistributedBuildQueues.containsKey( agent.getUrl() ) )
206 {
207 log.info( "agent is disabled, remove distributed build queue for build agent '" + agent.getUrl() + "'" );
208 removeDistributedBuildQueueOfAgent( agent.getUrl() );
209 }
210 }
211 }
212 }
213
214 public void prepareBuildProjects( Map<Integer, Integer>projectsBuildDefinitionsMap, int trigger, int projectGroupId,
215 String projectGroupName, String scmRootAddress, int scmRootId )
216 throws ContinuumException
217 {
218 PrepareBuildProjectsTask task = new PrepareBuildProjectsTask( projectsBuildDefinitionsMap, trigger,
219 projectGroupId, projectGroupName,
220 scmRootAddress, scmRootId );
221
222 OverallDistributedBuildQueue overallDistributedBuildQueue = getOverallDistributedBuildQueueByGroup( projectGroupId );
223
224 if ( overallDistributedBuildQueue == null )
225 {
226
227 overallDistributedBuildQueue = getOverallDistributedBuildQueueByAgentGroup( projectsBuildDefinitionsMap );
228 }
229
230 if ( overallDistributedBuildQueue == null )
231 {
232 overallDistributedBuildQueue = getOverallDistributedBuildQueue();
233 }
234
235 if ( overallDistributedBuildQueue != null )
236 {
237 try
238 {
239 overallDistributedBuildQueue.addToDistributedBuildQueue( task );
240 }
241 catch ( TaskQueueException e )
242 {
243 log.error( "Error while enqueuing prepare build task", e );
244 throw new ContinuumException( "Error occurred while enqueuing prepare build task", e );
245 }
246 }
247 else
248 {
249 log.warn( "No build agent configured. Not building projects." );
250 }
251 }
252
253 public void removeDistributedBuildQueueOfAgent( String buildAgentUrl )
254 throws ContinuumException
255 {
256 if ( overallDistributedBuildQueues.containsKey( buildAgentUrl ) )
257 {
258 List<PrepareBuildProjectsTask> tasks = null;
259
260 synchronized( overallDistributedBuildQueues )
261 {
262 OverallDistributedBuildQueue overallDistributedBuildQueue = overallDistributedBuildQueues.get( buildAgentUrl );
263
264 try
265 {
266 if ( overallDistributedBuildQueue.getDistributedBuildTaskQueueExecutor().getCurrentTask() != null )
267 {
268 log.error( "Unable to remove build agent because it is currently being used" );
269 throw new ContinuumException( "Unable to remove build agent because it is currently being used" );
270 }
271
272 tasks = overallDistributedBuildQueue.getProjectsInQueue();
273
274 overallDistributedBuildQueue.getDistributedBuildQueue().removeAll( tasks );
275
276 ( (ThreadedDistributedBuildTaskQueueExecutor) overallDistributedBuildQueue.getDistributedBuildTaskQueueExecutor() ).stop();
277
278 container.release( overallDistributedBuildQueue );
279
280 log.info( "remove distributed build queue for build agent '" + buildAgentUrl + "'" );
281 }
282 catch ( TaskQueueException e )
283 {
284 log.error( "Error occurred while removing build agent " + buildAgentUrl, e );
285 throw new ContinuumException( "Error occurred while removing build agent " + buildAgentUrl, e );
286 }
287 catch ( ComponentLifecycleException e )
288 {
289 log.error( "Error occurred while removing build agent " + buildAgentUrl, e );
290 throw new ContinuumException( "Error occurred while removing build agent " + buildAgentUrl, e );
291 }
292 catch ( StoppingException e )
293 {
294 log.error( "Error occurred while removing build agent " + buildAgentUrl, e );
295 throw new ContinuumException( "Error occurred while removing build agent " + buildAgentUrl, e );
296 }
297 }
298 }
299 }
300
301 public Map<String, List<PrepareBuildProjectsTask>> getProjectsInPrepareBuildQueue()
302 throws ContinuumException
303 {
304 Map<String, List<PrepareBuildProjectsTask>> map = new HashMap<String, List<PrepareBuildProjectsTask>>();
305
306 synchronized( overallDistributedBuildQueues )
307 {
308 for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
309 {
310 List<PrepareBuildProjectsTask> tasks = new ArrayList<PrepareBuildProjectsTask>();
311
312 try
313 {
314 SlaveBuildAgentTransportClient client =
315 new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) );
316 List<Map<String, Object>> projects = client.getProjectsInPrepareBuildQueue();
317
318 for ( Map<String, Object> context : projects )
319 {
320 tasks.add( getPrepareBuildProjectsTask( context ) );
321 }
322
323 map.put( buildAgentUrl, tasks );
324 }
325 catch ( MalformedURLException e )
326 {
327 throw new ContinuumException( "Invalid build agent url: " + buildAgentUrl );
328 }
329 catch ( Exception e )
330 {
331 throw new ContinuumException( "Error while retrieving projects in prepare build queue", e );
332 }
333 }
334 }
335
336 return map;
337 }
338
339 public Map<String, PrepareBuildProjectsTask> getProjectsCurrentlyPreparingBuild()
340 throws ContinuumException
341 {
342 Map<String, PrepareBuildProjectsTask> map = new HashMap<String, PrepareBuildProjectsTask>();
343
344 synchronized( overallDistributedBuildQueues )
345 {
346 for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
347 {
348 try
349 {
350 SlaveBuildAgentTransportClient client =
351 new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) );
352 Map<String, Object> project = client.getProjectCurrentlyPreparingBuild();
353
354 if ( !project.isEmpty() )
355 {
356 map.put( buildAgentUrl, getPrepareBuildProjectsTask( project ) );
357 }
358 }
359 catch ( MalformedURLException e )
360 {
361 throw new ContinuumException( "Invalid build agent url: " + buildAgentUrl );
362 }
363 catch ( Exception e )
364 {
365 throw new ContinuumException( "Error retrieving projects currently preparing build in " + buildAgentUrl, e );
366 }
367 }
368 }
369 return map;
370 }
371
372 public Map<String, BuildProjectTask> getProjectsCurrentlyBuilding()
373 throws ContinuumException
374 {
375 Map<String, BuildProjectTask> map = new HashMap<String, BuildProjectTask>();
376
377 synchronized( overallDistributedBuildQueues )
378 {
379 for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
380 {
381 try
382 {
383 SlaveBuildAgentTransportClient client =
384 new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) );
385 Map<String, Object> project = client.getProjectCurrentlyBuilding();
386
387 if ( !project.isEmpty() )
388 {
389 map.put( buildAgentUrl, getBuildProjectTask( project ) );
390 }
391 }
392 catch ( MalformedURLException e )
393 {
394 throw new ContinuumException( "Invalid build agent url: " + buildAgentUrl );
395 }
396 catch ( Exception e )
397 {
398 throw new ContinuumException( "Error retrieving projects currently building in " + buildAgentUrl, e );
399 }
400 }
401 }
402
403 return map;
404 }
405
406 public Map<String, List<BuildProjectTask>> getProjectsInBuildQueue()
407 throws ContinuumException
408 {
409 Map<String, List<BuildProjectTask>> map = new HashMap<String, List<BuildProjectTask>>();
410
411 synchronized( overallDistributedBuildQueues )
412 {
413 for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
414 {
415 List<BuildProjectTask> tasks = new ArrayList<BuildProjectTask>();
416
417 try
418 {
419 SlaveBuildAgentTransportClient client =
420 new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) );
421 List<Map<String, Object>> projects = client.getProjectsInBuildQueue();
422
423 for ( Map<String, Object> context : projects )
424 {
425 tasks.add( getBuildProjectTask( context ) );
426 }
427
428 map.put( buildAgentUrl, tasks );
429 }
430 catch ( MalformedURLException e )
431 {
432 throw new ContinuumException( "Invalid build agent url: " + buildAgentUrl );
433 }
434 catch ( Exception e )
435 {
436 throw new ContinuumException( "Error while retrieving projects in build queue", e );
437 }
438 }
439 }
440 return map;
441 }
442
443 public boolean isBuildAgentBusy( String buildAgentUrl )
444 {
445 synchronized ( overallDistributedBuildQueues )
446 {
447 OverallDistributedBuildQueue overallDistributedBuildQueue = overallDistributedBuildQueues.get( buildAgentUrl );
448
449 if ( overallDistributedBuildQueue != null &&
450 overallDistributedBuildQueue.getDistributedBuildTaskQueueExecutor().getCurrentTask() != null )
451 {
452 log.info( "build agent '" + buildAgentUrl + "' is busy" );
453 return true;
454 }
455
456 log.info( "build agent '" + buildAgentUrl + "' is not busy" );
457 return false;
458 }
459 }
460
461 public void cancelDistributedBuild( String buildAgentUrl )
462 throws ContinuumException
463 {
464 try
465 {
466 SlaveBuildAgentTransportClient client = new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) );
467
468 client.cancelBuild();
469 }
470 catch ( MalformedURLException e )
471 {
472 log.error( "Error cancelling build in build agent: Invalid build agent url " + buildAgentUrl );
473 throw new ContinuumException( "Error cancelling build in build agent: Invalid build agent url " + buildAgentUrl );
474 }
475 catch ( Exception e )
476 {
477 log.error( "Error occurred while cancelling build in build agent " + buildAgentUrl, e );
478 throw new ContinuumException( "Error occurred while cancelling build in build agent " + buildAgentUrl, e );
479 }
480 }
481
482 public Map<String, Object> getBuildResult( int projectId )
483 throws ContinuumException
484 {
485 Map<String, Object> map = new HashMap<String, Object>();
486
487 String buildAgentUrl = getBuildAgent( projectId );
488
489 if ( buildAgentUrl == null )
490 {
491 return null;
492 }
493
494 try
495 {
496 SlaveBuildAgentTransportClient client = new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) );
497
498 Map<String, Object> result = client.getBuildResult( projectId );
499
500 if ( result != null )
501 {
502 int buildDefinitionId = ContinuumBuildConstant.getBuildDefinitionId( result );
503
504 Project project = projectDao.getProjectWithAllDetails( projectId );
505 BuildDefinition buildDefinition = buildDefinitionDao.getBuildDefinition( buildDefinitionId );
506
507 BuildResult oldBuildResult =
508 buildResultDao.getLatestBuildResultForBuildDefinition( projectId, buildDefinitionId );
509
510 BuildResult buildResult = distributedBuildUtil.convertMapToBuildResult( result );
511 buildResult.setBuildDefinition( buildDefinition );
512 buildResult.setBuildNumber( project.getBuildNumber() + 1 );
513 buildResult.setModifiedDependencies( distributedBuildUtil.getModifiedDependencies( oldBuildResult, result ) );
514 buildResult.setScmResult( distributedBuildUtil.getScmResult( result ) );
515
516 String buildOutput = ContinuumBuildConstant.getBuildOutput( result );
517
518 map.put( ContinuumBuildConstant.KEY_BUILD_RESULT, buildResult );
519 map.put( ContinuumBuildConstant.KEY_BUILD_OUTPUT, buildOutput );
520 }
521 }
522 catch ( MalformedURLException e )
523 {
524 throw new ContinuumException( "Invalid build agent URL '" + buildAgentUrl + "'" );
525 }
526 catch ( Exception e )
527 {
528 throw new ContinuumException( "Error while retrieving build result for project" + projectId, e );
529 }
530
531 return map;
532 }
533
534 public List<Installation> getAvailableInstallations( String buildAgentUrl )
535 throws ContinuumException
536 {
537 List<Installation> installations = new ArrayList<Installation>();
538
539 try
540 {
541 SlaveBuildAgentTransportClient client = new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) );
542
543 List<Map<String, String>> installationsList = client.getAvailableInstallations();
544
545 for ( Map context : installationsList )
546 {
547 Installation installation = new Installation();
548 installation.setName( ContinuumBuildConstant.getInstallationName( context ) );
549 installation.setType( ContinuumBuildConstant.getInstallationType( context ) );
550 installation.setVarName( ContinuumBuildConstant.getInstallationVarName( context ) );
551 installation.setVarValue( ContinuumBuildConstant.getInstallationVarValue( context ) );
552 installations.add( installation );
553 }
554
555 return installations;
556 }
557 catch ( Exception e )
558 {
559 throw new ContinuumException( "Unable to get available installations of build agent", e );
560 }
561 }
562
563 public String generateWorkingCopyContent( int projectId, String directory, String baseUrl, String imageBaseUrl )
564 throws ContinuumException
565 {
566 BuildResult buildResult = buildResultDao.getLatestBuildResultForProject( projectId );
567
568 if ( buildResult != null )
569 {
570 String buildAgentUrl = buildResult.getBuildUrl();
571
572 if ( buildAgentUrl == null )
573 {
574 return "";
575 }
576
577 try
578 {
579 if ( directory == null )
580 {
581 directory = "";
582 }
583
584 SlaveBuildAgentTransportClient client = new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) );
585 return client.generateWorkingCopyContent( projectId, directory, baseUrl, imageBaseUrl );
586 }
587 catch ( MalformedURLException e )
588 {
589 log.error( "Invalid build agent url " + buildAgentUrl );
590 }
591 catch ( Exception e )
592 {
593 log.error( "Error while generating working copy content from build agent " + buildAgentUrl, e );
594 }
595 }
596 return "";
597 }
598
599 public String getFileContent( int projectId, String directory, String filename )
600 throws ContinuumException
601 {
602 BuildResult buildResult = buildResultDao.getLatestBuildResultForProject( projectId );
603
604 if ( buildResult != null )
605 {
606 String buildAgentUrl = buildResult.getBuildUrl();
607
608 if ( buildAgentUrl == null )
609 {
610 return "";
611 }
612
613 try
614 {
615 SlaveBuildAgentTransportClient client = new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) );
616 return client.getProjectFileContent( projectId, directory, filename );
617 }
618 catch ( MalformedURLException e )
619 {
620 log.error( "Invalid build agent url " + buildAgentUrl );
621 }
622 catch ( Exception e )
623 {
624 log.error( "Error while retrieving content of " + filename, e );
625 }
626 }
627 return "";
628 }
629
630 public void removeFromPrepareBuildQueue( String buildAgentUrl, int projectGroupId, int scmRootId )
631 throws ContinuumException
632 {
633 try
634 {
635 SlaveBuildAgentTransportClient client = new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) );
636 client.removeFromPrepareBuildQueue( projectGroupId, scmRootId );
637 }
638 catch ( MalformedURLException e )
639 {
640 log.error( "Unable to remove projectGroupId=" + projectGroupId + " scmRootId=" + scmRootId +
641 " from prepare build queue: Invalid build agent url " + buildAgentUrl );
642 throw new ContinuumException( "Unable to remove projectGroupId=" + projectGroupId + " scmRootId=" + scmRootId +
643 " from prepare build queue: Invalid build agent url " + buildAgentUrl );
644 }
645 catch ( Exception e )
646 {
647 log.error( "Error occurred while removing projectGroupId=" + projectGroupId + " scmRootId=" + scmRootId +
648 " from prepare build queue of agent " + buildAgentUrl, e );
649 throw new ContinuumException( "Error occurred while removing projectGroupId=" + projectGroupId + " scmRootId=" +
650 scmRootId + " from prepare build queue of agent " + buildAgentUrl, e );
651 }
652 }
653
654 public void removeFromBuildQueue( String buildAgentUrl, int projectId, int buildDefinitionId )
655 throws ContinuumException
656 {
657 try
658 {
659 SlaveBuildAgentTransportClient client = new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) );
660 client.removeFromBuildQueue( projectId, buildDefinitionId );
661 }
662 catch ( MalformedURLException e )
663 {
664 log.error( "Unable to remove project " + projectId +
665 " from build queue: Invalid build agent url " + buildAgentUrl );
666 throw new ContinuumException( "Unable to remove project " + projectId +
667 " from build queue: Invalid build agent url " + buildAgentUrl );
668 }
669 catch ( Exception e )
670 {
671 log.error( "Error occurred while removing project " + projectId +
672 " from build queue of agent " + buildAgentUrl, e );
673 throw new ContinuumException( "Error occurred while removing project " + projectId +
674 " from build queue of agent " + buildAgentUrl, e );
675 }
676 }
677
678 public void removeFromPrepareBuildQueue( List<String> hashCodes )
679 throws ContinuumException
680 {
681 synchronized ( overallDistributedBuildQueues )
682 {
683 for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
684 {
685 try
686 {
687 SlaveBuildAgentTransportClient client = new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) );
688 client.removeFromPrepareBuildQueue( hashCodes );
689 }
690 catch ( MalformedURLException e )
691 {
692 log.error( "Error trying to remove projects from prepare build queue. Invalid build agent url: " + buildAgentUrl );
693 }
694 catch ( Exception e )
695 {
696 log.error( "Error trying to remove projects from prepare build queue of agent " + buildAgentUrl, e );
697 }
698 }
699 }
700 }
701
702 public void removeFromBuildQueue( List<String> hashCodes )
703 throws ContinuumException
704 {
705 synchronized ( overallDistributedBuildQueues )
706 {
707 for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
708 {
709 try
710 {
711 SlaveBuildAgentTransportClient client = new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) );
712 client.removeFromBuildQueue( hashCodes );
713 }
714 catch ( MalformedURLException e )
715 {
716 log.error( "Error trying to remove projects from build queue. Invalid build agent url: " + buildAgentUrl );
717 }
718 catch ( Exception e )
719 {
720 log.error( "Error trying to remove projects from build queue of agent " + buildAgentUrl, e );
721 }
722 }
723 }
724 }
725
726 private String getBuildAgent( int projectId )
727 throws ContinuumException
728 {
729 synchronized( overallDistributedBuildQueues )
730 {
731 for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
732 {
733 OverallDistributedBuildQueue overallDistributedBuildQueue =
734 overallDistributedBuildQueues.get( buildAgentUrl );
735
736 if ( overallDistributedBuildQueue != null )
737 {
738 try
739 {
740 SlaveBuildAgentTransportClient client =
741 new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) );
742
743 if ( client.isProjectCurrentlyBuilding( projectId ) )
744 {
745 return buildAgentUrl;
746 }
747 }
748 catch ( MalformedURLException e )
749 {
750 log.warn( "Unable to check if project " + projectId + " is currently building in agent: Invalid build agent url" + buildAgentUrl );
751 }
752 catch ( Exception e )
753 {
754 log.warn( "Unable to check if project " + projectId + " is currently building in agent", e );
755 }
756 }
757 }
758 }
759
760 return null;
761 }
762
763 private void createDistributedBuildQueueForAgent( String buildAgentUrl )
764 throws ComponentLookupException
765 {
766 if ( !overallDistributedBuildQueues.containsKey( buildAgentUrl ) )
767 {
768 OverallDistributedBuildQueue overallDistributedBuildQueue =
769 (OverallDistributedBuildQueue) container.lookup( OverallDistributedBuildQueue.class );
770 overallDistributedBuildQueue.setBuildAgentUrl( buildAgentUrl );
771 overallDistributedBuildQueue.getDistributedBuildTaskQueueExecutor().setBuildAgentUrl( buildAgentUrl );
772
773 overallDistributedBuildQueues.put( buildAgentUrl, overallDistributedBuildQueue );
774 }
775 }
776
777 private OverallDistributedBuildQueue getOverallDistributedBuildQueueByGroupAndScmRoot( int projectGroupId, int scmRootId )
778 throws ContinuumException
779 {
780 synchronized( overallDistributedBuildQueues )
781 {
782 for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
783 {
784 OverallDistributedBuildQueue distributedBuildQueue = overallDistributedBuildQueues.get( buildAgentUrl );
785
786 try
787 {
788 for ( PrepareBuildProjectsTask task : distributedBuildQueue.getProjectsInQueue() )
789 {
790 if ( task.getProjectGroupId() == projectGroupId && task.getProjectScmRootId() == scmRootId )
791 {
792 return distributedBuildQueue;
793 }
794 }
795 }
796 catch ( TaskQueueException e )
797 {
798 log.error( "Error occurred while retrieving distributed build queue of projectGroupId=" + projectGroupId + " scmRootId=" + scmRootId, e );
799 throw new ContinuumException( "Error occurred while retrieving distributed build queue of group", e );
800 }
801 }
802 }
803
804 return null;
805 }
806
807 private OverallDistributedBuildQueue getOverallDistributedBuildQueueByGroup( int projectGroupId )
808 throws ContinuumException
809 {
810 synchronized( overallDistributedBuildQueues )
811 {
812 for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
813 {
814 OverallDistributedBuildQueue distributedBuildQueue = overallDistributedBuildQueues.get( buildAgentUrl );
815
816 try
817 {
818
819 for ( PrepareBuildProjectsTask task : distributedBuildQueue.getProjectsInQueue() )
820 {
821 if ( task.getProjectGroupId() == projectGroupId )
822 {
823 return distributedBuildQueue;
824 }
825 }
826
827 Task task = distributedBuildQueue.getDistributedBuildTaskQueueExecutor().getCurrentTask();
828 if ( task != null && ( (PrepareBuildProjectsTask) task ).getProjectGroupId() == projectGroupId )
829 {
830 return distributedBuildQueue;
831 }
832
833 SlaveBuildAgentTransportClient client = new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) );
834
835 if ( client.isProjectGroupInQueue( projectGroupId ) )
836 {
837 return distributedBuildQueue;
838 }
839 }
840 catch ( TaskQueueException e )
841 {
842 log.error( "Error occurred while retrieving distributed build queue of projectGroupId=" + projectGroupId, e );
843 throw new ContinuumException( "Error occurred while retrieving distributed build queue of group", e );
844 }
845 catch ( MalformedURLException e )
846 {
847 log.error( "Error occurred while retrieving distributed build queue of projectGroupId=" + projectGroupId +
848 ": Invalid build agent url " + buildAgentUrl );
849 throw new ContinuumException( "Error occurred while retrieving distributed build queue of projectGroupId=" + projectGroupId +
850 ": Invalid build agent url " + buildAgentUrl );
851 }
852 catch ( Exception e )
853 {
854 log.error( "Error occurred while retrieving distributed build queue of projectGroupId=" + projectGroupId, e );
855 throw new ContinuumException( "Error occurred while retrieving distributed build queue of group", e );
856 }
857 }
858 }
859
860 return null;
861 }
862
863
864 private OverallDistributedBuildQueue getOverallDistributedBuildQueueByHashCode( int hashCode )
865 throws ContinuumException
866 {
867 synchronized( overallDistributedBuildQueues )
868 {
869 for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
870 {
871 OverallDistributedBuildQueue distributedBuildQueue = overallDistributedBuildQueues.get( buildAgentUrl );
872
873 try
874 {
875 for ( PrepareBuildProjectsTask task : distributedBuildQueue.getProjectsInQueue() )
876 {
877 if ( task.getHashCode() == hashCode )
878 {
879 return distributedBuildQueue;
880 }
881 }
882 }
883 catch ( TaskQueueException e )
884 {
885 log.error( "Error occurred while retrieving distributed build queue", e );
886 throw new ContinuumException( "Error occurred while retrieving distributed build queue", e );
887 }
888 }
889 }
890
891 return null;
892 }
893
894 private OverallDistributedBuildQueue getOverallDistributedBuildQueueByAgentGroup( Map<Integer, Integer> projectsAndBuildDefinitionsMap )
895 throws ContinuumException
896 {
897 OverallDistributedBuildQueue whereToBeQueued = null;
898
899 BuildAgentGroupConfiguration buildAgentGroup = getBuildAgentGroup( projectsAndBuildDefinitionsMap );
900
901 if ( buildAgentGroup != null )
902 {
903 List<BuildAgentConfiguration> buildAgents = buildAgentGroup.getBuildAgents();
904
905 if ( buildAgents != null && buildAgents.size() > 0 )
906 {
907 List<String> buildAgentUrls = new ArrayList<String>();
908
909 for ( BuildAgentConfiguration buildAgent : buildAgents )
910 {
911 buildAgentUrls.add( buildAgent.getUrl() );
912 }
913
914 synchronized( overallDistributedBuildQueues )
915 {
916 int idx = 0;
917 int size = 0;
918
919 for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
920 {
921 if ( ( !buildAgentUrls.isEmpty() && buildAgentUrls.contains( buildAgentUrl ) ) || buildAgentUrls.isEmpty() )
922 {
923 OverallDistributedBuildQueue distributedBuildQueue = overallDistributedBuildQueues.get( buildAgentUrl );
924
925 if ( distributedBuildQueue != null )
926 {
927 try
928 {
929 SlaveBuildAgentTransportClient client = new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) );
930 int agentBuildSize = client.getBuildSizeOfAgent();
931
932 if ( idx == 0 )
933 {
934 whereToBeQueued = distributedBuildQueue;
935 size = agentBuildSize;
936 }
937
938 if ( agentBuildSize < size )
939 {
940 whereToBeQueued = distributedBuildQueue;
941 size = agentBuildSize;
942 }
943 }
944 catch ( MalformedURLException e )
945 {
946 log.error( "Error occurred while retrieving distributed build queue: Invalid build agent url " + buildAgentUrl );
947 }
948 catch ( Exception e )
949 {
950 log.error( "Error occurred while retrieving distributed build queue ", e );
951 }
952 }
953 }
954 }
955 }
956 }
957 }
958 return whereToBeQueued;
959 }
960
961 private OverallDistributedBuildQueue getOverallDistributedBuildQueue()
962 throws ContinuumException
963 {
964 OverallDistributedBuildQueue whereToBeQueued = null;
965
966 synchronized ( overallDistributedBuildQueues )
967 {
968 if ( overallDistributedBuildQueues.isEmpty() )
969 {
970 log.info( "No distributed build queues are configured for build agents" );
971 return null;
972 }
973
974 int idx = 0;
975 int size = 0;
976
977 for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
978 {
979 OverallDistributedBuildQueue distributedBuildQueue = overallDistributedBuildQueues.get( buildAgentUrl );
980
981 if ( distributedBuildQueue != null )
982 {
983 try
984 {
985 SlaveBuildAgentTransportClient client = new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) );
986 int agentBuildSize = client.getBuildSizeOfAgent();
987
988 if ( idx == 0 )
989 {
990 whereToBeQueued = distributedBuildQueue;
991 size = agentBuildSize;
992 }
993
994 if ( agentBuildSize < size )
995 {
996 whereToBeQueued = distributedBuildQueue;
997 size = agentBuildSize;
998 }
999 }
1000 catch ( MalformedURLException e )
1001 {
1002 log.error( "Error occurred while retrieving distributed build queue: invalid build agent url " + buildAgentUrl );
1003 }
1004 catch ( Exception e )
1005 {
1006 log.error( "Error occurred while retrieving distributed build queue", e );
1007 throw new ContinuumException( "Error occurred while retrieving distributed build queue", e );
1008 }
1009 }
1010
1011 idx++;
1012 }
1013 }
1014
1015 return whereToBeQueued;
1016 }
1017
1018 private BuildAgentGroupConfiguration getBuildAgentGroup( Map<Integer, Integer> projectsAndBuildDefinitions )
1019 throws ContinuumException
1020 {
1021
1022 if ( projectsAndBuildDefinitions == null )
1023 {
1024 return null;
1025 }
1026
1027 try
1028 {
1029 List<Project> projects = new ArrayList<Project>();
1030
1031 for ( Integer projectId : projectsAndBuildDefinitions.keySet() )
1032 {
1033 projects.add( projectDao.getProjectWithDependencies( projectId ) );
1034 }
1035
1036 projects = ProjectSorter.getSortedProjects( projects, null );
1037
1038 int buildDefinitionId = projectsAndBuildDefinitions.get( projects.get( 0 ).getId() );
1039 BuildDefinition buildDefinition = buildDefinitionDao.getBuildDefinition( buildDefinitionId );
1040
1041 Profile profile = buildDefinition.getProfile();
1042
1043 if ( profile != null && !StringUtils.isEmpty( profile.getBuildAgentGroup() ) )
1044 {
1045 String groupName = profile.getBuildAgentGroup();
1046
1047 BuildAgentGroupConfiguration buildAgentGroup = configurationService.getBuildAgentGroup( groupName );
1048
1049 return buildAgentGroup;
1050 }
1051 }
1052 catch ( ContinuumStoreException e )
1053 {
1054 log.error( "Error while getting build agent group", e );
1055 throw new ContinuumException( "Error while getting build agent group", e );
1056 }
1057
1058 log.info( "profile build agent group is null" );
1059
1060 return null;
1061 }
1062
1063 private PrepareBuildProjectsTask getPrepareBuildProjectsTask( Map context )
1064 {
1065 int projectGroupId = ContinuumBuildConstant.getProjectGroupId( context );
1066 int scmRootId = ContinuumBuildConstant.getScmRootId( context );
1067 String scmRootAddress = ContinuumBuildConstant.getScmRootAddress( context );
1068 int trigger = ContinuumBuildConstant.getTrigger( context );
1069
1070 return new PrepareBuildProjectsTask( null, trigger, projectGroupId, null, scmRootAddress, scmRootId );
1071 }
1072
1073 private BuildProjectTask getBuildProjectTask( Map context )
1074 {
1075 int projectId = ContinuumBuildConstant.getProjectId( context );
1076 int buildDefinitionId = ContinuumBuildConstant.getBuildDefinitionId( context );
1077 int trigger = ContinuumBuildConstant.getTrigger( context );
1078 int projectGroupId = ContinuumBuildConstant.getProjectGroupId( context );
1079 String buildDefinitionLabel = ContinuumBuildConstant.getBuildDefinitionLabel( context );
1080
1081 return new BuildProjectTask( projectId, buildDefinitionId, trigger, null, buildDefinitionLabel, null, projectGroupId );
1082 }
1083 }