You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@continuum.apache.org by oc...@apache.org on 2010/05/06 11:23:34 UTC
svn commit: r941625 [6/24] - in
/continuum/branches/continuum-flat-multi-module: ./ continuum-api/
continuum-api/src/main/java/org/apache/continuum/builder/distributed/
continuum-api/src/main/java/org/apache/continuum/builder/distributed/manager/
conti...
Modified: continuum/branches/continuum-flat-multi-module/continuum-core/src/main/java/org/apache/continuum/builder/distributed/manager/DefaultDistributedBuildManager.java
URL: http://svn.apache.org/viewvc/continuum/branches/continuum-flat-multi-module/continuum-core/src/main/java/org/apache/continuum/builder/distributed/manager/DefaultDistributedBuildManager.java?rev=941625&r1=941624&r2=941625&view=diff
==============================================================================
--- continuum/branches/continuum-flat-multi-module/continuum-core/src/main/java/org/apache/continuum/builder/distributed/manager/DefaultDistributedBuildManager.java (original)
+++ continuum/branches/continuum-flat-multi-module/continuum-core/src/main/java/org/apache/continuum/builder/distributed/manager/DefaultDistributedBuildManager.java Thu May 6 09:23:13 2010
@@ -19,49 +19,40 @@ package org.apache.continuum.builder.dis
* under the License.
*/
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import org.apache.continuum.builder.distributed.executor.DistributedBuildTaskQueueExecutor;
+import org.apache.continuum.buildagent.NoBuildAgentException;
+import org.apache.continuum.buildagent.NoBuildAgentInGroupException;
import org.apache.continuum.builder.distributed.executor.ThreadedDistributedBuildTaskQueueExecutor;
+import org.apache.continuum.builder.distributed.util.DistributedBuildUtil;
import org.apache.continuum.builder.utils.ContinuumBuildConstant;
import org.apache.continuum.configuration.BuildAgentConfiguration;
+import org.apache.continuum.configuration.BuildAgentGroupConfiguration;
import org.apache.continuum.dao.BuildDefinitionDao;
import org.apache.continuum.dao.BuildResultDao;
import org.apache.continuum.dao.ProjectDao;
-import org.apache.continuum.dao.ProjectScmRootDao;
import org.apache.continuum.distributed.transport.slave.SlaveBuildAgentTransportClient;
+import org.apache.continuum.distributed.transport.slave.SlaveBuildAgentTransportService;
import org.apache.continuum.model.project.ProjectScmRoot;
+import org.apache.continuum.taskqueue.BuildProjectTask;
+import org.apache.continuum.taskqueue.OverallDistributedBuildQueue;
import org.apache.continuum.taskqueue.PrepareBuildProjectsTask;
import org.apache.continuum.utils.ContinuumUtils;
+import org.apache.continuum.utils.ProjectSorter;
+import org.apache.continuum.utils.build.BuildTrigger;
import org.apache.maven.continuum.ContinuumException;
-import org.apache.maven.continuum.configuration.ConfigurationException;
import org.apache.maven.continuum.configuration.ConfigurationService;
-import org.apache.maven.continuum.execution.ContinuumBuildExecutorConstants;
-import org.apache.maven.continuum.installation.InstallationService;
import org.apache.maven.continuum.model.project.BuildDefinition;
import org.apache.maven.continuum.model.project.BuildResult;
import org.apache.maven.continuum.model.project.Project;
-import org.apache.maven.continuum.model.project.ProjectDependency;
-import org.apache.maven.continuum.model.project.ProjectDeveloper;
-import org.apache.maven.continuum.model.project.ProjectNotifier;
-import org.apache.maven.continuum.model.scm.ChangeFile;
-import org.apache.maven.continuum.model.scm.ChangeSet;
-import org.apache.maven.continuum.model.scm.ScmResult;
import org.apache.maven.continuum.model.system.Installation;
import org.apache.maven.continuum.model.system.Profile;
-import org.apache.maven.continuum.notification.ContinuumNotificationDispatcher;
-import org.apache.maven.continuum.project.ContinuumProjectState;
import org.apache.maven.continuum.store.ContinuumStoreException;
import org.codehaus.plexus.PlexusConstants;
import org.codehaus.plexus.PlexusContainer;
@@ -73,6 +64,8 @@ import org.codehaus.plexus.personality.p
import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.StoppingException;
+import org.codehaus.plexus.taskqueue.Task;
+import org.codehaus.plexus.taskqueue.TaskQueueException;
import org.codehaus.plexus.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -86,15 +79,13 @@ public class DefaultDistributedBuildMana
{
private static final Logger log = LoggerFactory.getLogger( DefaultDistributedBuildManager.class );
- /**
- * @plexus.requirement
- */
- private ConfigurationService configurationService;
+ private Map<String, OverallDistributedBuildQueue> overallDistributedBuildQueues =
+ Collections.synchronizedMap( new HashMap<String, OverallDistributedBuildQueue>() );
/**
* @plexus.requirement
*/
- private InstallationService installationService;
+ private ConfigurationService configurationService;
/**
* @plexus.requirement
@@ -109,22 +100,15 @@ public class DefaultDistributedBuildMana
/**
* @plexus.requirement
*/
- private ProjectScmRootDao projectScmRootDao;
-
- /**
- * @plexus.requirement
- */
private BuildResultDao buildResultDao;
/**
* @plexus.requirement
*/
- private ContinuumNotificationDispatcher notifierDispatcher;
+ private DistributedBuildUtil distributedBuildUtil;
private PlexusContainer container;
- private Map<String, DistributedBuildTaskQueueExecutor> taskQueueExecutors;
-
// --------------------------------
// Plexus Lifecycle
// --------------------------------
@@ -137,26 +121,77 @@ public class DefaultDistributedBuildMana
public void initialize()
throws InitializationException
{
- taskQueueExecutors = new HashMap<String, DistributedBuildTaskQueueExecutor>();
-
List<BuildAgentConfiguration> agents = configurationService.getBuildAgents();
if ( agents != null )
{
+ synchronized( overallDistributedBuildQueues )
+ {
+ for ( BuildAgentConfiguration agent : agents )
+ {
+ if ( agent.isEnabled() )
+ {
+ try
+ {
+ SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection( agent.getUrl() );
+
+ if ( client.ping() )
+ {
+ log.info(
+ "agent is enabled, create distributed build queue for build agent '" + agent.getUrl() + "'" );
+ createDistributedBuildQueueForAgent( agent.getUrl() );
+ }
+ else
+ {
+ log.info( "unable to ping build agent '" + agent.getUrl() + "'" );
+ }
+ }
+ catch ( MalformedURLException e )
+ {
+ // do not throw exception, just log it
+ log.info( "Invalid build agent URL " + agent.getUrl() + ", not creating distributed build queue" );
+ }
+ catch ( ContinuumException e )
+ {
+ throw new InitializationException(
+ "Error while initializing distributed build queues", e );
+ }
+ catch ( Exception e )
+ {
+ agent.setEnabled( false );
+ log.info( "unable to ping build agent '" + agent.getUrl() + "': " +
+ ContinuumUtils.throwableToString( e ) );
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public void reload()
+ throws ContinuumException
+ {
+ List<BuildAgentConfiguration> agents = configurationService.getBuildAgents();
+
+ if ( agents == null )
+ {
+ return;
+ }
+
+ synchronized( overallDistributedBuildQueues )
+ {
for ( BuildAgentConfiguration agent : agents )
{
- if ( agent.isEnabled() )
+ if ( agent.isEnabled() && !overallDistributedBuildQueues.containsKey( agent.getUrl() ) )
{
try
{
- SlaveBuildAgentTransportClient client =
- new SlaveBuildAgentTransportClient( new URL( agent.getUrl() ) );
-
+ SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection( agent.getUrl() );
+
if ( client.ping() )
{
- log.info(
- "agent is enabled, add TaskQueueExecutor for build agent '" + agent.getUrl() + "'" );
- addTaskQueueExecutor( agent.getUrl() );
+ log.info( "agent is enabled, create distributed build queue for build agent '" + agent.getUrl() + "'" );
+ createDistributedBuildQueueForAgent( agent.getUrl() );
}
else
{
@@ -166,12 +201,7 @@ public class DefaultDistributedBuildMana
catch ( MalformedURLException e )
{
// do not throw exception, just log it
- log.info( "Invalid build agent URL " + agent.getUrl() + ", not creating task queue executor" );
- }
- catch ( ContinuumException e )
- {
- throw new InitializationException(
- "Error while initializing distributed build task queue executors", e );
+ log.info( "Invalid build agent URL " + agent.getUrl() + ", not creating distributed build queue" );
}
catch ( Exception e )
{
@@ -180,376 +210,330 @@ public class DefaultDistributedBuildMana
ContinuumUtils.throwableToString( e ) );
}
}
+ else if ( !agent.isEnabled() && overallDistributedBuildQueues.containsKey( agent.getUrl() ) )
+ {
+ log.info( "agent is disabled, remove distributed build queue for build agent '" + agent.getUrl() + "'" );
+ removeDistributedBuildQueueOfAgent( agent.getUrl() );
+ }
}
}
}
- public void reload()
- throws ContinuumException
+ public void prepareBuildProjects( Map<Integer, Integer>projectsBuildDefinitionsMap, BuildTrigger buildTrigger, int projectGroupId,
+ String projectGroupName, String scmRootAddress, int scmRootId, List<ProjectScmRoot> scmRoots )
+ throws ContinuumException, NoBuildAgentException, NoBuildAgentInGroupException
{
- List<BuildAgentConfiguration> agents = configurationService.getBuildAgents();
+ PrepareBuildProjectsTask task = new PrepareBuildProjectsTask( projectsBuildDefinitionsMap, buildTrigger,
+ projectGroupId, projectGroupName,
+ scmRootAddress, scmRootId );
- for ( BuildAgentConfiguration agent : agents )
+ OverallDistributedBuildQueue overallDistributedBuildQueue = getOverallDistributedBuildQueueByGroup( projectGroupId, scmRoots, scmRootId );
+
+ if ( overallDistributedBuildQueue == null )
{
- if ( agent.isEnabled() && !taskQueueExecutors.containsKey( agent.getUrl() ) )
+ if ( hasBuildagentGroup( projectsBuildDefinitionsMap ) )
{
- try
- {
- SlaveBuildAgentTransportClient client =
- new SlaveBuildAgentTransportClient( new URL( agent.getUrl() ) );
-
- if ( client.ping() )
- {
- log.info( "agent is enabled, add TaskQueueExecutor for build agent '" + agent.getUrl() + "'" );
- addTaskQueueExecutor( agent.getUrl() );
- }
- else
- {
- log.info( "unable to ping build agent '" + agent.getUrl() + "'" );
- }
- }
- catch ( MalformedURLException e )
+ if ( !hasBuildagentInGroup( projectsBuildDefinitionsMap ) )
{
- // do not throw exception, just log it
- log.info( "Invalid build agent URL " + agent.getUrl() + ", not creating task queue executor" );
+ log.warn( "No build agent configured in build agent group. Not building projects." );
+
+ throw new NoBuildAgentInGroupException( "No build agent configured in build agent group" );
}
- catch ( Exception e )
+ else
{
- agent.setEnabled( false );
- log.info( "unable to ping build agent '" + agent.getUrl() + "': " +
- ContinuumUtils.throwableToString( e ) );
+ // get overall distributed build queue from build agent group
+ log.info( "getting the least busy build agent from the build agent group" );
+ overallDistributedBuildQueue = getOverallDistributedBuildQueueByAgentGroup( projectsBuildDefinitionsMap );
}
}
- else if ( !agent.isEnabled() && taskQueueExecutors.containsKey( agent.getUrl() ) )
+ else
{
- log.info( "agent is disabled, remove TaskQueueExecutor for build agent '" + agent.getUrl() + "'" );
- removeAgentFromTaskQueueExecutor( agent.getUrl() );
+ // project does not have build agent group
+ log.info( "project does not have a build agent group, getting the least busy build agent" );
+ overallDistributedBuildQueue = getOverallDistributedBuildQueue();
}
}
- }
-
- public void removeAgentFromTaskQueueExecutor( String buildAgentUrl )
- throws ContinuumException
- {
- log.info( "remove TaskQueueExecutor for build agent '" + buildAgentUrl + "'" );
- ThreadedDistributedBuildTaskQueueExecutor executor =
- (ThreadedDistributedBuildTaskQueueExecutor) taskQueueExecutors.get( buildAgentUrl );
-
- if ( executor == null )
- {
- return;
- }
- try
+ if ( overallDistributedBuildQueue != null )
{
- executor.stop();
- container.release( executor );
- }
- catch ( StoppingException e )
- {
- throw new ContinuumException( "Error while stopping task queue executor", e );
+ try
+ {
+ overallDistributedBuildQueue.addToDistributedBuildQueue( task );
+ }
+ catch ( TaskQueueException e )
+ {
+ log.error( "Error while enqueuing prepare build task", e );
+ throw new ContinuumException( "Error occurred while enqueuing prepare build task", e );
+ }
}
- catch ( ComponentLifecycleException e )
+ else
{
- throw new ContinuumException( "Error while releasing task queue executor from container", e );
- }
-
- taskQueueExecutors.remove( buildAgentUrl );
- }
-
- public boolean isBuildAgentBusy( String buildAgentUrl )
- {
- DistributedBuildTaskQueueExecutor executor = taskQueueExecutors.get( buildAgentUrl );
+ log.warn( "No build agent configured. Not building projects." );
- if ( executor != null && executor.getCurrentTask() != null )
- {
- log.info( "build agent '" + buildAgentUrl + "' is busy" );
- return true;
+ throw new NoBuildAgentException( "No build agent configured" );
}
- log.info( "build agent '" + buildAgentUrl + "' is not busy" );
- return false;
+ // call in case we disabled a build agent
+ reload();
}
- private void addTaskQueueExecutor( String url )
+ public void removeDistributedBuildQueueOfAgent( String buildAgentUrl )
throws ContinuumException
{
- try
- {
- DistributedBuildTaskQueueExecutor taskQueueExecutor = (DistributedBuildTaskQueueExecutor) container.
- lookup( DistributedBuildTaskQueueExecutor.class, "distributed-build-project" );
- taskQueueExecutor.setBuildAgentUrl( url );
- taskQueueExecutors.put( url, taskQueueExecutor );
- }
- catch ( ComponentLookupException e )
+ if ( overallDistributedBuildQueues.containsKey( buildAgentUrl ) )
{
- throw new ContinuumException( "Unable to lookup TaskQueueExecutor for distributed-build-project", e );
+ List<PrepareBuildProjectsTask> tasks = null;
+
+ synchronized( overallDistributedBuildQueues )
+ {
+ OverallDistributedBuildQueue overallDistributedBuildQueue = overallDistributedBuildQueues.get( buildAgentUrl );
+
+ try
+ {
+ if ( overallDistributedBuildQueue.getDistributedBuildTaskQueueExecutor().getCurrentTask() != null )
+ {
+ log.error( "Unable to remove build agent because it is currently being used" );
+ throw new ContinuumException( "Unable to remove build agent because it is currently being used" );
+ }
+
+ tasks = overallDistributedBuildQueue.getProjectsInQueue();
+
+ overallDistributedBuildQueue.getDistributedBuildQueue().removeAll( tasks );
+
+ ( (ThreadedDistributedBuildTaskQueueExecutor) overallDistributedBuildQueue.getDistributedBuildTaskQueueExecutor() ).stop();
+
+ container.release( overallDistributedBuildQueue );
+
+ overallDistributedBuildQueues.remove( buildAgentUrl );
+
+ log.info( "remove distributed build queue for build agent '" + buildAgentUrl + "'" );
+ }
+ catch ( TaskQueueException e )
+ {
+ log.error( "Error occurred while removing build agent " + buildAgentUrl, e );
+ throw new ContinuumException( "Error occurred while removing build agent " + buildAgentUrl, e );
+ }
+ catch ( ComponentLifecycleException e )
+ {
+ log.error( "Error occurred while removing build agent " + buildAgentUrl, e );
+ throw new ContinuumException( "Error occurred while removing build agent " + buildAgentUrl, e );
+ }
+ catch ( StoppingException e )
+ {
+ log.error( "Error occurred while removing build agent " + buildAgentUrl, e );
+ throw new ContinuumException( "Error occurred while removing build agent " + buildAgentUrl, e );
+ }
+ }
}
}
- public void cancelDistributedBuild( String buildAgentUrl, int projectGroupId, String scmRootAddress )
+ public Map<String, List<PrepareBuildProjectsTask>> getProjectsInPrepareBuildQueue()
throws ContinuumException
{
- DistributedBuildTaskQueueExecutor taskQueueExecutor = taskQueueExecutors.get( buildAgentUrl );
+ Map<String, List<PrepareBuildProjectsTask>> map = new HashMap<String, List<PrepareBuildProjectsTask>>();
- if ( taskQueueExecutor != null )
+ synchronized( overallDistributedBuildQueues )
{
- if ( taskQueueExecutor.getCurrentTask() != null )
+ for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
{
- if ( taskQueueExecutor.getCurrentTask() instanceof PrepareBuildProjectsTask )
- {
- PrepareBuildProjectsTask currentTask = (PrepareBuildProjectsTask) taskQueueExecutor.getCurrentTask()
- ;
+ List<PrepareBuildProjectsTask> tasks = new ArrayList<PrepareBuildProjectsTask>();
- if ( currentTask.getProjectGroupId() == projectGroupId &&
- currentTask.getScmRootAddress().equals( scmRootAddress ) )
+ try
+ {
+ if ( isAgentAvailable( buildAgentUrl ) )
{
- log.info( "cancelling task for project group " + projectGroupId + " with scm root address " +
- scmRootAddress );
- taskQueueExecutor.cancelTask( currentTask );
+ SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection( buildAgentUrl );
- try
- {
- SlaveBuildAgentTransportClient client =
- new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) );
- client.cancelBuild();
- }
- catch ( Exception e )
+ List<Map<String, Object>> projects = client.getProjectsInPrepareBuildQueue();
+
+ for ( Map<String, Object> context : projects )
{
- log.error( "Error while cancelling build in build agent '" + buildAgentUrl + "'" );
- throw new ContinuumException(
- "Error while cancelling build in build agent '" + buildAgentUrl + "'", e );
+ tasks.add( getPrepareBuildProjectsTask( context ) );
}
- }
- else
- {
- log.info( "current task not for project group " + projectGroupId + " with scm root address " +
- scmRootAddress );
+
+ map.put( buildAgentUrl, tasks );
}
}
- else
+ catch ( MalformedURLException e )
{
- log.info( "current task not a prepare build projects task, not cancelling" );
+ throw new ContinuumException( "Invalid build agent url: " + buildAgentUrl );
+ }
+ catch ( Exception e )
+ {
+ throw new ContinuumException( "Error while retrieving projects in prepare build queue", e );
}
}
- else
- {
- log.info( "no current task in build agent '" + buildAgentUrl + "'" );
- }
- }
- else
- {
- log.info( "no task queue executor defined for build agent '" + buildAgentUrl + "'" );
}
+
+ // call reload in case we disable a build agent
+ reload();
+
+ return map;
}
- public void updateBuildResult( Map<String, Object> context )
+ public Map<String, PrepareBuildProjectsTask> getProjectsCurrentlyPreparingBuild()
throws ContinuumException
{
- try
- {
- int projectId = ContinuumBuildConstant.getProjectId( context );
- int buildDefinitionId = ContinuumBuildConstant.getBuildDefinitionId( context );
-
- log.info( "update build result of project '" + projectId + "'" );
-
- Project project = projectDao.getProjectWithAllDetails( projectId );
- BuildDefinition buildDefinition = buildDefinitionDao.getBuildDefinition( buildDefinitionId );
-
- BuildResult oldBuildResult =
- buildResultDao.getLatestBuildResultForBuildDefinition( projectId, buildDefinitionId );
-
- int buildNumber;
-
- if ( ContinuumBuildConstant.getBuildState( context ) == ContinuumProjectState.OK )
- {
- buildNumber = project.getBuildNumber() + 1;
- }
- else
- {
- buildNumber = project.getBuildNumber();
- }
-
- // ----------------------------------------------------------------------
- // Make the buildResult
- // ----------------------------------------------------------------------
-
- BuildResult buildResult = convertMapToBuildResult( context );
+ Map<String, PrepareBuildProjectsTask> map = new HashMap<String, PrepareBuildProjectsTask>();
- if ( buildResult.getState() != ContinuumProjectState.CANCELLED )
+ synchronized( overallDistributedBuildQueues )
+ {
+ for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
{
- buildResult.setBuildDefinition( buildDefinition );
- buildResult.setBuildNumber( buildNumber );
- buildResult.setModifiedDependencies( getModifiedDependencies( oldBuildResult, context ) );
- buildResult.setScmResult( getScmResult( context ) );
-
- Date date = ContinuumBuildConstant.getLatestUpdateDate( context );
- if ( date != null )
+ try
+ {
+ if ( isAgentAvailable( buildAgentUrl ) )
+ {
+ SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection( buildAgentUrl );
+ Map<String, Object> project = client.getProjectCurrentlyPreparingBuild();
+
+ if ( !project.isEmpty() )
+ {
+ map.put( buildAgentUrl, getPrepareBuildProjectsTask( project ) );
+ }
+ }
+ }
+ catch ( MalformedURLException e )
{
- buildResult.setLastChangedDate( date.getTime() );
+ throw new ContinuumException( "Invalid build agent url: " + buildAgentUrl );
}
- else if ( oldBuildResult != null )
+ catch ( Exception e )
{
- buildResult.setLastChangedDate( oldBuildResult.getLastChangedDate() );
+ throw new ContinuumException( "Error retrieving projects currently preparing build in " + buildAgentUrl, e );
}
-
- buildResultDao.addBuildResult( project, buildResult );
-
- project.setOldState( project.getState() );
- project.setState( ContinuumBuildConstant.getBuildState( context ) );
- project.setBuildNumber( buildNumber );
- project.setLatestBuildId( buildResult.getId() );
- }
- else
- {
- project.setState( project.getOldState() );
- project.setOldState( 0 );
}
+ }
- projectDao.updateProject( project );
-
- File buildOutputFile = configurationService.getBuildOutputFile( buildResult.getId(), project.getId() );
-
- FileWriter fstream = new FileWriter( buildOutputFile );
- BufferedWriter out = new BufferedWriter( fstream );
- out.write( ContinuumBuildConstant.getBuildOutput( context ) == null ? ""
- : ContinuumBuildConstant.getBuildOutput( context ) );
- out.close();
+ // call reload in case we disable a build agent
+ reload();
- if ( buildResult.getState() != ContinuumProjectState.CANCELLED )
- {
- notifierDispatcher.buildComplete( project, buildDefinition, buildResult );
- }
- }
- catch ( ContinuumStoreException e )
- {
- throw new ContinuumException( "Error while updating build result for project", e );
- }
- catch ( ConfigurationException e )
- {
- throw new ContinuumException( "Error retrieving build output file", e );
- }
- catch ( IOException e )
- {
- throw new ContinuumException( "Error while writing build output to file", e );
- }
+ return map;
}
-
- public void prepareBuildFinished( Map<String, Object> context )
+
+ public Map<String, BuildProjectTask> getProjectsCurrentlyBuilding()
throws ContinuumException
{
- int projectGroupId = ContinuumBuildConstant.getProjectGroupId( context );
- String scmRootAddress = ContinuumBuildConstant.getScmRootAddress( context );
+ Map<String, BuildProjectTask> map = new HashMap<String, BuildProjectTask>();
- try
+ synchronized( overallDistributedBuildQueues )
{
- ProjectScmRoot scmRoot =
- projectScmRootDao.getProjectScmRootByProjectGroupAndScmRootAddress( projectGroupId, scmRootAddress );
-
- String error = ContinuumBuildConstant.getScmError( context );
-
- if ( StringUtils.isEmpty( error ) )
+ for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
{
- scmRoot.setState( ContinuumProjectState.UPDATED );
- }
- else
- {
- scmRoot.setState( ContinuumProjectState.ERROR );
- scmRoot.setError( error );
+ try
+ {
+ if ( isAgentAvailable( buildAgentUrl ) )
+ {
+ SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection( buildAgentUrl );
+ Map<String, Object> project = client.getProjectCurrentlyBuilding();
+
+ if ( !project.isEmpty() )
+ {
+ map.put( buildAgentUrl, getBuildProjectTask( project ) );
+ }
+ }
+ }
+ catch ( MalformedURLException e )
+ {
+ throw new ContinuumException( "Invalid build agent url: " + buildAgentUrl );
+ }
+ catch ( Exception e )
+ {
+ throw new ContinuumException( "Error retrieving projects currently building in " + buildAgentUrl, e );
+ }
}
+ }
- projectScmRootDao.updateProjectScmRoot( scmRoot );
+ // call reload in case we disable a build agent
+ reload();
- notifierDispatcher.prepareBuildComplete( scmRoot );
- }
- catch ( ContinuumStoreException e )
- {
- throw new ContinuumException( "Error while updating project scm root '" + scmRootAddress + "'", e );
- }
+ return map;
}
- public Map<String, PrepareBuildProjectsTask> getDistributedBuildProjects()
+ public Map<String, List<BuildProjectTask>> getProjectsInBuildQueue()
+ throws ContinuumException
{
- Map<String, PrepareBuildProjectsTask> map = new HashMap<String, PrepareBuildProjectsTask>();
+ Map<String, List<BuildProjectTask>> map = new HashMap<String, List<BuildProjectTask>>();
- for ( String url : taskQueueExecutors.keySet() )
+ synchronized( overallDistributedBuildQueues )
{
- DistributedBuildTaskQueueExecutor taskQueueExecutor = taskQueueExecutors.get( url );
-
- if ( taskQueueExecutor.getCurrentTask() != null )
+ for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
{
- PrepareBuildProjectsTask task = (PrepareBuildProjectsTask) taskQueueExecutor.getCurrentTask();
+ List<BuildProjectTask> tasks = new ArrayList<BuildProjectTask>();
- map.put( url, task );
+ try
+ {
+ if ( isAgentAvailable( buildAgentUrl ) )
+ {
+ SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection( buildAgentUrl );
+ List<Map<String, Object>> projects = client.getProjectsInBuildQueue();
+
+ for ( Map<String, Object> context : projects )
+ {
+ tasks.add( getBuildProjectTask( context ) );
+ }
+
+ map.put( buildAgentUrl, tasks );
+ }
+ }
+ catch ( MalformedURLException e )
+ {
+ throw new ContinuumException( "Invalid build agent url: " + buildAgentUrl );
+ }
+ catch ( Exception e )
+ {
+ throw new ContinuumException( "Error while retrieving projects in build queue", e );
+ }
}
}
+ // call reload in case we disable a build agent
+ reload();
+
return map;
}
- public List<Installation> getAvailableInstallations( String buildAgentUrl )
- throws ContinuumException
+ public boolean isBuildAgentBusy( String buildAgentUrl )
{
- List<Installation> installations = new ArrayList<Installation>();
-
- try
+ synchronized ( overallDistributedBuildQueues )
{
- SlaveBuildAgentTransportClient client = new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) );
-
- List<Map<String, String>> installationsList = client.getAvailableInstallations();
+ OverallDistributedBuildQueue overallDistributedBuildQueue = overallDistributedBuildQueues.get( buildAgentUrl );
- for ( Map context : installationsList )
+ if ( overallDistributedBuildQueue != null &&
+ overallDistributedBuildQueue.getDistributedBuildTaskQueueExecutor().getCurrentTask() != null )
{
- Installation installation = new Installation();
- installation.setName( ContinuumBuildConstant.getInstallationName( context ) );
- installation.setType( ContinuumBuildConstant.getInstallationType( context ) );
- installation.setVarName( ContinuumBuildConstant.getInstallationVarName( context ) );
- installation.setVarValue( ContinuumBuildConstant.getInstallationVarValue( context ) );
- installations.add( installation );
+ log.info( "build agent '" + buildAgentUrl + "' is busy" );
+ return true;
}
- return installations;
- }
- catch ( Exception e )
- {
- throw new ContinuumException( "Unable to get available installations of build agent", e );
+ log.info( "build agent '" + buildAgentUrl + "' is not busy" );
+ return false;
}
}
- public void startProjectBuild( int projectId )
+ public void cancelDistributedBuild( String buildAgentUrl )
throws ContinuumException
{
try
{
- Project project = projectDao.getProject( projectId );
- project.setState( ContinuumProjectState.BUILDING );
- projectDao.updateProject( project );
- }
- catch ( ContinuumStoreException e )
- {
- log.error( "Error while updating project's state", e );
- throw new ContinuumException( "Error while updating project's state", e );
- }
- }
+ if ( isAgentAvailable( buildAgentUrl ) )
+ {
+ SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection( buildAgentUrl );
+
+ client.cancelBuild();
+ }
- public void startPrepareBuild( Map<String, Object> context )
- throws ContinuumException
- {
- try
+ // call reload in case we disable the build agent
+ reload();
+ }
+ catch ( MalformedURLException e )
{
- int projectGroupId = ContinuumBuildConstant.getProjectGroupId( context );
- String scmRootAddress = ContinuumBuildConstant.getScmRootAddress( context );
-
- ProjectScmRoot scmRoot =
- projectScmRootDao.getProjectScmRootByProjectGroupAndScmRootAddress( projectGroupId, scmRootAddress );
- scmRoot.setOldState( scmRoot.getState() );
- scmRoot.setState( ContinuumProjectState.UPDATING );
- projectScmRootDao.updateProjectScmRoot( scmRoot );
+ log.error( "Error cancelling build in build agent: Invalid build agent url " + buildAgentUrl );
+ throw new ContinuumException( "Error cancelling build in build agent: Invalid build agent url " + buildAgentUrl );
}
- catch ( ContinuumStoreException e )
+ catch ( Exception e )
{
- log.error( "Error while updating project scm root's state", e );
- throw new ContinuumException( "Error while updating project scm root's state", e );
+ log.error( "Error occurred while cancelling build in build agent " + buildAgentUrl, e );
+ throw new ContinuumException( "Error occurred while cancelling build in build agent " + buildAgentUrl, e );
}
}
@@ -567,30 +551,33 @@ public class DefaultDistributedBuildMana
try
{
- SlaveBuildAgentTransportClient client = new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) );
+ if ( isAgentAvailable( buildAgentUrl ) )
+ {
+ SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection( buildAgentUrl );
- Map result = client.getBuildResult( projectId );
+ Map<String, Object> result = client.getBuildResult( projectId );
- if ( result != null )
- {
- int buildDefinitionId = ContinuumBuildConstant.getBuildDefinitionId( result );
+ if ( result != null )
+ {
+ int buildDefinitionId = ContinuumBuildConstant.getBuildDefinitionId( result );
- Project project = projectDao.getProjectWithAllDetails( projectId );
- BuildDefinition buildDefinition = buildDefinitionDao.getBuildDefinition( buildDefinitionId );
+ Project project = projectDao.getProjectWithAllDetails( projectId );
+ BuildDefinition buildDefinition = buildDefinitionDao.getBuildDefinition( buildDefinitionId );
- BuildResult oldBuildResult =
- buildResultDao.getLatestBuildResultForBuildDefinition( projectId, buildDefinitionId );
+ BuildResult oldBuildResult =
+ buildResultDao.getLatestBuildResultForBuildDefinition( projectId, buildDefinitionId );
- BuildResult buildResult = convertMapToBuildResult( result );
- buildResult.setBuildDefinition( buildDefinition );
- buildResult.setBuildNumber( project.getBuildNumber() + 1 );
- buildResult.setModifiedDependencies( getModifiedDependencies( oldBuildResult, result ) );
- buildResult.setScmResult( getScmResult( result ) );
+ BuildResult buildResult = distributedBuildUtil.convertMapToBuildResult( result );
+ buildResult.setBuildDefinition( buildDefinition );
+ buildResult.setBuildNumber( project.getBuildNumber() + 1 );
+ buildResult.setModifiedDependencies( distributedBuildUtil.getModifiedDependencies( oldBuildResult, result ) );
+ buildResult.setScmResult( distributedBuildUtil.getScmResult( result ) );
- String buildOutput = ContinuumBuildConstant.getBuildOutput( result );
+ String buildOutput = ContinuumBuildConstant.getBuildOutput( result );
- map.put( ContinuumBuildConstant.KEY_BUILD_RESULT, buildResult );
- map.put( ContinuumBuildConstant.KEY_BUILD_OUTPUT, buildOutput );
+ map.put( ContinuumBuildConstant.KEY_BUILD_RESULT, buildResult );
+ map.put( ContinuumBuildConstant.KEY_BUILD_OUTPUT, buildOutput );
+ }
}
}
catch ( MalformedURLException e )
@@ -602,92 +589,44 @@ public class DefaultDistributedBuildMana
throw new ContinuumException( "Error while retrieving build result for project" + projectId, e );
}
+ // call reload in case we disable the build agent
+ reload();
+
return map;
}
- public Map<String, String> getEnvironments( int buildDefinitionId, String installationType )
+ public List<Installation> getAvailableInstallations( String buildAgentUrl )
throws ContinuumException
{
- BuildDefinition buildDefinition;
+ List<Installation> installations = new ArrayList<Installation>();
try
{
- buildDefinition = buildDefinitionDao.getBuildDefinition( buildDefinitionId );
- }
- catch ( ContinuumStoreException e )
- {
- throw new ContinuumException( "Failed to retrieve build definition: " + buildDefinitionId, e );
- }
-
- Profile profile = buildDefinition.getProfile();
- if ( profile == null )
- {
- return Collections.EMPTY_MAP;
- }
- Map<String, String> envVars = new HashMap<String, String>();
- String javaHome = getJavaHomeValue( buildDefinition );
- if ( !StringUtils.isEmpty( javaHome ) )
- {
- envVars.put( installationService.getEnvVar( InstallationService.JDK_TYPE ), javaHome );
- }
- Installation builder = profile.getBuilder();
- if ( builder != null )
- {
- envVars.put( installationService.getEnvVar( installationType ), builder.getVarValue() );
- }
- envVars.putAll( getEnvironmentVariables( buildDefinition ) );
- return envVars;
- }
+ if ( isAgentAvailable( buildAgentUrl ) )
+ {
+ SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection( buildAgentUrl );
- public void updateProject( Map<String, Object> context )
- throws ContinuumException
- {
- try
- {
- Project project = projectDao.getProject( ContinuumBuildConstant.getProjectId( context ) );
+ List<Map<String, String>> installationsList = client.getAvailableInstallations();
- if ( StringUtils.isNotBlank( ContinuumBuildConstant.getGroupId( context ) ) )
- {
- project.setGroupId( ContinuumBuildConstant.getGroupId( context ) );
- }
- if ( StringUtils.isNotBlank( ContinuumBuildConstant.getArtifactId( context ) ) )
- {
- project.setArtifactId( ContinuumBuildConstant.getArtifactId( context ) );
- }
- if ( StringUtils.isNotBlank( ContinuumBuildConstant.getVersion( context ) ) )
- {
- project.setVersion( ContinuumBuildConstant.getVersion( context ) );
- }
- if ( StringUtils.isNotBlank( ContinuumBuildConstant.getProjectName( context ) ) )
- {
- project.setName( ContinuumBuildConstant.getProjectName( context ) );
- }
- if ( StringUtils.isNotBlank( ContinuumBuildConstant.getProjectDescription( context ) ) )
- {
- project.setDescription( ContinuumBuildConstant.getProjectDescription( context ) );
- }
- if ( StringUtils.isNotBlank( ContinuumBuildConstant.getProjectUrl( context ) ) )
- {
- project.setUrl( ContinuumBuildConstant.getProjectUrl( context ) );
- }
- if ( StringUtils.isNotBlank( ContinuumBuildConstant.getScmUrl( context ) ) )
- {
- project.setScmUrl( ContinuumBuildConstant.getScmUrl( context ) );
- }
- if ( StringUtils.isNotBlank( ContinuumBuildConstant.getScmTag( context ) ) )
- {
- project.setScmTag( ContinuumBuildConstant.getScmTag( context ) );
+ for ( Map context : installationsList )
+ {
+ Installation installation = new Installation();
+ installation.setName( ContinuumBuildConstant.getInstallationName( context ) );
+ installation.setType( ContinuumBuildConstant.getInstallationType( context ) );
+ installation.setVarName( ContinuumBuildConstant.getInstallationVarName( context ) );
+ installation.setVarValue( ContinuumBuildConstant.getInstallationVarValue( context ) );
+ installations.add( installation );
+ }
}
- project.setParent( getProjectParent( context ) );
- project.setDependencies( getProjectDependencies( context ) );
- project.setDevelopers( getProjectDevelopers( context ) );
- project.setNotifiers( getProjectNotifiers( context ) );
- projectDao.updateProject( project );
+ // call reload in case we disable the build agent
+ reload();
+
+ return installations;
}
- catch ( ContinuumStoreException e )
+ catch ( Exception e )
{
- throw new ContinuumException( "Unable to update project from working copy", e );
+ throw new ContinuumException( "Unable to get available installations of build agent", e );
}
}
@@ -712,8 +651,11 @@ public class DefaultDistributedBuildMana
directory = "";
}
- SlaveBuildAgentTransportClient client = new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) );
- return client.generateWorkingCopyContent( projectId, directory, baseUrl, imageBaseUrl );
+ if ( isAgentAvailable( buildAgentUrl ) )
+ {
+ SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection( buildAgentUrl );
+ return client.generateWorkingCopyContent( projectId, directory, baseUrl, imageBaseUrl );
+ }
}
catch ( MalformedURLException e )
{
@@ -724,9 +666,13 @@ public class DefaultDistributedBuildMana
log.error( "Error while generating working copy content from build agent " + buildAgentUrl, e );
}
}
+
+ // call reload in case we disable the build agent
+ reload();
+
return "";
}
-
+
public String getFileContent( int projectId, String directory, String filename )
throws ContinuumException
{
@@ -743,8 +689,11 @@ public class DefaultDistributedBuildMana
try
{
- SlaveBuildAgentTransportClient client = new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) );
- return client.getProjectFileContent( projectId, directory, filename );
+ if ( isAgentAvailable( buildAgentUrl ) )
+ {
+ SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection( buildAgentUrl );
+ return client.getProjectFileContent( projectId, directory, filename );
+ }
}
catch ( MalformedURLException e )
{
@@ -755,561 +704,797 @@ public class DefaultDistributedBuildMana
log.error( "Error while retrieving content of " + filename, e );
}
}
+
+ // call reload in case we disable the build agent
+ reload();
+
return "";
}
- public boolean shouldBuild( Map<String, Object> context )
+ public void removeFromPrepareBuildQueue( String buildAgentUrl, int projectGroupId, int scmRootId )
+ throws ContinuumException
{
try
{
- int projectId = ContinuumBuildConstant.getProjectId( context );
-
- int buildDefinitionId = ContinuumBuildConstant.getBuildDefinitionId( context );
-
- int trigger = ContinuumBuildConstant.getTrigger( context );
-
- Project project = projectDao.getProjectWithAllDetails( projectId );
-
- BuildDefinition buildDefinition = buildDefinitionDao.getBuildDefinition( buildDefinitionId );
-
- BuildResult oldBuildResult =
- buildResultDao.getLatestBuildResultForBuildDefinition( projectId, buildDefinitionId );
-
- List<ProjectDependency> modifiedDependencies = getModifiedDependencies( oldBuildResult, context );
-
- List<ChangeSet> changes = getScmChanges( context );
-
- if ( buildDefinition.isBuildFresh() )
+ if ( isAgentAvailable( buildAgentUrl ) )
{
- log.info( "FreshBuild configured, building" );
- return true;
- }
- if ( buildDefinition.isAlwaysBuild() )
- {
- log.info( "AlwaysBuild configured, building" );
- return true;
- }
- if ( oldBuildResult == null )
- {
- log.info( "The project was never be built with the current build definition, building" );
- return true;
+ SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection( buildAgentUrl );
+ client.removeFromPrepareBuildQueue( projectGroupId, scmRootId );
}
+ }
+ catch ( MalformedURLException e )
+ {
+ log.error( "Unable to remove projectGroupId=" + projectGroupId + " scmRootId=" + scmRootId +
+ " from prepare build queue: Invalid build agent url " + buildAgentUrl );
+ throw new ContinuumException( "Unable to remove projectGroupId=" + projectGroupId + " scmRootId=" + scmRootId +
+ " from prepare build queue: Invalid build agent url " + buildAgentUrl );
+ }
+ catch ( Exception e )
+ {
+ log.error( "Error occurred while removing projectGroupId=" + projectGroupId + " scmRootId=" + scmRootId +
+ " from prepare build queue of agent " + buildAgentUrl, e );
+ throw new ContinuumException( "Error occurred while removing projectGroupId=" + projectGroupId + " scmRootId=" +
+ scmRootId + " from prepare build queue of agent " + buildAgentUrl, e );
+ }
- //CONTINUUM-1428
- if ( project.getOldState() == ContinuumProjectState.ERROR ||
- oldBuildResult.getState() == ContinuumProjectState.ERROR )
- {
- log.info( "Latest state was 'ERROR', building" );
- return true;
- }
+ // call reload in case we disable the build agent
+ reload();
+ }
- if ( trigger == ContinuumProjectState.TRIGGER_FORCED )
+ public void removeFromBuildQueue( String buildAgentUrl, int projectId, int buildDefinitionId )
+ throws ContinuumException
+ {
+ try
+ {
+ if ( isAgentAvailable( buildAgentUrl ) )
{
- log.info( "The project build is forced, building" );
- return true;
+ SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection( buildAgentUrl );
+ client.removeFromBuildQueue( projectId, buildDefinitionId );
}
+ }
+ catch ( MalformedURLException e )
+ {
+ log.error( "Unable to remove project " + projectId +
+ " from build queue: Invalid build agent url " + buildAgentUrl );
+ throw new ContinuumException( "Unable to remove project " + projectId +
+ " from build queue: Invalid build agent url " + buildAgentUrl );
+ }
+ catch ( Exception e )
+ {
+ log.error( "Error occurred while removing project " + projectId +
+ " from build queue of agent " + buildAgentUrl, e );
+ throw new ContinuumException( "Error occurred while removing project " + projectId +
+ " from build queue of agent " + buildAgentUrl, e );
+ }
- Date date = ContinuumBuildConstant.getLatestUpdateDate( context );
- if ( date != null && oldBuildResult.getLastChangedDate() >= date.getTime() )
+ // call reload in case we disable the build agent
+ reload();
+ }
+
+ public void removeFromPrepareBuildQueue( List<String> hashCodes )
+ throws ContinuumException
+ {
+ synchronized ( overallDistributedBuildQueues )
+ {
+ for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
{
- log.info( "No changes found,not building" );
- return false;
+ try
+ {
+ if ( isAgentAvailable( buildAgentUrl ) )
+ {
+ SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection( buildAgentUrl );
+ client.removeFromPrepareBuildQueue( hashCodes );
+ }
+ }
+ catch ( MalformedURLException e )
+ {
+ log.error( "Error trying to remove projects from prepare build queue. Invalid build agent url: " + buildAgentUrl );
+ }
+ catch ( Exception e )
+ {
+ log.error( "Error trying to remove projects from prepare build queue of agent " + buildAgentUrl, e );
+ }
}
- else if ( date != null && changes.isEmpty() )
+ }
+
+ // call reload in case we disable a build agent
+ reload();
+ }
+
+ public void removeFromBuildQueue( List<String> hashCodes )
+ throws ContinuumException
+ {
+ synchronized ( overallDistributedBuildQueues )
+ {
+ for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
{
- // fresh checkout from build agent that's why changes is empty
- log.info( "Changes found in the current project, building" );
- return true;
+ try
+ {
+ if ( isAgentAvailable( buildAgentUrl ) )
+ {
+ SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection( buildAgentUrl );
+ client.removeFromBuildQueue( hashCodes );
+ }
+ }
+ catch ( MalformedURLException e )
+ {
+ log.error( "Error trying to remove projects from build queue. Invalid build agent url: " + buildAgentUrl );
+ }
+ catch ( Exception e )
+ {
+ log.error( "Error trying to remove projects from build queue of agent " + buildAgentUrl, e );
+ }
}
+ }
- boolean shouldBuild = false;
+ // call reload in case we disable a build agent
+ reload();
+ }
- boolean allChangesUnknown = true;
+ public boolean isProjectInAnyPrepareBuildQueue( int projectId, int buildDefinitionId )
+ throws ContinuumException
+ {
+ boolean found = false;
- if ( project.getOldState() != ContinuumProjectState.NEW &&
- project.getOldState() != ContinuumProjectState.CHECKEDOUT &&
- project.getState() != ContinuumProjectState.NEW &&
- project.getState() != ContinuumProjectState.CHECKEDOUT )
+ synchronized( overallDistributedBuildQueues )
+ {
+ for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
{
- // Check SCM changes
- allChangesUnknown = checkAllChangesUnknown( changes );
-
- if ( allChangesUnknown )
+ try
{
- if ( !changes.isEmpty() )
+ if ( isAgentAvailable( buildAgentUrl ) )
{
- log.info(
- "The project was not built because all changes are unknown (maybe local modifications or ignored files not defined in your SCM tool." );
+ SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection( buildAgentUrl );
+
+ List<Map<String, Object>> projects = client.getProjectsAndBuildDefinitionsInPrepareBuildQueue();
+
+ for ( Map<String, Object> context : projects )
+ {
+ int pid = ContinuumBuildConstant.getProjectId( context );
+ int buildId = ContinuumBuildConstant.getBuildDefinitionId( context );
+
+ if ( pid == projectId && buildId == buildDefinitionId )
+ {
+ found = true;
+ break;
+ }
+
+ }
}
- else
+
+ if ( found )
{
- log.info(
- "The project was not built because no changes were detected in sources since the last build." );
+ break;
}
}
-
- // Check dependencies changes
- if ( modifiedDependencies != null && !modifiedDependencies.isEmpty() )
+ catch ( MalformedURLException e )
{
- log.info( "Found dependencies changes, building" );
- shouldBuild = true;
+ throw new ContinuumException( "Invalid build agent url: " + buildAgentUrl );
+ }
+ catch ( Exception e )
+ {
+ throw new ContinuumException( "Error while retrieving projects in prepare build queue", e );
}
}
+ }
- // Check changes
- if ( !shouldBuild && ( ( !allChangesUnknown && !changes.isEmpty() ) ||
- project.getExecutorId().equals( ContinuumBuildExecutorConstants.MAVEN_TWO_BUILD_EXECUTOR ) ) )
- {
- shouldBuild = shouldBuild( changes, buildDefinition, project, getMavenProjectVersion( context ),
- getMavenProjectModules( context ) );
- }
-
- if ( shouldBuild )
- {
- log.info( "Changes found in the current project, building" );
- }
- else
- {
- log.info( "No changes in the current project, not building" );
- }
+ // call reload in case we disable a build agent
+ reload();
- return shouldBuild;
+ if ( found )
+ {
+ return true;
}
- catch ( ContinuumStoreException e )
+ else
{
- log.error( "Failed to determine if project should build", e );
+ return false;
}
- catch ( ContinuumException e )
+ }
+
+ public boolean isProjectInAnyBuildQueue( int projectId, int buildDefinitionId )
+ throws ContinuumException
+ {
+ Map<String, List<BuildProjectTask>> map = getProjectsInBuildQueue();
+
+ for ( String url : map.keySet() )
{
- log.error( "Failed to determine if project should build", e );
+ for ( BuildProjectTask task : map.get( url ) )
+ {
+ if ( task.getProjectId() == projectId && task.getBuildDefinitionId() == buildDefinitionId )
+ {
+ return true;
+ }
+ }
}
return false;
}
- private boolean shouldBuild( List<ChangeSet> changes, BuildDefinition buildDefinition, Project project,
- String mavenProjectVersion, List<String> mavenProjectModules )
+ public boolean isProjectCurrentlyPreparingBuild( int projectId, int buildDefinitionId )
+ throws ContinuumException
{
- //Check if it's a recursive build
- boolean isRecursive = false;
- if ( StringUtils.isNotEmpty( buildDefinition.getArguments() ) )
- {
- isRecursive = buildDefinition.getArguments().indexOf( "-N" ) < 0 &&
- buildDefinition.getArguments().indexOf( "--non-recursive" ) < 0;
- }
+ boolean found = false;
- if ( isRecursive && changes != null && !changes.isEmpty() )
+ synchronized( overallDistributedBuildQueues )
{
- if ( log.isInfoEnabled() )
+ for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
{
- log.info( "recursive build and changes found --> building" );
+ try
+ {
+ if ( isAgentAvailable( buildAgentUrl ) )
+ {
+ SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection( buildAgentUrl );
+ List<Map<String, Object>> projects = client.getProjectsAndBuildDefinitionsCurrentlyPreparingBuild();
+
+ for ( Map<String, Object> context : projects )
+ {
+ int pid = ContinuumBuildConstant.getProjectId( context );
+ int buildId = ContinuumBuildConstant.getBuildDefinitionId( context );
+
+ if ( pid == projectId && buildId == buildDefinitionId )
+ {
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if ( found )
+ {
+ break;
+ }
+ }
+ catch ( MalformedURLException e )
+ {
+ throw new ContinuumException( "Invalid build agent url: " + buildAgentUrl );
+ }
+ catch ( Exception e )
+ {
+ throw new ContinuumException( "Error retrieving projects currently preparing build in " + buildAgentUrl, e );
+ }
}
- return true;
}
- if ( !project.getVersion().equals( mavenProjectVersion ) )
+ // call reload in case we disable a build agent
+ reload();
+
+ if ( found )
{
- log.info( "Found changes in project's version ( maybe project was recently released ), building" );
return true;
}
-
- if ( changes == null || changes.isEmpty() )
+ else
{
- if ( log.isInfoEnabled() )
- {
- log.info( "Found no changes, not building" );
- }
return false;
}
+ }
- //check if changes are only in sub-modules or not
- List<ChangeFile> files = new ArrayList<ChangeFile>();
- for ( ChangeSet changeSet : changes )
- {
- files.addAll( changeSet.getFiles() );
- }
+ public boolean isProjectCurrentlyBuilding( int projectId, int buildDefinitionId )
+ throws ContinuumException
+ {
+ Map<String, BuildProjectTask> map = getProjectsCurrentlyBuilding();
- int i = 0;
- while ( i <= files.size() - 1 )
+ for ( String url : map.keySet() )
{
- ChangeFile file = files.get( i );
- if ( log.isDebugEnabled() )
+ BuildProjectTask task = map.get( url );
+
+ if ( task.getProjectId() == projectId && task.getBuildDefinitionId() == buildDefinitionId )
{
- log.debug( "changeFile.name " + file.getName() );
- log.debug( "check in modules " + mavenProjectModules );
+ return true;
}
- boolean found = false;
- if ( mavenProjectModules != null )
+ }
+
+ return false;
+ }
+
+ private String getBuildAgent( int projectId )
+ throws ContinuumException
+ {
+ String agentUrl = null;
+
+ synchronized( overallDistributedBuildQueues )
+ {
+ for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
{
- for ( String module : mavenProjectModules )
+ OverallDistributedBuildQueue overallDistributedBuildQueue =
+ overallDistributedBuildQueues.get( buildAgentUrl );
+
+ if ( overallDistributedBuildQueue != null )
{
- if ( file.getName().indexOf( module ) >= 0 )
+ try
{
- if ( log.isDebugEnabled() )
+ if ( isAgentAvailable( buildAgentUrl ) )
{
- log.debug( "changeFile.name " + file.getName() + " removed because in a module" );
+ SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection( buildAgentUrl );
+
+ if ( client.isProjectCurrentlyBuilding( projectId ) )
+ {
+ agentUrl = buildAgentUrl;
+ break;
+ }
}
- files.remove( file );
- found = true;
- break;
}
- if ( log.isDebugEnabled() )
+ catch ( MalformedURLException e )
+ {
+ log.warn( "Unable to check if project " + projectId + " is currently building in agent: Invalid build agent url" + buildAgentUrl );
+ }
+ catch ( Exception e )
{
- log.debug( "not removing file " + file.getName() + " not in module " + module );
+ log.warn( "Unable to check if project " + projectId + " is currently building in agent", e );
}
}
}
- if ( !found )
- {
- i++;
- }
}
- boolean shouldBuild = !files.isEmpty();
+ // call reload in case we disable a build agent
+ reload();
- if ( !shouldBuild )
- {
- log.info( "Changes are only in sub-modules." );
- }
+ return agentUrl;
+ }
- if ( log.isDebugEnabled() )
+ private void createDistributedBuildQueueForAgent( String buildAgentUrl )
+ throws ComponentLookupException
+ {
+ if ( !overallDistributedBuildQueues.containsKey( buildAgentUrl ) )
{
- log.debug( "shoulbuild = " + shouldBuild );
- }
+ OverallDistributedBuildQueue overallDistributedBuildQueue =
+ (OverallDistributedBuildQueue) container.lookup( OverallDistributedBuildQueue.class );
+ overallDistributedBuildQueue.setBuildAgentUrl( buildAgentUrl );
+ overallDistributedBuildQueue.getDistributedBuildTaskQueueExecutor().setBuildAgentUrl( buildAgentUrl );
- return shouldBuild;
+ overallDistributedBuildQueues.put( buildAgentUrl, overallDistributedBuildQueue );
+ }
}
- private boolean checkAllChangesUnknown( List<ChangeSet> changes )
+ private OverallDistributedBuildQueue getOverallDistributedBuildQueueByGroupAndScmRoot( int projectGroupId, int scmRootId )
+ throws ContinuumException
{
- for ( ChangeSet changeSet : changes )
+ synchronized( overallDistributedBuildQueues )
{
- List<ChangeFile> changeFiles = changeSet.getFiles();
-
- for ( ChangeFile changeFile : changeFiles )
+ for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
{
- if ( !"unknown".equalsIgnoreCase( changeFile.getStatus() ) )
+ OverallDistributedBuildQueue distributedBuildQueue = overallDistributedBuildQueues.get( buildAgentUrl );
+
+ try
{
- return false;
+ for ( PrepareBuildProjectsTask task : distributedBuildQueue.getProjectsInQueue() )
+ {
+ if ( task.getProjectGroupId() == projectGroupId && task.getProjectScmRootId() == scmRootId )
+ {
+ return distributedBuildQueue;
+ }
+ }
+ }
+ catch ( TaskQueueException e )
+ {
+ log.error( "Error occurred while retrieving distributed build queue of projectGroupId=" + projectGroupId + " scmRootId=" + scmRootId, e );
+ throw new ContinuumException( "Error occurred while retrieving distributed build queue of group", e );
}
}
}
- return true;
+ return null;
}
- private List<ProjectDependency> getModifiedDependencies( BuildResult oldBuildResult, Map<String, Object> context )
+ private OverallDistributedBuildQueue getOverallDistributedBuildQueueByScmRoot( ProjectScmRoot scmRoot, int projectGroupId )
throws ContinuumException
{
- if ( oldBuildResult == null )
- {
- return null;
- }
+ int scmRootId = scmRoot.getId();
- try
+ synchronized( overallDistributedBuildQueues )
{
- Project project = projectDao.getProjectWithAllDetails( ContinuumBuildConstant.getProjectId( context ) );
- List<ProjectDependency> dependencies = project.getDependencies();
-
- if ( dependencies == null )
- {
- dependencies = new ArrayList<ProjectDependency>();
- }
-
- if ( project.getParent() != null )
+ for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
{
- dependencies.add( project.getParent() );
- }
+ OverallDistributedBuildQueue distributedBuildQueue = overallDistributedBuildQueues.get( buildAgentUrl );
- if ( dependencies.isEmpty() )
- {
- return null;
- }
-
- List<ProjectDependency> modifiedDependencies = new ArrayList<ProjectDependency>();
-
- for ( ProjectDependency dep : dependencies )
- {
- Project dependencyProject =
- projectDao.getProject( dep.getGroupId(), dep.getArtifactId(), dep.getVersion() );
-
- if ( dependencyProject != null )
+ try
{
- List<BuildResult> buildResults =
- buildResultDao.getBuildResultsInSuccessForProject( dependencyProject.getId(),
- oldBuildResult.getEndTime() );
- if ( buildResults != null && !buildResults.isEmpty() )
+ for ( PrepareBuildProjectsTask task : distributedBuildQueue.getProjectsInQueue() )
{
- log.debug( "Dependency changed: " + dep.getGroupId() + ":" + dep.getArtifactId() + ":" +
- dep.getVersion() );
- modifiedDependencies.add( dep );
+ if ( task.getProjectScmRootId() == scmRootId )
+ {
+ return distributedBuildQueue;
+ }
}
- else
+
+ Task task = distributedBuildQueue.getDistributedBuildTaskQueueExecutor().getCurrentTask();
+ if ( task != null && ( (PrepareBuildProjectsTask) task ).getProjectScmRootId() == scmRootId )
{
- log.debug( "Dependency not changed: " + dep.getGroupId() + ":" + dep.getArtifactId() + ":" +
- dep.getVersion() );
+ return distributedBuildQueue;
+ }
+
+ if ( isAgentAvailable( buildAgentUrl ) )
+ {
+ List<Project> projects = projectDao.getProjectsInGroup( projectGroupId );
+ List<Integer> pIds = new ArrayList<Integer>();
+
+ for ( Project project : projects )
+ {
+ if ( project.getScmUrl().startsWith( scmRoot.getScmRootAddress() ) )
+ {
+ pIds.add( project.getId() );
+ }
+ }
+
+ SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection( buildAgentUrl );
+
+ if ( client.isProjectScmRootInQueue( scmRootId, pIds ) )
+ {
+ return distributedBuildQueue;
+ }
}
}
- else
+ catch ( TaskQueueException e )
+ {
+ log.error( "Error occurred while retrieving distributed build queue of scmRootId=" + scmRootId, e );
+ throw new ContinuumException( "Error occurred while retrieving distributed build queue of scmRoot", e );
+ }
+ catch ( MalformedURLException e )
+ {
+ log.error( "Error occurred while retrieving distributed build queue of scmRootId=" + scmRootId +
+ ": Invalid build agent url " + buildAgentUrl );
+ throw new ContinuumException( "Error occurred while retrieving distributed build queue of scmRootId=" + scmRootId +
+ ": Invalid build agent url " + buildAgentUrl );
+ }
+ catch ( Exception e )
{
- log.debug( "Skip non Continuum project: " + dep.getGroupId() + ":" + dep.getArtifactId() + ":" +
- dep.getVersion() );
+ log.error( "Error occurred while retrieving distributed build queue of scmRootId=" + scmRootId, e );
+ throw new ContinuumException( "Error occurred while retrieving distributed build queue of scmRoot", e );
}
}
-
- return modifiedDependencies;
- }
- catch ( ContinuumStoreException e )
- {
- log.warn( "Can't get the project dependencies", e );
}
return null;
}
- private String getBuildAgent( int projectId )
+ private OverallDistributedBuildQueue getOverallDistributedBuildQueueByGroup( int projectGroupId, List<ProjectScmRoot> scmRoots, int scmRootId )
throws ContinuumException
{
- Map<String, PrepareBuildProjectsTask> map = getDistributedBuildProjects();
-
- for ( String url : map.keySet() )
+ if ( scmRoots != null )
{
- PrepareBuildProjectsTask task = map.get( url );
-
- for ( Integer id : task.getProjectsBuildDefinitionsMap().keySet() )
+ for ( ProjectScmRoot scmRoot : scmRoots )
{
- if ( projectId == id )
+ if ( scmRoot.getId() == scmRootId )
{
- return url;
+ break;
+ }
+ else if ( scmRoot.getProjectGroup().getId() == projectGroupId )
+ {
+ return getOverallDistributedBuildQueueByScmRoot( scmRoot, projectGroupId );
}
}
}
-
return null;
}
- private BuildResult convertMapToBuildResult( Map<String, Object> context )
- {
- BuildResult buildResult = new BuildResult();
-
- buildResult.setStartTime( ContinuumBuildConstant.getStartTime( context ) );
- buildResult.setEndTime( ContinuumBuildConstant.getEndTime( context ) );
- buildResult.setError( ContinuumBuildConstant.getBuildError( context ) );
- buildResult.setExitCode( ContinuumBuildConstant.getBuildExitCode( context ) );
- buildResult.setState( ContinuumBuildConstant.getBuildState( context ) );
- buildResult.setTrigger( ContinuumBuildConstant.getTrigger( context ) );
- buildResult.setBuildUrl( ContinuumBuildConstant.getBuildAgentUrl( context ) );
-
- return buildResult;
- }
-
- private String getJavaHomeValue( BuildDefinition buildDefinition )
+ // need to change this
+ private OverallDistributedBuildQueue getOverallDistributedBuildQueueByHashCode( int hashCode )
+ throws ContinuumException
{
- Profile profile = buildDefinition.getProfile();
- if ( profile == null )
- {
- return null;
- }
- Installation jdk = profile.getJdk();
- if ( jdk == null )
+ synchronized( overallDistributedBuildQueues )
{
- return null;
- }
- return jdk.getVarValue();
- }
+ for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
+ {
+ OverallDistributedBuildQueue distributedBuildQueue = overallDistributedBuildQueues.get( buildAgentUrl );
- private Map<String, String> getEnvironmentVariables( BuildDefinition buildDefinition )
- {
- Profile profile = buildDefinition.getProfile();
- Map<String, String> envVars = new HashMap<String, String>();
- if ( profile == null )
- {
- return envVars;
- }
- List<Installation> environmentVariables = profile.getEnvironmentVariables();
- if ( environmentVariables.isEmpty() )
- {
- return envVars;
- }
- for ( Installation installation : environmentVariables )
- {
- envVars.put( installation.getVarName(), installation.getVarValue() );
+ try
+ {
+ for ( PrepareBuildProjectsTask task : distributedBuildQueue.getProjectsInQueue() )
+ {
+ if ( task.getHashCode() == hashCode )
+ {
+ return distributedBuildQueue;
+ }
+ }
+ }
+ catch ( TaskQueueException e )
+ {
+ log.error( "Error occurred while retrieving distributed build queue", e );
+ throw new ContinuumException( "Error occurred while retrieving distributed build queue", e );
+ }
+ }
}
- return envVars;
+
+ return null;
}
- private List<ChangeSet> getScmChanges( Map<String, Object> context )
+ private OverallDistributedBuildQueue getOverallDistributedBuildQueueByAgentGroup( Map<Integer, Integer> projectsAndBuildDefinitionsMap )
+ throws ContinuumException
{
- List<ChangeSet> changes = new ArrayList<ChangeSet>();
- List<Map> scmChanges = ContinuumBuildConstant.getScmChanges( context );
+ OverallDistributedBuildQueue whereToBeQueued = null;
+
+ BuildAgentGroupConfiguration buildAgentGroup = getBuildAgentGroup( projectsAndBuildDefinitionsMap );
- if ( scmChanges != null )
+ if ( buildAgentGroup != null )
{
- for ( Map map : scmChanges )
+ List<BuildAgentConfiguration> buildAgents = buildAgentGroup.getBuildAgents();
+
+ if ( buildAgents != null && buildAgents.size() > 0 )
{
- ChangeSet changeSet = new ChangeSet();
- changeSet.setAuthor( ContinuumBuildConstant.getChangeSetAuthor( map ) );
- changeSet.setComment( ContinuumBuildConstant.getChangeSetComment( map ) );
- changeSet.setDate( ContinuumBuildConstant.getChangeSetDate( map ) );
- setChangeFiles( changeSet, map );
- changes.add( changeSet );
+ List<String> buildAgentUrls = new ArrayList<String>();
+
+ for ( BuildAgentConfiguration buildAgent : buildAgents )
+ {
+ buildAgentUrls.add( buildAgent.getUrl() );
+ }
+
+ synchronized( overallDistributedBuildQueues )
+ {
+ int idx = 0;
+ int size = 0;
+
+ for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
+ {
+ if ( !buildAgentUrls.isEmpty() && buildAgentUrls.contains( buildAgentUrl ) )
+ {
+ OverallDistributedBuildQueue distributedBuildQueue = overallDistributedBuildQueues.get( buildAgentUrl );
+
+ if ( distributedBuildQueue != null )
+ {
+ try
+ {
+ if ( isAgentAvailable( buildAgentUrl ) )
+ {
+ SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection( buildAgentUrl );
+ int agentBuildSize = client.getBuildSizeOfAgent();
+
+ if ( idx == 0 )
+ {
+ whereToBeQueued = distributedBuildQueue;
+ size = agentBuildSize;
+ idx++;
+ }
+
+ if ( agentBuildSize < size )
+ {
+ whereToBeQueued = distributedBuildQueue;
+ size = agentBuildSize;
+ }
+ }
+ }
+ catch ( MalformedURLException e )
+ {
+ log.error( "Error occurred while retrieving distributed build queue: Invalid build agent url " + buildAgentUrl );
+ }
+ catch ( Exception e )
+ {
+ log.error( "Error occurred while retrieving distributed build queue ", e );
+ }
+ }
+ }
+ }
+ }
}
}
- return changes;
+ return whereToBeQueued;
}
- private void setChangeFiles( ChangeSet changeSet, Map<String, Object> context )
+ private OverallDistributedBuildQueue getOverallDistributedBuildQueue()
+ throws ContinuumException
{
- List<Map> changeFiles = ContinuumBuildConstant.getChangeSetFiles( context );
+ OverallDistributedBuildQueue whereToBeQueued = null;
- if ( changeFiles != null )
+ synchronized ( overallDistributedBuildQueues )
{
- for ( Map map : changeFiles )
+ if ( overallDistributedBuildQueues.isEmpty() )
{
- ChangeFile changeFile = new ChangeFile();
- changeFile.setName( ContinuumBuildConstant.getChangeFileName( map ) );
- changeFile.setRevision( ContinuumBuildConstant.getChangeFileRevision( map ) );
- changeFile.setStatus( ContinuumBuildConstant.getChangeFileStatus( map ) );
+ log.info( "No distributed build queues are configured for build agents" );
+ return null;
+ }
+
+ int idx = 0;
+ int size = 0;
- changeSet.addFile( changeFile );
+ for ( String buildAgentUrl : overallDistributedBuildQueues.keySet() )
+ {
+ OverallDistributedBuildQueue distributedBuildQueue = overallDistributedBuildQueues.get( buildAgentUrl );
+
+ if ( distributedBuildQueue != null )
+ {
+ try
+ {
+ if ( isAgentAvailable( buildAgentUrl ) )
+ {
+ SlaveBuildAgentTransportService client = createSlaveBuildAgentTransportClientConnection( buildAgentUrl );
+ int agentBuildSize = client.getBuildSizeOfAgent();
+
+ if ( idx == 0 )
+ {
+ whereToBeQueued = distributedBuildQueue;
+ size = agentBuildSize;
+ idx++;
+ }
+
+ if ( agentBuildSize < size )
+ {
+ whereToBeQueued = distributedBuildQueue;
+ size = agentBuildSize;
+ }
+ }
+ }
+ catch ( MalformedURLException e )
+ {
+ log.error( "Error occurred while retrieving distributed build queue: invalid build agent url " + buildAgentUrl );
+ }
+ catch ( Exception e )
+ {
+ log.error( "Error occurred while retrieving distributed build queue", e );
+ throw new ContinuumException( "Error occurred while retrieving distributed build queue", e );
+ }
+ }
}
}
+
+ return whereToBeQueued;
}
- private ProjectDependency getProjectParent( Map<String, Object> context )
+ private BuildAgentGroupConfiguration getBuildAgentGroup( Map<Integer, Integer> projectsAndBuildDefinitions )
+ throws ContinuumException
{
- Map map = ContinuumBuildConstant.getProjectParent( context );
-
- if ( map != null && map.size() > 0 )
+ if ( projectsAndBuildDefinitions == null )
{
- ProjectDependency parent = new ProjectDependency();
- parent.setGroupId( ContinuumBuildConstant.getGroupId( map ) );
- parent.setArtifactId( ContinuumBuildConstant.getArtifactId( map ) );
- parent.setVersion( ContinuumBuildConstant.getVersion( map ) );
-
- return parent;
+ return null;
}
+
+ try
+ {
+ List<Project> projects = new ArrayList<Project>();
- return null;
- }
+ for ( Integer projectId : projectsAndBuildDefinitions.keySet() )
+ {
+ projects.add( projectDao.getProjectWithDependencies( projectId ) );
+ }
- private List<ProjectDependency> getProjectDependencies( Map<String, Object> context )
- {
- List<ProjectDependency> projectDependencies = new ArrayList<ProjectDependency>();
+ projects = ProjectSorter.getSortedProjects( projects, log );
- List<Map> dependencies = ContinuumBuildConstant.getProjectDependencies( context );
+ int buildDefinitionId = projectsAndBuildDefinitions.get( projects.get( 0 ).getId() );
+ BuildDefinition buildDefinition = buildDefinitionDao.getBuildDefinition( buildDefinitionId );
- if ( dependencies != null )
- {
- for ( Map map : dependencies )
+ Profile profile = buildDefinition.getProfile();
+
+ if ( profile != null && !StringUtils.isEmpty( profile.getBuildAgentGroup() ) )
{
- ProjectDependency dependency = new ProjectDependency();
- dependency.setGroupId( ContinuumBuildConstant.getGroupId( map ) );
- dependency.setArtifactId( ContinuumBuildConstant.getArtifactId( map ) );
- dependency.setVersion( ContinuumBuildConstant.getVersion( map ) );
+ String groupName = profile.getBuildAgentGroup();
+
+ BuildAgentGroupConfiguration buildAgentGroup = configurationService.getBuildAgentGroup( groupName );
- projectDependencies.add( dependency );
[... 208 lines stripped ...]