package hudson.plugins.javanet_trigger_installer;
import org.kohsuke.jnt.JavaNet;
import org.kohsuke.jnt.ProcessingException;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import hudson.util.TimeUnit2;
/**
* Does the actual job of subscribing/unsubscribing.
*
* <p>
* The programmatic access to java.net often takes a long time
* to run, so the actual work is done in a separate thread
* asynchronously.
*
* @author Kohsuke Kawaguchi
*/
public class Worker extends Thread {
/**
* Job queue.
*/
/*package*/ static final List<Task> queue = new LinkedList<Task>();
public Worker() {
super("java.net SCM trigger worker thread");
}
public void run() {
long lastUsed;
try {
JavaNet connection=null;
while(true) {
try {
lastUsed = System.currentTimeMillis();
Task t = pick();
// if a connection is left unused for a long time,
// don't bother using it. it must have already gone expired.
if(System.currentTimeMillis()-lastUsed >= SESSION_TIMEOUT)
connection = null;
Exception ex = null;
for( int i=0; i<2; i++ ) {// allow one retry, in case the connection becomes expired
if(connection==null)
connection = JavaNet.connect();
try {
t.execute(connection);
break;
// in case of error, force a fresh connection and retry
} catch (IOException e) {
connection = null;
ex = e;
} catch (ProcessingException e) {
connection = null;
ex = e;
}
}
if(ex!=null)
LOGGER.log(Level.SEVERE,"Failed to execute "+t,ex);
} catch (InterruptedException e) {
throw e;
} catch (Throwable t) {
LOGGER.log(Level.SEVERE,"Terminated abnormally because of an error. Retrying after a minute",t);
Thread.sleep(60*1000);
}
}
} catch (InterruptedException e) {
LOGGER.info("Going to shut down");
}
}
/**
* Pick up the next task
*/
private Task pick() throws InterruptedException {
synchronized(queue) {
while(queue.isEmpty())
queue.wait();
return queue.remove(0);
}
}
private static final Logger LOGGER = Logger.getLogger(Worker.class.getName());
private static final long SESSION_TIMEOUT = TimeUnit2.MINUTES.toMillis(120);
}