/*
* Copyright 2016 Adobe.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.adobe.acs.commons.fam.impl;
import com.adobe.acs.commons.fam.ThrottledTaskRunner;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Runnable task that has a time limit
*/
public class TimedRunnable implements Runnable {
long created = System.currentTimeMillis();
long started = -1;
long executed = -1;
long finished = -1;
Runnable work;
ThrottledTaskRunner runner;
int timeout;
TimeUnit timeoutUnit;
private static final Logger LOG = LoggerFactory.getLogger(TimedRunnable.class);
public TimedRunnable(Runnable work, ThrottledTaskRunner runner, int timeout, TimeUnit timeoutUnit) {
this.work = work;
this.runner = runner;
this.timeout = timeout;
this.timeoutUnit = timeoutUnit;
LOG.debug("Task created");
}
/**
* Run the underlying runnable but only give it a fixed duration before
* throwing an interruption
*/
@Override
public void run() {
final Thread thisThread = Thread.currentThread();
final Semaphore timerSemaphore = new Semaphore(0);
Thread watchDog = new Thread(() -> {
boolean finished1 = false;
try {
finished1 = timerSemaphore.tryAcquire(timeout, timeoutUnit);
}catch (InterruptedException ex) {
LOG.error("Watchdog thread interrupted", ex);
}
if (!finished1) {
thisThread.interrupt();
}
});
boolean successful = false;
Throwable error = null;
try {
started = System.currentTimeMillis();
runner.waitForLowCpuAndLowMemory();
executed = System.currentTimeMillis();
if (timeout > 0) {
watchDog.start();
}
work.run();
finished = System.currentTimeMillis();
timerSemaphore.release();
successful = true;
} catch (Throwable ex) {
finished = System.currentTimeMillis();
LOG.error("Task encountered an uncaught exception", ex);
}
runner.logCompletion(created, started, executed, finished, successful, error);
}
}