Fix project-node registration

Previously, a node would register the ability to run a job under
all labels associated with the project if the node matched at
least one of them.  What we really want to do is, if the node
matches any project label, register the generalized job and then
also register it for each label in the _intersection_ of project
labels and node labels.

Change-Id: Ie41af7b1a2f26a4ca2aac6c7263817d5021cca9b
This commit is contained in:
James E. Blair 2014-06-20 11:34:04 -07:00 committed by Clark Boylan
parent 67f6b2342b
commit 6961c9d441
1 changed files with 20 additions and 55 deletions

View File

@ -21,6 +21,7 @@ package hudson.plugins.gearman;
import hudson.model.AbstractProject;
import hudson.model.Computer;
import hudson.model.Label;
import hudson.model.labels.LabelAtom;
import hudson.model.Node;
import hudson.model.Node.Mode;
@ -70,46 +71,6 @@ public class ExecutorWorkerThread extends AbstractWorkerThread{
this.functionMap = new HashMap<String,GearmanFunctionFactory>();
}
/**
* This function tokenizes the labels in a label string
* that is set in the jenkins projects
*
* @param label
* The label string.
* @param pattern
* The pattern for tokenizing the label.
* @return
* A list of labels, the list can be empty
*/
private Set<String> tokenizeLabelString(String label, String pattern) {
Set<String> labelSet = new HashSet<String>();
if (pattern == null) {
return labelSet;
}
if (pattern.isEmpty()) {
return labelSet;
}
if (label != null) {
Scanner slabel = new Scanner(label);
try {
slabel.useDelimiter(pattern);
while (slabel.hasNext()) {
String newLabel = slabel.next();
labelSet.add(newLabel);
}
} finally {
slabel.close();
}
}
return labelSet;
}
/**
* Register gearman functions on this computer. This will unregister all
* functions before registering new functions. Works for free-style
@ -174,25 +135,29 @@ public class ExecutorWorkerThread extends AbstractWorkerThread{
jobFunctionName, StartJobWorker.class.getName(),
project, computer, this.masterName, worker));
}
} else { // register "build:$projectName:$projectLabel" if this
} else { // register "build:$projectName:$label" if this
// node matches a node from the project label
Set<Node> projectLabelNodes = label.getNodes();
String projectLabelString = label.getExpression();
Set<String> projectLabels = tokenizeLabelString(
projectLabelString, "\\|\\|");
Set<LabelAtom> projectLabelAtoms = label.listAtoms();
Set<LabelAtom> nodeLabelAtoms = node.getAssignedLabels();
// Get the intersection of label atoms for the project and the current node
Set<LabelAtom> nodeProjectLabelAtoms = new HashSet<LabelAtom>(projectLabelAtoms);
nodeProjectLabelAtoms.retainAll(nodeLabelAtoms);
// iterate thru all project labels and find matching nodes
for (String projectLabel : projectLabels) {
if (projectLabelNodes.contains(node)) {
String jobFunctionName = "build:" + projectName
+ ":" + projectLabel;
// register with label (i.e. "build:$projectName:$projectLabel")
newFunctionMap.put(jobFunctionName, new CustomGearmanFunctionFactory(
jobFunctionName, StartJobWorker.class.getName(),
project, computer, this.masterName, worker));
jobFunctionName = "build:" + projectName;
// also register without label (i.e. "build:$projectName")
// Register functions iff the current node is in
// the list of nodes for the project's label
if (projectLabelNodes.contains(node)) {
String jobFunctionName = "build:" + projectName;
// register without label (i.e. "build:$projectName")
newFunctionMap.put(jobFunctionName, new CustomGearmanFunctionFactory(
jobFunctionName, StartJobWorker.class.getName(),
project, computer, this.masterName, worker));
// iterate over the intersection of project and node labels
for (LabelAtom labelAtom : nodeProjectLabelAtoms) {
jobFunctionName = "build:" + projectName
+ ":" + labelAtom.getDisplayName();
// register with label (i.e. "build:$projectName:$label")
newFunctionMap.put(jobFunctionName, new CustomGearmanFunctionFactory(
jobFunctionName, StartJobWorker.class.getName(),
project, computer, this.masterName, worker));