Skip to content
Permalink
Browse files
[FIXES JENKINS-19622] Replace hudson.model.Trigger#timer with jenkins…
….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.
  • Loading branch information
recampbell committed Oct 28, 2013
1 parent eb1de2c commit 565ced0dba75c3f198c5cf9b9df247941df6ad46
@@ -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.
@@ -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}\""; }
@@ -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;


/**
@@ -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();

/**
@@ -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;
@@ -54,10 +57,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>
@@ -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 {
@@ -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}.)
@@ -89,6 +93,14 @@ public long getInitialDelay() {
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;
@@ -65,8 +65,8 @@
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.TimeUnit2;
import hudson.util.XStream2;
import hudson.util.ConsistentHash;
@@ -91,7 +91,6 @@
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.Timer;
import java.util.TreeSet;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
@@ -1986,10 +1985,7 @@ public String toString(Object item) {

private void periodic() {
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() {
@@ -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;

@@ -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);
}

/**
@@ -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;
@@ -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;
@@ -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;
@@ -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.
@@ -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,
@@ -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();
}

/**

0 comments on commit 565ced0

Please sign in to comment.