Skip to content

Commit

Permalink
Merge pull request #23 from emsa23/master
Browse files Browse the repository at this point in the history
[JENKINS-27966] Priority Sorter must not require matrix-project
  • Loading branch information
emsa23 committed Apr 25, 2015
2 parents ba869de + 78ce5be commit 53bde96
Show file tree
Hide file tree
Showing 22 changed files with 389 additions and 89 deletions.
11 changes: 9 additions & 2 deletions pom.xml
@@ -1,4 +1,5 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.jenkins-ci.plugins</groupId>
Expand Down Expand Up @@ -65,7 +66,7 @@
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>matrix-project</artifactId>
<version>1.4</version>
<optional>false</optional> <!-- should be true but for now require this [JENKINS-27966] -->
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
Expand All @@ -79,6 +80,12 @@
<version>1.18</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>credentials</artifactId>
<version>1.22</version>
<scope>test</scope>
</dependency>
</dependencies>

<repositories>
Expand Down
29 changes: 12 additions & 17 deletions src/main/java/jenkins/advancedqueue/PriorityConfiguration.java
Expand Up @@ -26,6 +26,7 @@
import hudson.DescriptorExtensionList;
import hudson.Extension;
import hudson.ExtensionList;
import hudson.Plugin;
import hudson.matrix.MatrixConfiguration;
import hudson.matrix.MatrixProject;
import hudson.model.Describable;
Expand Down Expand Up @@ -79,6 +80,7 @@ public class PriorityConfiguration extends Descriptor<PriorityConfiguration> imp
private final static Logger LOGGER = Logger.getLogger(PriorityConfiguration.class.getName());

transient private Map<Integer, JobGroup> id2jobGroup;
transient private PriorityConfigurationMatrixHelper priorityConfigurationMatrixHelper;
private List<JobGroup> jobGroups;

public PriorityConfiguration() {
Expand All @@ -101,6 +103,13 @@ public int compare(JobGroup.PriorityStrategyHolder o1, JobGroup.PriorityStrategy
}
});
}
//
Plugin plugin = Jenkins.getInstance().getPlugin("matrix-project");
if(plugin == null || !plugin.getWrapper().isEnabled()){
priorityConfigurationMatrixHelper = null;
} else {
priorityConfigurationMatrixHelper = new PriorityConfigurationMatrixHelper();
}
}

