Skip to content

Commit

Permalink
[FIXES JENKINS-19622] Replace hudson.model.Trigger#timer with jenkins…
Browse files Browse the repository at this point in the history
….util.Timer, which exposes a ScheduledExecutorService. Up to 10 additional threads will be created to run pending tasks even if running tasks are blocked.

Also, move static initialization of timers to the classes which require them.

(cherry picked from commit 565ced0)

Conflicts:
	core/src/main/java/hudson/model/Queue.java
  • Loading branch information
recampbell authored and olivergondza committed Dec 11, 2013
1 parent 7d602d5 commit 44ee0bb
Show file tree
Hide file tree
Showing 11 changed files with 208 additions and 77 deletions.
5 changes: 3 additions & 2 deletions core/src/main/groovy/hudson/util/LoadMonitor.groovy
Expand Up @@ -24,14 +24,15 @@
package hudson.util

import hudson.model.Computer
import jenkins.util.Timer
import jenkins.model.Jenkins
import hudson.model.Label
import hudson.model.Queue.BlockedItem
import hudson.model.Queue.BuildableItem
import hudson.model.Queue.WaitingItem
import hudson.triggers.SafeTimerTask
import java.text.DateFormat
import hudson.triggers.Trigger;
import java.util.concurrent.TimeUnit

/**
* Spits out the load information.
Expand All @@ -51,7 +52,7 @@ public class LoadMonitorImpl extends SafeTimerTask {
this.dataFile = dataFile;
labels = Jenkins.getInstance().labels*.name;
printHeaders();
Trigger.timer.scheduleAtFixedRate(this,0,10*1000);
Timer.get().scheduleAtFixedRate(this,0,10*1000, TimeUnit.MILLISECONDS);
}

private String quote(Object s) { "\"${s}\""; }
Expand Down
20 changes: 14 additions & 6 deletions core/src/main/java/hudson/model/AperiodicWork.java
Expand Up @@ -25,14 +25,17 @@

import hudson.ExtensionList;
import hudson.ExtensionPoint;
import hudson.init.Initializer;
import hudson.triggers.SafeTimerTask;
import hudson.triggers.Trigger;
import jenkins.model.Jenkins;
import jenkins.util.Timer;

import java.util.Random;
import java.util.Timer;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;

import static hudson.init.InitMilestone.JOB_LOADED;


/**
Expand Down Expand Up @@ -85,12 +88,17 @@ public long getInitialDelay() {
@Override
public final void doRun() throws Exception{
doAperiodicRun();
Timer timer = Trigger.timer;
if (timer != null) {
timer.schedule(getNewInstance(), getRecurrencePeriod());
Timer.get().schedule(getNewInstance(), getRecurrencePeriod(), TimeUnit.MILLISECONDS);
}

@Initializer(after= JOB_LOADED)
public static void init() {
// start all AperidocWorks
for (AperiodicWork p : AperiodicWork.all()) {
Timer.get().schedule(p, p.getInitialDelay(), TimeUnit.MILLISECONDS);
}
}

protected abstract void doAperiodicRun();

/**
Expand Down
16 changes: 16 additions & 0 deletions core/src/main/java/hudson/model/ComputerSet.java
Expand Up @@ -28,16 +28,19 @@
import hudson.Extension;
import hudson.Util;
import hudson.XmlFile;
import hudson.init.Initializer;
import hudson.model.Descriptor.FormException;
import hudson.model.listeners.SaveableListener;
import hudson.node_monitors.NodeMonitor;
import hudson.slaves.NodeDescriptor;
import hudson.triggers.SafeTimerTask;
import hudson.util.DescribableList;
import hudson.util.FormApply;
import hudson.util.FormValidation;
import jenkins.model.Jenkins;
import jenkins.model.ModelObjectWithChildren;
import jenkins.model.ModelObjectWithContextMenu.ContextMenu;
import jenkins.util.Timer;
import org.kohsuke.stapler.HttpResponse;
import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.StaplerRequest;
Expand All @@ -55,10 +58,13 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.sf.json.JSONObject;

import static hudson.init.InitMilestone.JOB_LOADED;

/**
* Serves as the top of {@link Computer}s in the URL hierarchy.
* <p>
Expand Down Expand Up @@ -397,6 +403,16 @@ public AutoCompletionCandidates doAutoCompleteCopyNewItemFrom(@QueryParameter fi
*/
public static void initialize() {}

