提交 ae28f88a 编写于 作者: K kohsuke

[FIXED HUDSON-3028] in 1.319. In a long run, I believe doing this control in...

[FIXED HUDSON-3028] in 1.319. In a long run, I believe doing this control in the queue with ResourceController is better, because (1) scheduling one at a time can create unnecessary wait time --- say if one of the configuration needs to run on a slave that's blocked, then it's better to schedule others first, and (2) the notion of shared resources spans beyond a single job, so doing that coordination at a job level isn't general enough. That said, I think it'll be easy enough to maintain data compatibility when this happens, so I'm committing this change now.

git-svn-id: https://hudson.dev.java.net/svn/hudson/trunk/hudson/main@20445 71c3de6d-444a-0410-be80-ed276b4c234a
上级 ca1010ca
......@@ -180,21 +180,17 @@ public class MatrixBuild extends AbstractBuild<MatrixProject,MatrixBuild> {
return Result.FAILURE;
try {
for(MatrixConfiguration c : activeConfigurations) {
logger.println(Messages.MatrixBuild_Triggering(c.getDisplayName()));
ParametersAction parameters = getAction(ParametersAction.class);
if (parameters != null) {
c.scheduleBuild(parameters, new UpstreamCause(MatrixBuild.this));
} else {
c.scheduleBuild(new UpstreamCause(MatrixBuild.this));
}
}
if(!p.isRunSequentially())
for(MatrixConfiguration c : activeConfigurations)
scheduleConfigurationBuild(logger, c);
// this occupies an executor unnecessarily.
// it would be nice if this can be placed in a temproary executor.
Result r = Result.SUCCESS;
for (MatrixConfiguration c : activeConfigurations) {
if(p.isRunSequentially())
scheduleConfigurationBuild(logger, c);
String whyInQueue = "";
long startTime = System.currentTimeMillis();
......@@ -271,6 +267,11 @@ public class MatrixBuild extends AbstractBuild<MatrixProject,MatrixBuild> {
}
}
private void scheduleConfigurationBuild(PrintStream logger, MatrixConfiguration c) {
logger.println(Messages.MatrixBuild_Triggering(c.getDisplayName()));
c.scheduleBuild(getAction(ParametersAction.class), new UpstreamCause(MatrixBuild.this));
}
public void post2(BuildListener listener) throws Exception {
for (MatrixAggregator a : aggregators)
a.endBuild();
......
......@@ -299,7 +299,12 @@ public class MatrixConfiguration extends Project<MatrixConfiguration,MatrixRun>
public boolean scheduleBuild(ParametersAction parameters) {
return scheduleBuild(parameters, new LegacyCodeCause());
}
/**
*
* @param parameters
* Can be null.
*/
public boolean scheduleBuild(ParametersAction parameters, Cause c) {
return Hudson.getInstance().getQueue().schedule(this, getQuietPeriod(), parameters, new CauseAction(c))!=null;
}
......
......@@ -44,6 +44,7 @@ import hudson.model.SCMedItem;
import hudson.model.Saveable;
import hudson.model.TopLevelItem;
import hudson.model.TopLevelItemDescriptor;
import hudson.model.ResourceController;
import hudson.model.Queue.FlyweightTask;
import hudson.model.Descriptor.FormException;
import hudson.tasks.BuildStep;
......@@ -132,6 +133,8 @@ public class MatrixProject extends AbstractProject<MatrixProject,MatrixBuild> im
@CopyOnWrite
private transient /*final*/ Set<MatrixConfiguration> activeConfigurations = new LinkedHashSet<MatrixConfiguration>();
private boolean runSequentially;
public MatrixProject(String name) {
super(Hudson.getInstance(), name);
}
......@@ -149,6 +152,20 @@ public class MatrixProject extends AbstractProject<MatrixProject,MatrixBuild> im
save();
}
/**
* If true, {@link MatrixRun}s are run sequentially, instead of running in parallel.
*
* TODO: this should be subsumed by {@link ResourceController}.
*/
public boolean isRunSequentially() {
return runSequentially;
}
public void setRunSequentially(boolean runSequentially) throws IOException {
this.runSequentially = runSequentially;
save();
}
/**
* Sets the combination filter.
*
......@@ -529,6 +546,8 @@ public class MatrixProject extends AbstractProject<MatrixProject,MatrixBuild> im
JSONObject json = req.getSubmittedForm();
runSequentially = json.has("runSequentially");
buildWrappers.rebuild(req, json, BuildWrappers.getFor(this));
builders.rebuildHetero(req, json, Builder.all(), "builder");
publishers.rebuild(req, json, BuildStepDescriptor.filter(Publisher.all(),this.getClass()));
......
......@@ -376,6 +376,13 @@ public class Queue extends ResourceController implements Saveable {
* That said, one can still look at {@link WaitingItem#future}, {@link WaitingItem#id}, etc.
*/
public synchronized WaitingItem schedule(Task p, int quietPeriod, List<Action> actions) {
// remove nulls
actions = new ArrayList<Action>(actions);
for (Iterator<Action> itr = actions.iterator(); itr.hasNext();) {
Action a = itr.next();
if (a==null) itr.remove();
}
boolean shouldSchedule = true;
for(QueueDecisionHandler h : QueueDecisionHandler.all()) {
shouldSchedule = shouldSchedule && h.shouldSchedule(p, actions);
......@@ -490,6 +497,11 @@ public class Queue extends ResourceController implements Saveable {
return schedule(p, quietPeriod, actions)!=null;
}
/**
* @param actions
* For convenience of the caller, some of the items in the array can be null,
* and they'll be ignored.
*/
public synchronized WaitingItem schedule(Task p, int quietPeriod, Action... actions) {
return schedule(p, quietPeriod, Arrays.asList(actions));
}
......
......@@ -104,6 +104,7 @@ THE SOFTWARE.
</table>
</f:repeatable>
</f:entry>
<f:optionalBlock field="runSequentially" title="${%Run each configuration sequentially}" />
</f:optionalBlock>
<f:optionalBlock name="hasCombinationFilter" title="${%Combination Filter}" checked="${!empty(it.combinationFilter)}"
......
<div>
With this option checked, Hudson builds each configuration in a sequence.
This can be useful if your configuration needs to access the shared resource
like database, as well as to avoid crowding out other jobs.
</div>
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册