TimedResource.java
package emissary.core;
import emissary.place.IServiceProviderPlace;
import com.codahale.metrics.Timer;
import jakarta.annotation.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.locks.ReentrantLock;
/**
* Class to help track the things we are interested in monitoring
*/
public class TimedResource implements AutoCloseable {
protected static final Logger LOG = LoggerFactory.getLogger(TimedResource.class);
public static final TimedResource EMPTY = new TimedResource();
@Nullable
private final IMobileAgent agent;
private final int payloadCount;
private final long allowedDuration;
private final String placeName;
private final long started;
@Nullable
private final Timer.Context timerContext;
private final ReentrantLock lock = new ReentrantLock();
private volatile boolean isClosed = false;
private TimedResource() {
isClosed = true;
started = -1;
allowedDuration = -1;
agent = null;
payloadCount = -1;
placeName = "NOOP";
timerContext = null;
}
public TimedResource(final IMobileAgent agent, final IServiceProviderPlace place, final long allowedDuration, final Timer timer) {
this.started = System.currentTimeMillis();
this.agent = agent;
this.payloadCount = agent.payloadCount();
this.placeName = place.getPlaceName();
this.timerContext = timer.time();
this.allowedDuration = allowedDuration;
}
// checks the state of the current place, returns true if it's closed
protected boolean checkState(long now) {
if (allowedDuration > 0 && (now - started) > (allowedDuration * payloadCount)) {
interruptAgent();
}
return isClosed;
}
// test visibility
void interruptAgent() {
// don't grab the lock if we're done
if (isClosed) {
return;
}
lock.lock();
try {
if (!isClosed) {
LOG.debug("Found agent that needs interrupting {} in place {}", agent.getName(), placeName);
agent.interrupt();
}
} catch (RuntimeException e) {
LOG.error("Unable to interrupt agent {}: {}", agent.getName(), e.getMessage(), e);
} finally {
lock.unlock();
}
}
@Override
public void close() {
lock.lock();
try {
if (isClosed) {
return;
}
timerContext.stop();
isClosed = true;
} finally {
lock.unlock();
}
}
}