TimedResource.java

  1. package emissary.core;

  2. import emissary.place.IServiceProviderPlace;

  3. import com.codahale.metrics.Timer;
  4. import org.slf4j.Logger;
  5. import org.slf4j.LoggerFactory;

  6. import java.util.concurrent.locks.ReentrantLock;
  7. import javax.annotation.Nullable;

  8. /**
  9.  * Class to help track the things we are interested in monitoring
  10.  */
  11. public class TimedResource implements AutoCloseable {

  12.     protected static final Logger LOG = LoggerFactory.getLogger(TimedResource.class);

  13.     public static final TimedResource EMPTY = new TimedResource();

  14.     @Nullable
  15.     private final IMobileAgent agent;
  16.     private final int payloadCount;
  17.     private final long allowedDuration;
  18.     private final String placeName;
  19.     private final long started;

  20.     @Nullable
  21.     private final Timer.Context timerContext;

  22.     private final ReentrantLock lock = new ReentrantLock();

  23.     private volatile boolean isClosed = false;

  24.     private TimedResource() {
  25.         isClosed = true;
  26.         started = -1;
  27.         allowedDuration = -1;
  28.         agent = null;
  29.         payloadCount = -1;
  30.         placeName = "NOOP";
  31.         timerContext = null;
  32.     }

  33.     public TimedResource(final IMobileAgent agent, final IServiceProviderPlace place, final long allowedDuration, final Timer timer) {
  34.         this.started = System.currentTimeMillis();
  35.         this.agent = agent;
  36.         this.payloadCount = agent.payloadCount();
  37.         this.placeName = place.getPlaceName();
  38.         this.timerContext = timer.time();
  39.         this.allowedDuration = allowedDuration;

  40.     }

  41.     // checks the state of the current place, returns true if it's closed
  42.     protected boolean checkState(long now) {
  43.         if (allowedDuration > 0 && (now - started) > (allowedDuration * payloadCount)) {
  44.             interruptAgent();
  45.         }
  46.         return isClosed;
  47.     }

  48.     // test visibility
  49.     void interruptAgent() {
  50.         // don't grab the lock if we're done
  51.         if (isClosed) {
  52.             return;
  53.         }
  54.         lock.lock();
  55.         try {
  56.             if (!isClosed) {
  57.                 LOG.debug("Found agent that needs interrupting {} in place {}", agent.getName(), placeName);
  58.                 agent.interrupt();
  59.             }
  60.         } catch (RuntimeException e) {
  61.             LOG.error("Unable to interrupt agent {}: {}", agent.getName(), e.getMessage(), e);
  62.         } finally {
  63.             lock.unlock();
  64.         }
  65.     }

  66.     @Override
  67.     public void close() {
  68.         lock.lock();
  69.         try {
  70.             if (isClosed) {
  71.                 return;
  72.             }
  73.             timerContext.stop();
  74.             isClosed = true;
  75.         } finally {
  76.             lock.unlock();
  77.         }
  78.     }
  79. }