@Initializer(after= JOB_LOADED)
public static void init() {
// start monitoring nodes, although there's no hurry.
Timer.get().schedule(new SafeTimerTask() {
public void doRun() {
ComputerSet.initialize();
}
}, 10, TimeUnit.SECONDS);
}

private static final Logger LOGGER = Logger.getLogger(ComputerSet.class.getName());

static {
Expand Down
14 changes: 13 additions & 1 deletion core/src/main/java/hudson/model/PeriodicWork.java
Expand Up @@ -23,16 +23,20 @@
*/
package hudson.model;

import hudson.init.Initializer;
import hudson.triggers.SafeTimerTask;
import hudson.triggers.Trigger;
import hudson.ExtensionPoint;
import hudson.Extension;
import hudson.ExtensionList;
import jenkins.model.Jenkins;
import jenkins.util.Timer;

import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import java.util.Random;
import java.util.Timer;

import static hudson.init.InitMilestone.JOB_LOADED;

/**
* Extension point to perform a periodic task in Hudson (through {@link Timer}.)
Expand Down Expand Up @@ -89,6 +93,14 @@ public static ExtensionList<PeriodicWork> all() {
return Jenkins.getInstance().getExtensionList(PeriodicWork.class);
}

@Initializer(after= JOB_LOADED)
public static void init() {
// start all PeriodicWorks
for (PeriodicWork p : PeriodicWork.all()) {
Timer.get().scheduleAtFixedRate(p, p.getInitialDelay(), p.getRecurrencePeriod(), TimeUnit.MILLISECONDS);
}
}

// time constants
protected static final long MIN = 1000*60;
protected static final long HOUR =60*MIN;
Expand Down
7 changes: 2 additions & 5 deletions core/src/main/java/hudson/model/Queue.java
Expand Up @@ -66,6 +66,7 @@
import hudson.model.queue.CauseOfBlockage.BecauseNodeIsBusy;
import hudson.model.queue.WorkUnitContext;
import hudson.security.ACL;
import jenkins.util.Timer;
import hudson.triggers.SafeTimerTask;
import hudson.triggers.Trigger;
import hudson.util.OneShotEvent;
Expand Down Expand Up @@ -93,7 +94,6 @@
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.Timer;
import java.util.TreeSet;
import java.util.Map.Entry;
import java.util.concurrent.TimeUnit;
Expand Down Expand Up @@ -2072,10 +2072,7 @@ private static class MaintainTask extends SafeTimerTask {
this.queue = new WeakReference<Queue>(queue);

long interval = 5000;
Timer timer = Trigger.timer;
if (timer != null) {
timer.schedule(this, interval, interval);
}
Timer.get().scheduleWithFixedDelay(this, interval, interval, TimeUnit.MILLISECONDS);
}

protected void doRun() {
Expand Down
Expand Up @@ -29,16 +29,16 @@
import jenkins.model.Jenkins;
import hudson.model.ComputerSet;
import hudson.model.AdministrativeMonitor;
import hudson.triggers.Trigger;
import hudson.triggers.SafeTimerTask;
import hudson.slaves.OfflineCause;
import jenkins.util.Timer;

import java.io.IOException;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Timer;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;

Expand Down Expand Up @@ -87,14 +87,12 @@ protected AbstractNodeMonitorDescriptor(Class<? extends NodeMonitor> clazz, long
}

private void schedule(long interval) {
Timer timer = Trigger.timer;
if (timer != null) {
timer.scheduleAtFixedRate(new SafeTimerTask() {
Timer.get()
.scheduleAtFixedRate(new SafeTimerTask() {
public void doRun() {
triggerUpdate();
}
}, interval, interval);
}
}, interval, interval, TimeUnit.MILLISECONDS);
}

/**
Expand Down
36 changes: 4 additions & 32 deletions core/src/main/java/hudson/triggers/Trigger.java
Expand Up @@ -23,18 +23,14 @@
*/
package hudson.triggers;

import static hudson.init.InitMilestone.JOB_LOADED;
import hudson.DependencyRunner;
import hudson.DependencyRunner.ProjectRunnable;
import hudson.DescriptorExtensionList;
import hudson.Extension;
import hudson.ExtensionPoint;
import hudson.init.Initializer;
import hudson.model.AbstractProject;
import hudson.model.Action;
import hudson.model.AperiodicWork;
import hudson.model.Build;
import hudson.model.ComputerSet;
import hudson.model.Describable;
import hudson.scheduler.Hash;
import jenkins.model.Jenkins;
Expand All @@ -45,7 +41,6 @@
import hudson.model.TopLevelItemDescriptor;
import hudson.scheduler.CronTab;
import hudson.scheduler.CronTabList;
import hudson.util.DoubleLaunchChecker;

import java.io.InvalidObjectException;
import java.io.ObjectStreamException;
Expand All @@ -56,7 +51,6 @@
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Timer;
import java.util.concurrent.Future;
import java.util.logging.Level;
import java.util.logging.Logger;
Expand Down Expand Up @@ -279,34 +273,12 @@ public void run(AbstractProject p) {
* Initialized and cleaned up by {@link jenkins.model.Jenkins}, but value kept here for compatibility.
*
* If plugins want to run periodic jobs, they should implement {@link PeriodicWork}.
*
* @deprecated Use {@link jenkins.util.Timer#get()} instead.
*/
@SuppressWarnings("MS_SHOULD_BE_FINAL")
public static @CheckForNull Timer timer;

@Initializer(after=JOB_LOADED)
public static void init() {
new DoubleLaunchChecker().schedule();

Timer _timer = timer;
if (_timer != null) {
// start all PeridocWorks
for(PeriodicWork p : PeriodicWork.all()) {
_timer.scheduleAtFixedRate(p,p.getInitialDelay(),p.getRecurrencePeriod());
}

// start all AperidocWorks
for(AperiodicWork p : AperiodicWork.all()) {
_timer.schedule(p,p.getInitialDelay());
}

// start monitoring nodes, although there's no hurry.
_timer.schedule(new SafeTimerTask() {
public void doRun() {
ComputerSet.initialize();
}
}, 1000*10);
}
}
@Deprecated
public static @CheckForNull java.util.Timer timer;

/**
* Returns all the registered {@link Trigger} descriptors.
Expand Down
22 changes: 15 additions & 7 deletions core/src/main/java/hudson/util/DoubleLaunchChecker.java
Expand Up @@ -23,24 +23,28 @@
*/
package hudson.util;

import hudson.init.Initializer;
import jenkins.model.Jenkins;
import hudson.triggers.SafeTimerTask;
import hudson.triggers.Trigger;
import jenkins.util.Timer;
import org.apache.commons.io.FileUtils;
import org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;

import javax.servlet.ServletException;
import javax.servlet.ServletContext;

import static hudson.init.InitMilestone.JOB_LOADED;
import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
import java.io.File;
import java.io.IOException;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import java.util.logging.Level;
import java.lang.management.ManagementFactory;
import java.lang.reflect.Method;
import java.util.Timer;

/**
* Makes sure that no other Hudson uses our <tt>JENKINS_HOME</tt> directory,
Expand Down Expand Up @@ -146,14 +150,18 @@ public String getCollidingId() {
public void schedule() {
// randomize the scheduling so that multiple Hudson instances will write at the file at different time
long MINUTE = 1000*60;
Timer timer = Trigger.timer;
if (timer != null) {
timer.schedule(new SafeTimerTask() {

Timer.get()
.schedule(new SafeTimerTask() {
protected void doRun() {
execute();
}
},(random.nextInt(30)+60)*MINUTE);
}
}, (random.nextInt(30) + 60) * MINUTE, TimeUnit.MILLISECONDS);
}

@Initializer(after= JOB_LOADED)
public static void init() {
new DoubleLaunchChecker().schedule();
}

/**
Expand Down

0 comments on commit 44ee0bb

Please sign in to comment.