Skip to content
Permalink
Browse files

[FIXED JENKINS-18660] Added dedicated denormalized counter function

(cherry picked from commit 5981ac4)

Conflicts:
	core/src/main/java/hudson/model/Label.java
  • Loading branch information...
stephenc authored and olivergondza committed Jul 8, 2013
1 parent 31c302c commit 9bee3ba75d80115456732e9791ba9caab71c9042
Showing with 57 additions and 1 deletion.
  1. +56 −0 core/src/main/java/hudson/model/Label.java
  2. +1 −1 core/src/main/java/hudson/model/Node.java
@@ -39,11 +39,16 @@
import hudson.model.labels.LabelExpressionParser;
import hudson.model.labels.LabelOperatorPrecedence;
import hudson.model.labels.LabelVisitor;
import hudson.security.ACL;
import hudson.slaves.NodeProvisioner;
import hudson.slaves.Cloud;
import hudson.util.QuotedStringTokenizer;
import hudson.util.VariableResolver;
import jenkins.model.Jenkins;
import org.acegisecurity.context.SecurityContext;
import org.acegisecurity.context.SecurityContextHolder;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.kohsuke.stapler.export.Exported;
import org.kohsuke.stapler.export.ExportedBean;

@@ -54,6 +59,7 @@
import java.util.List;
import java.util.Set;
import java.util.Collection;
import java.util.Stack;
import java.util.TreeSet;

import com.thoughtworks.xstream.converters.Converter;
@@ -342,6 +348,56 @@ private String toString(Collection<? extends ModelObject> model) {
return r;
}

/**
* Returns a count of projects that are tied on this node. In a system without security this should be the same
* as {@code getTiedJobs().size()} but significantly faster as it involves fewer temporary objects and avoids
* sorting the intermediary list. In a system with security, this will likely return a higher value as it counts
* all jobs (mostly) irrespective of access.
* @return a count of projects that are tied on this node.
*/
public int getTiedJobCount() {
// denormalize for performance
// we don't need to respect security as much when returning a simple count
SecurityContext context = ACL.impersonate(ACL.SYSTEM);
try {
int result = 0;
// top level gives the map without checking security of items in the map
// therefore best performance
for (TopLevelItem topLevelItem : Jenkins.getInstance().getItemMap().values()) {
if (topLevelItem instanceof AbstractProject) {
final AbstractProject project = (AbstractProject) topLevelItem;
if (this.equals(project.getAssignedLabel())) {
result++;
}
}
if (topLevelItem instanceof ItemGroup) {
Stack<ItemGroup> q = new Stack<ItemGroup>();
q.push((ItemGroup) topLevelItem);

while (!q.isEmpty()) {
ItemGroup<?> parent = q.pop();
// we run the risk of permissions checks in ItemGroup#getItems()
// not much we can do here though
for (Item i : parent.getItems()) {
if (i instanceof AbstractProject) {
final AbstractProject project = (AbstractProject) i;
if (this.equals(project.getAssignedLabel())) {
result++;
}
}
if (i instanceof ItemGroup) {
q.push((ItemGroup) i);
}
}
}
}
}
return result;
} finally {
SecurityContextHolder.setContext(context);
}
}

public boolean contains(Node node) {
return getNodes().contains(node);
}
@@ -222,7 +222,7 @@ void setTemporaryOfflineCause(OfflineCause cause) {
public TagCloud<LabelAtom> getLabelCloud() {
return new TagCloud<LabelAtom>(getAssignedLabels(),new WeightFunction<LabelAtom>() {
public float weight(LabelAtom item) {
return item.getTiedJobs().size();
return item.getTiedJobCount();
}
});
}

0 comments on commit 9bee3ba

Please sign in to comment.
You can’t perform that action at this time.