public String getIconFileName() {
Expand Down Expand Up @@ -207,23 +216,9 @@ private PriorityConfigurationCallback getPriorityInternal(Queue.Item item, Prior
}

Job<?, ?> job = (Job<?, ?>) item.task;

// [JENKINS-8597]
// For MatrixConfiguration use the latest assigned Priority from the
// MatrixProject
if (job instanceof MatrixConfiguration) {
MatrixProject matrixProject = ((MatrixConfiguration) job).getParent();
priorityCallback.addDecisionLog(0, "Job is MatrixConfiguration [" + matrixProject.getName() + "] ...");
ItemInfo itemInfo = QueueItemCache.get().getItem(matrixProject.getName());
// Can be null (for example) at startup when the MatrixBuild got
// lost (was running at
// restart)
if (itemInfo != null) {
priorityCallback.addDecisionLog(0, "MatrixProject found in cache, using priority from queue-item [" + itemInfo.getItemId() + "]");
return priorityCallback.setPrioritySelection(itemInfo.getPriority(), itemInfo.getJobGroupId(), itemInfo.getPriorityStrategy());
}
priorityCallback.addDecisionLog(0, "MatrixProject not found in cache, assigning global default priority");
return priorityCallback.setPrioritySelection(PrioritySorterConfiguration.get().getStrategy().getDefaultPriority());

if (priorityConfigurationMatrixHelper != null && priorityConfigurationMatrixHelper.isMatrixConfiguration(job)) {
return priorityConfigurationMatrixHelper.getPriority((MatrixConfiguration) job, priorityCallback);
}

//
Expand Down
Expand Up @@ -7,5 +7,7 @@ public interface PriorityConfigurationCallback extends DecisionLogger {
PriorityConfigurationCallback setPrioritySelection(int priority);

PriorityConfigurationCallback setPrioritySelection(int priority, int jobGroupId, PriorityStrategy reason);


PriorityConfigurationCallback setPrioritySelection(int priority, long sortAsInQueueSince, int jobGroupId, PriorityStrategy reason);

}
@@ -0,0 +1,36 @@
package jenkins.advancedqueue;

import jenkins.advancedqueue.sorter.ItemInfo;
import jenkins.advancedqueue.sorter.QueueItemCache;
import hudson.matrix.MatrixConfiguration;
import hudson.matrix.MatrixProject;
import hudson.model.Job;

class PriorityConfigurationMatrixHelper {

boolean isMatrixConfiguration(Job<?, ?> job) {
return job instanceof MatrixConfiguration;
}

PriorityConfigurationCallback getPriority(MatrixConfiguration matrixConfiguration,
PriorityConfigurationCallback priorityCallback) {
// [JENKINS-8597]
// For MatrixConfiguration use the latest assigned Priority from the
// MatrixProject
MatrixProject matrixProject = matrixConfiguration.getParent();
priorityCallback.addDecisionLog(0, "Job is MatrixConfiguration [" + matrixProject.getName() + "] ...");
ItemInfo itemInfo = QueueItemCache.get().getItem(matrixProject.getName());
// Can be null (for example) at startup when the MatrixBuild got
// lost (was running at restart)
if (itemInfo != null) {
priorityCallback.addDecisionLog(0, "MatrixProject found in cache, using priority from queue-item ["
+ itemInfo.getItemId() + "]");
return priorityCallback.setPrioritySelection(itemInfo.getPriority(), itemInfo.getJobGroupId(),
itemInfo.getPriorityStrategy());
}
priorityCallback.addDecisionLog(0, "MatrixProject not found in cache, assigning global default priority");
return priorityCallback.setPrioritySelection(PrioritySorterConfiguration.get().getStrategy()
.getDefaultPriority());

}
}
Expand Up @@ -34,6 +34,11 @@ public PriorityConfigurationCallback setPrioritySelection(int priority) {
public PriorityConfigurationCallback addDecisionLog(int indent, String log) {
return this;
}

public PriorityConfigurationCallback setPrioritySelection(int priority, long sortAsInQueueSince,
int jobGroupId, PriorityStrategy reason) {
return this;
}
};

@Extension
Expand Down
Expand Up @@ -95,6 +95,11 @@ public PriorityConfigurationCallback setPrioritySelection(int priority) {
public PriorityConfigurationCallback addDecisionLog(int indent, String log) {
return this;
}

public PriorityConfigurationCallback setPrioritySelection(int priority, long sortAsInQueueSince,
int jobGroupId, PriorityStrategy reason) {
return this;
}
};

@Override
Expand Down
33 changes: 11 additions & 22 deletions src/main/java/jenkins/advancedqueue/sorter/AdvancedQueueSorter.java
Expand Up @@ -75,30 +75,17 @@ public void sortBuildableItems(List<BuildableItem> items) {

Collections.sort(items, new Comparator<BuildableItem>() {
public int compare(BuildableItem o1, BuildableItem o2) {
float o1weight = getCalculatedWeight(o1);
float o2weight = getCalculatedWeight(o2);
if (o1weight > o2weight) {
return 1;
}
if (o1weight < o2weight) {
return -1;
}
// Same weights sort on time in queue
if(o1.getInQueueSince() > o2.getInQueueSince()) {
return 1;
}
if(o1.getInQueueSince() < o2.getInQueueSince()) {
return -1;
}
// Having same time-stamp is not likely - but maybe it can happen ...
return new Integer(o1.id).compareTo(o2.id);
ItemInfo item1 = QueueItemCache.get().getItem(o1.id);
ItemInfo item2 = QueueItemCache.get().getItem(o2.id);
return item1.compareTo(item2);
}
});
//
if (items.size() > 0 && LOGGER.isLoggable(Level.FINE)) {
float minWeight = QueueItemCache.get().getItem(items.get(0).id).getWeight();
float maxWeight = QueueItemCache.get().getItem(items.get(items.size() - 1).id).getWeight();
LOGGER.log(Level.FINE, "Sorted {0} Buildable Items with Min Weight {1} and Max Weight {2}", new Object[] { items.size(), minWeight, maxWeight });
LOGGER.log(Level.FINE, "Sorted {0} Buildable Items with Min Weight {1} and Max Weight {2}", new Object[] {
items.size(), minWeight, maxWeight });
}
//
if (items.size() > 0 && LOGGER.isLoggable(Level.FINER)) {
Expand All @@ -109,11 +96,13 @@ public int compare(BuildableItem o1, BuildableItem o2) {
for (BuildableItem item : items) {
ItemInfo itemInfo = QueueItemCache.get().getItem(item.id);
String jobName = itemInfo.getJobName();
if(jobName.length() > 21) {
jobName = jobName.substring(0, 9) + "..." + jobName.substring(jobName.length() - 9 , jobName.length());
if (jobName.length() > 21) {
jobName = jobName.substring(0, 9) + "..."
+ jobName.substring(jobName.length() - 9, jobName.length());
}
queueStr.append(String.format("| %10d | %20s | %8d | %20.5f |\n", item.id, jobName, itemInfo.getPriority(), itemInfo.getWeight()));

queueStr.append(String.format("| %10d | %20s | %8d | %20.5f |\n", item.id, jobName,
itemInfo.getPriority(), itemInfo.getWeight()));

}
queueStr.append("+----------------------------------------------------------------------+");
LOGGER.log(Level.FINER, queueStr.toString());
Expand Down
19 changes: 18 additions & 1 deletion src/main/java/jenkins/advancedqueue/sorter/ItemInfo.java
Expand Up @@ -45,6 +45,8 @@ public class ItemInfo implements PriorityConfigurationCallback, DecisionLogger,
private int itemId;

private long inQueueSince;

private Long sortAsInQueueSince = null;

private int jobGroupId;

Expand Down Expand Up @@ -74,6 +76,14 @@ public PriorityConfigurationCallback setPrioritySelection(int priority, int jobG
return this;
}

public PriorityConfigurationCallback setPrioritySelection(int priority, long sortAsInQueueSince, int jobGroupId, PriorityStrategy reason) {
this.priority = priority;
this.sortAsInQueueSince = sortAsInQueueSince;
this.jobGroupId = jobGroupId;
this.priorityStrategy = reason;
return this;
}

public PriorityConfigurationCallback addDecisionLog(int indent, String log) {
this.decisionLog.add(String.format("%"+ ((indent + 1) * 2) + "s%s", "", log));
return this;
Expand Down Expand Up @@ -107,6 +117,13 @@ public long getInQueueSince() {
return inQueueSince;
}

public long getSortableInQueueSince() {
if(sortAsInQueueSince != null) {
return sortAsInQueueSince;
}
return inQueueSince;
}

public int getJobGroupId() {
return jobGroupId;
}
Expand All @@ -133,7 +150,7 @@ public ItemStatus getItemStatus() {

public int compareTo(ItemInfo o) {
if(this.getWeight() == o.getWeight()) {
if(this.getInQueueSince() == o.getInQueueSince()) {
if(this.getSortableInQueueSince() == o.getSortableInQueueSince()) {
return Integer.compare(this.getItemId(), o.getItemId());
}
return Long.compare(this.getInQueueSince(), o.getInQueueSince());
Expand Down
20 changes: 2 additions & 18 deletions src/test/java/jenkins/advancedqueue/test/BasicTest.java
Expand Up @@ -17,27 +17,11 @@ public class BasicTest {

private JobHelper jobHelper = new JobHelper(j);

@Test
public void simple_with_no_configuration() throws Exception {
TestRunListener.init(new ExpectedItem("Job 0", 3));
jobHelper.scheduleProjects(new UserIdCause());
j.waitUntilNoActivity();
TestRunListener.assertStartedItems();
}

@Test
public void simple_two_jobs_with_no_configuration() throws Exception {
TestRunListener.init(new ExpectedItem("Job 0", 3), new ExpectedItem("Job 1", 3));
jobHelper.scheduleProjects(new UserIdCause(), new UserIdCause());
j.waitUntilNoActivity();
TestRunListener.assertStartedItems();
}

@Test
@LocalData
public void simple_two_jobs_with_basic_configuration() throws Exception {
TestRunListener.init(new ExpectedItem("Job 0", 9), new ExpectedItem("Job 1", 9));
jobHelper.scheduleProjects(new UserIdCause(), new UserIdCause());
jobHelper.scheduleProjects(new UserIdCause(), new UserIdCause()).go();
j.waitUntilNoActivity();
TestRunListener.assertStartedItems();
}
Expand All @@ -46,7 +30,7 @@ public void simple_two_jobs_with_basic_configuration() throws Exception {
@LocalData
public void simple_with_basic_configuration() throws Exception {
TestRunListener.init(new ExpectedItem("Job 0", 9));
jobHelper.scheduleProjects(new UserIdCause());
jobHelper.scheduleProjects(new UserIdCause()).go();
j.waitUntilNoActivity();
TestRunListener.assertStartedItems();
}
Expand Down
Expand Up @@ -21,7 +21,7 @@ public class JobPatternGroupTest {
@LocalData
public void test_job_pattern_1() throws Exception {
TestRunListener.init(new ExpectedItem("Job 0", 3));
jobHelper.scheduleProjects(new UserIdCause());
jobHelper.scheduleProjects(new UserIdCause()).go();
j.waitUntilNoActivity();
TestRunListener.assertStartedItems();
}
Expand All @@ -30,7 +30,7 @@ public void test_job_pattern_1() throws Exception {
@LocalData
public void test_job_pattern_2() throws Exception {
TestRunListener.init(new ExpectedItem("Job 0", 3), new ExpectedItem("Job 1", 9));
jobHelper.scheduleProjects(new UserIdCause(), new UserIdCause());
jobHelper.scheduleProjects(new UserIdCause(), new UserIdCause()).go();
j.waitUntilNoActivity();
TestRunListener.assertStartedItems();
}
Expand All @@ -40,7 +40,7 @@ public void test_job_pattern_2() throws Exception {
public void test_job_pattern_3() throws Exception {
TestRunListener.init(new ExpectedItem("Job 0", 3), new ExpectedItem("Job 3", 3), new ExpectedItem("Job 1", 9),
new ExpectedItem("Job 2", 9));
jobHelper.scheduleProjects(new UserIdCause(), new UserIdCause(), new UserIdCause(), new UserIdCause());
jobHelper.scheduleProjects(new UserIdCause(), new UserIdCause(), new UserIdCause(), new UserIdCause()).go();
j.waitUntilNoActivity();
TestRunListener.assertStartedItems();
}
Expand Down
73 changes: 73 additions & 0 deletions src/test/java/jenkins/advancedqueue/test/MatrixTest.java
@@ -0,0 +1,73 @@
package jenkins.advancedqueue.test;

import hudson.cli.BuildCommand.CLICause;
import hudson.model.Cause.UserIdCause;
import jenkins.advancedqueue.testutil.ExpectedItem;
import jenkins.advancedqueue.testutil.JobHelper;
import jenkins.advancedqueue.testutil.TestRunListener;

import org.junit.Rule;
import org.junit.Test;
import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.recipes.LocalData;

public class MatrixTest {

@Rule
public JenkinsRule j = new JenkinsRule();

private JobHelper jobHelper = new JobHelper(j);

@Test
@LocalData
public void simple_matrix_with_no_configuration() throws Exception {
TestRunListener.init(
new ExpectedItem("Matrix 0", 1),
new ExpectedItem("0A1=0A.", 1), new ExpectedItem("0A1=0A.", 1)
);
jobHelper.scheduleMatrixProjects(new UserIdCause()).go();
j.waitUntilNoActivity();
TestRunListener.assertStartedItems();
}

@Test
@LocalData
public void simple_two_matrix_with_no_configuration() throws Exception {
TestRunListener.init(
new ExpectedItem("Matrix 0", 1), new ExpectedItem("Matrix 1", 1),
new ExpectedItem("0A1=0A.", 1), new ExpectedItem("0A1=0A.", 1),
new ExpectedItem("1A1=1A.", 1), new ExpectedItem("1A1=1A.", 1)
);
jobHelper.scheduleMatrixProjects(new UserIdCause(), new UserIdCause()).go();
j.waitUntilNoActivity();
TestRunListener.assertStartedItems();
}

@Test
@LocalData
public void matrix_and_jobs_with_no_configuration() throws Exception {
TestRunListener.init(
new ExpectedItem("Matrix 0", 1), new ExpectedItem("Matrix 1", 5),
new ExpectedItem("0A1=0A.", 1), new ExpectedItem("0A1=0A.", 1),
new ExpectedItem("Job 0", 5),
new ExpectedItem("1A1=1A.", 5), new ExpectedItem("1A1=1A.", 5)
);
jobHelper.scheduleProjects(new CLICause()).scheduleMatrixProjects(new UserIdCause(), new CLICause()).go();
j.waitUntilNoActivity();
TestRunListener.assertStartedItems();
}

@Test
@LocalData
public void matrix_and_jobs_with_no_configuration_reverse() throws Exception {
TestRunListener.init(
new ExpectedItem("Matrix 0", 1), new ExpectedItem("Matrix 1", 5),
new ExpectedItem("0A1=0A.", 1), new ExpectedItem("0A1=0A.", 1),
new ExpectedItem("1A1=1A.", 5), new ExpectedItem("1A1=1A.", 5),
new ExpectedItem("Job 0", 5)
);
jobHelper.scheduleMatrixProjects(new UserIdCause(), new CLICause()).scheduleProjects(new CLICause()).go();
j.waitUntilNoActivity();
TestRunListener.assertStartedItems();
}
}

0 comments on commit 53bde96

Please sign in to comment.