package org.dcache.pool.classic; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Required; import java.io.PrintWriter; import java.util.concurrent.Callable; import diskCacheV111.vehicles.JobInfo; import dmg.cells.nucleus.CellCommandListener; import dmg.cells.nucleus.CellInfoProvider; import dmg.util.command.Command; public class JobTimeoutManager implements Runnable, CellCommandListener, CellInfoProvider { private static final Logger LOGGER = LoggerFactory.getLogger(JobTimeoutManager.class); private final Thread _worker; private IoQueueManager _ioQueues; public JobTimeoutManager() { _worker = new Thread(this, "JobTimeoutManager"); } @Required public void setIoQueueManager(IoQueueManager queues) { _ioQueues = queues; } public synchronized void start() { if (_worker.isAlive()) { throw new IllegalStateException("Already running"); } _worker.start(); } public synchronized void stop() { _worker.interrupt(); } @Override public void getInfo(PrintWriter pw) { for (MoverRequestScheduler entry : _ioQueues.queues()) { pw.println(" " + entry.getName() + " (lastAccess=" + (entry.getLastAccessed() / 1000L) + ";total=" + (entry.getTotal() / 1000L) + ")"); } } @Command(name = "jtm go", hint = "kill transfers that have exceeded time limits", description = "Immediately kills all transfers that have exceeded the inactivity " + "limits defined for the corresponding queue. Usually the job timeout manager " + "does this automatically every second minute, but with this command such " + "transfers can be killed immediately.") public class JtmGoCommand implements Callable<String> { @Override public String call() throws IllegalMonitorStateException { synchronized (JobTimeoutManager.this) { JobTimeoutManager.this.notifyAll(); } return ""; } } @Override public void run() { try { while (!Thread.currentThread().isInterrupted()) { synchronized (this) { wait(120000L); } long now = System.currentTimeMillis(); for (MoverRequestScheduler jobs : _ioQueues.queues()) { for (JobInfo info : jobs.getJobInfos()) { int jobId = (int) info.getJobId(); if (jobs.isExpired(info, now)) { LOGGER.error("Trying to kill <{}> id={}", jobs.getName(), jobId); jobs.cancel(jobId, "killed by JTM"); } } } } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } }