Exemple #1
0
 ServiceManagerState(ImmutableCollection<Service> services) {
   this.numberOfServices = services.size();
   this.servicesByState.putAll(Service.State.NEW, services);
   for (Service service : services) {
     this.startupTimers.put(service, Stopwatch.createUnstarted());
   }
 }
/** @author <a href="http://www.polymap.de">Falko Bräutigam</a> */
public class Timer {

  private static Log log = LogFactory.getLog(Timer.class);

  public static Timer startNow() {
    Timer result = new Timer();
    result.start();
    return result;
  }

  // instance *******************************************

  private Stopwatch watch = Stopwatch.createUnstarted();

  public void start() {
    if (watch.isRunning()) {
      watch.reset().start();
    } else {
      watch.start();
    }
  }

  public long elapsedTime() {
    return watch.elapsed(TimeUnit.MILLISECONDS);
  }
}
 /**
  * DO NOT RUN!!!!
  *
  * @author Joshua Barlin (propoke24)
  * @version 1
  * @return Time between execution and interruption
  * @deprecated Test Code
  */
 @Deprecated
 public static long timer() {
   final Stopwatch stopwatch = Stopwatch.createUnstarted();
   stopwatch.start();
   stopwatch.stop();
   return stopwatch.elapsed(TimeUnit.SECONDS);
 }
  @Test
  public void testCloseDuringPendingRequest() throws Exception {
    CyclicBarrier beforeRequest = new CyclicBarrier(2);
    CyclicBarrier afterRequest = new CyclicBarrier(2);
    StaticRequestProcessor processor = new StaticRequestProcessor(beforeRequest, afterRequest);
    processor.setResponse(
        new TestingResponse(
            HttpStatus.NO_CONTENT, ImmutableListMultimap.<String, String>of(), new byte[0]));

    CyclicBarrier requestComplete = new CyclicBarrier(2);
    TestingClientCallback callback = new TestingClientCallback(requestComplete);

    URI location = URI.create("http://localhost:8080");
    HttpPageBufferClient client =
        new HttpPageBufferClient(
            new TestingHttpClient(processor, executor),
            new DataSize(10, Unit.MEGABYTE),
            new Duration(1, TimeUnit.MINUTES),
            location,
            callback,
            blockEncodingManager,
            executor,
            Stopwatch.createUnstarted());

    assertStatus(client, location, "queued", 0, 0, 0, 0, "not scheduled");

    // send request
    client.scheduleRequest();
    beforeRequest.await(10, TimeUnit.SECONDS);
    assertStatus(client, location, "running", 0, 1, 0, 0, "PROCESSING_REQUEST");
    assertEquals(client.isRunning(), true);
    // request is pending, now close it
    client.close();

    try {
      requestComplete.await(10, TimeUnit.SECONDS);
    } catch (BrokenBarrierException ignored) {
    }
    try {
      afterRequest.await(10, TimeUnit.SECONDS);
    } catch (BrokenBarrierException ignored) {
      afterRequest.reset();
    }
    // client.close() triggers a DELETE request, so wait for it to finish
    beforeRequest.await(10, TimeUnit.SECONDS);
    afterRequest.await(10, TimeUnit.SECONDS);
    requestComplete.await(10, TimeUnit.SECONDS);
    assertStatus(client, location, "closed", 0, 1, 2, 1, "not scheduled");
  }
 public HttpPageBufferClient(
     HttpClient httpClient,
     DataSize maxResponseSize,
     Duration minErrorDuration,
     URI location,
     ClientCallback clientCallback,
     BlockEncodingSerde blockEncodingSerde,
     ScheduledExecutorService executor) {
   this(
       httpClient,
       maxResponseSize,
       minErrorDuration,
       location,
       clientCallback,
       blockEncodingSerde,
       executor,
       Stopwatch.createUnstarted());
 }
  @Override
  public void doFilterInternal(
      final HttpServletRequest request,
      final HttpServletResponse response,
      final FilterChain filterChain)
      throws IOException, ServletException {
    if (LOG.isDebugEnabled()) {
      final String requestDetails = buildRequestDetails(request);

      if (LOG.isDebugEnabled()) {
        LOG.debug(requestDetails + "Begin");
      }

      logCookies(request);

      final ResponseWrapper wrappedResponse = new ResponseWrapper(response);

      final Stopwatch stopwatch = Stopwatch.createUnstarted();
      stopwatch.start();
      try {
        filterChain.doFilter(request, wrappedResponse);
      } finally {
        stopwatch.stop();
        final int status = wrappedResponse.getStatus();

        if (status != 0) {
          LOG.debug(requestDetails + stopwatch.toString() + " (" + status + ")");
        } else {
          LOG.debug(requestDetails + stopwatch.toString());
        }
      }

      return;
    }

    filterChain.doFilter(request, response);
  }
  private Integer mergeTranslations(
      final Long sourceVersionId,
      final Long targetVersionId,
      final int batchStart,
      final int batchLength,
      final boolean useNewerTranslation,
      final List<HLocale> supportedLocales)
      throws Exception {

    final Stopwatch stopwatch = Stopwatch.createUnstarted();
    stopwatch.start();

    List<HTextFlow[]> matches =
        textFlowDAO.getSourceByMatchedContext(
            sourceVersionId, targetVersionId, batchStart, batchLength);

    Multimap<DocumentLocaleKey, TextFlowTargetStateChange> eventMap = HashMultimap.create();

    Map<DocumentLocaleKey, Map<ContentState, Long>> docStatsMap = Maps.newHashMap();

    Map<DocumentLocaleKey, Long> lastUpdatedTargetId = Maps.newHashMap();
    ;

    for (HTextFlow[] results : matches) {
      HTextFlow sourceTf = results[0];
      HTextFlow targetTf = results[1];
      boolean foundChange = false;
      Map<Long, ContentState> localeContentStateMap = Maps.newHashMap();

      for (HLocale hLocale : supportedLocales) {
        HTextFlowTarget sourceTft = sourceTf.getTargets().get(hLocale.getId());
        // only process translated state
        if (sourceTft == null || !sourceTft.getState().isTranslated()) {
          continue;
        }

        HTextFlowTarget targetTft = targetTf.getTargets().get(hLocale.getId());
        if (targetTft == null) {
          targetTft = new HTextFlowTarget(targetTf, hLocale);
          targetTft.setVersionNum(0);
          targetTf.getTargets().put(hLocale.getId(), targetTft);
        }

        if (MergeTranslationsServiceImpl.shouldMerge(sourceTft, targetTft, useNewerTranslation)) {
          foundChange = true;

          ContentState oldState = targetTft.getState();
          localeContentStateMap.put(hLocale.getId(), oldState);
          mergeTextFlowTarget(sourceTft, targetTft);
        }
      }
      if (foundChange) {
        translationStateCacheImpl.clearDocumentStatistics(targetTf.getDocument().getId());
        textFlowDAO.makePersistent(targetTf);
        textFlowDAO.flush();

        for (Map.Entry<Long, ContentState> entry : localeContentStateMap.entrySet()) {
          HTextFlowTarget updatedTarget = targetTf.getTargets().get(entry.getKey());

          DocumentLocaleKey key =
              new DocumentLocaleKey(
                  targetTf.getDocument().getId(), updatedTarget.getLocale().getLocaleId());

          eventMap.put(
              key,
              new TextFlowTargetStateEvent.TextFlowTargetStateChange(
                  targetTf.getId(),
                  updatedTarget.getId(),
                  updatedTarget.getState(),
                  entry.getValue()));

          lastUpdatedTargetId.put(key, updatedTarget.getId());

          Map<ContentState, Long> contentStateDeltas =
              docStatsMap.get(key) == null ? Maps.newHashMap() : docStatsMap.get(key);

          DocStatsEvent.updateContentStateDeltas(
              contentStateDeltas,
              updatedTarget.getState(),
              entry.getValue(),
              targetTf.getWordCount());

          docStatsMap.put(key, contentStateDeltas);
        }
      }
    }
    Long actorId = authenticatedAccount.getPerson().getId();
    for (Map.Entry<DocumentLocaleKey, Collection<TextFlowTargetStateChange>> entry :
        eventMap.asMap().entrySet()) {
      TextFlowTargetStateEvent tftUpdatedEvent =
          new TextFlowTargetStateEvent(
              entry.getKey(), targetVersionId, actorId, ImmutableList.copyOf(entry.getValue()));
      textFlowTargetStateEvent.fire(tftUpdatedEvent);
    }
    for (Map.Entry<DocumentLocaleKey, Map<ContentState, Long>> entry : docStatsMap.entrySet()) {
      DocStatsEvent docEvent =
          new DocStatsEvent(
              entry.getKey(),
              targetVersionId,
              entry.getValue(),
              lastUpdatedTargetId.get(entry.getKey()));
      docStatsEvent.fire(docEvent);
    }
    stopwatch.stop();
    log.info(
        "Complete merge translations of {} in {}",
        matches.size() * supportedLocales.size(),
        stopwatch);
    return matches.size() * supportedLocales.size();
  }
/**
 * Supplies an arbitrary "default" instance for a wide range of types, often useful in testing
 * utilities.
 *
 * <p>Covers arrays, enums and common types defined in {@code java.lang}, {@code java.lang.reflect},
 * {@code java.io}, {@code java.nio}, {@code java.math}, {@code java.util}, {@code
 * java.util.concurrent}, {@code java.util.regex}, {@code com.google.common.base}, {@code
 * com.google.common.collect} and {@code com.google.common.primitives}. In addition, if the type
 * exposes at least one public static final constant of the same type, one of the constants will be
 * used; or if the class exposes a public parameter-less constructor then it will be "new"d and
 * returned.
 *
 * <p>All default instances returned by {@link #get} are generics-safe. Clients won't get type
 * errors for using {@code get(Comparator.class)} as a {@code Comparator<Foo>}, for example.
 * Immutable empty instances are returned for collection types; {@code ""} for string; {@code 0} for
 * number types; reasonable default instance for other stateless types. For mutable types, a fresh
 * instance is created each time {@code get()} is called.
 *
 * @author Kevin Bourrillion
 * @author Ben Yu
 * @since 12.0
 */
@Beta
public final class ArbitraryInstances {

  private static final Ordering<Field> BY_FIELD_NAME =
      new Ordering<Field>() {
        @Override
        public int compare(Field left, Field right) {
          return left.getName().compareTo(right.getName());
        }
      };

  /**
   * Returns a new {@code MatchResult} that corresponds to a successful match. Apache Harmony (used
   * in Android) requires a successful match in order to generate a {@code MatchResult}:
   * http://goo.gl/5VQFmC
   */
  private static MatchResult newMatchResult() {
    Matcher matcher = Pattern.compile(".").matcher("X");
    matcher.find();
    return matcher.toMatchResult();
  }

  private static final ClassToInstanceMap<Object> DEFAULTS =
      ImmutableClassToInstanceMap.builder()
          // primitives
          .put(Object.class, "")
          .put(Number.class, 0)
          .put(UnsignedInteger.class, UnsignedInteger.ZERO)
          .put(UnsignedLong.class, UnsignedLong.ZERO)
          .put(BigInteger.class, BigInteger.ZERO)
          .put(BigDecimal.class, BigDecimal.ZERO)
          .put(CharSequence.class, "")
          .put(String.class, "")
          .put(Pattern.class, Pattern.compile(""))
          .put(MatchResult.class, newMatchResult())
          .put(TimeUnit.class, TimeUnit.SECONDS)
          .put(Charset.class, Charsets.UTF_8)
          .put(Currency.class, Currency.getInstance(Locale.US))
          .put(Locale.class, Locale.US)
          // common.base
          .put(CharMatcher.class, CharMatcher.NONE)
          .put(Joiner.class, Joiner.on(','))
          .put(Splitter.class, Splitter.on(','))
          .put(Optional.class, Optional.absent())
          .put(Predicate.class, Predicates.alwaysTrue())
          .put(Equivalence.class, Equivalence.equals())
          .put(Ticker.class, Ticker.systemTicker())
          .put(Stopwatch.class, Stopwatch.createUnstarted())
          // io types
          .put(InputStream.class, new ByteArrayInputStream(new byte[0]))
          .put(ByteArrayInputStream.class, new ByteArrayInputStream(new byte[0]))
          .put(Readable.class, new StringReader(""))
          .put(Reader.class, new StringReader(""))
          .put(StringReader.class, new StringReader(""))
          .put(Buffer.class, ByteBuffer.allocate(0))
          .put(CharBuffer.class, CharBuffer.allocate(0))
          .put(ByteBuffer.class, ByteBuffer.allocate(0))
          .put(ShortBuffer.class, ShortBuffer.allocate(0))
          .put(IntBuffer.class, IntBuffer.allocate(0))
          .put(LongBuffer.class, LongBuffer.allocate(0))
          .put(FloatBuffer.class, FloatBuffer.allocate(0))
          .put(DoubleBuffer.class, DoubleBuffer.allocate(0))
          .put(File.class, new File(""))
          .put(ByteSource.class, ByteSource.empty())
          .put(CharSource.class, CharSource.empty())
          .put(ByteSink.class, NullByteSink.INSTANCE)
          .put(CharSink.class, NullByteSink.INSTANCE.asCharSink(Charsets.UTF_8))
          // All collections are immutable empty. So safe for any type parameter.
          .put(Iterator.class, ImmutableSet.of().iterator())
          .put(PeekingIterator.class, Iterators.peekingIterator(ImmutableSet.of().iterator()))
          .put(ListIterator.class, ImmutableList.of().listIterator())
          .put(Iterable.class, ImmutableSet.of())
          .put(Collection.class, ImmutableList.of())
          .put(ImmutableCollection.class, ImmutableList.of())
          .put(List.class, ImmutableList.of())
          .put(ImmutableList.class, ImmutableList.of())
          .put(Set.class, ImmutableSet.of())
          .put(ImmutableSet.class, ImmutableSet.of())
          .put(SortedSet.class, ImmutableSortedSet.of())
          .put(ImmutableSortedSet.class, ImmutableSortedSet.of())
          .put(NavigableSet.class, Sets.unmodifiableNavigableSet(Sets.newTreeSet()))
          .put(Map.class, ImmutableMap.of())
          .put(ImmutableMap.class, ImmutableMap.of())
          .put(SortedMap.class, ImmutableSortedMap.of())
          .put(ImmutableSortedMap.class, ImmutableSortedMap.of())
          .put(NavigableMap.class, Maps.unmodifiableNavigableMap(Maps.newTreeMap()))
          .put(Multimap.class, ImmutableMultimap.of())
          .put(ImmutableMultimap.class, ImmutableMultimap.of())
          .put(ListMultimap.class, ImmutableListMultimap.of())
          .put(ImmutableListMultimap.class, ImmutableListMultimap.of())
          .put(SetMultimap.class, ImmutableSetMultimap.of())
          .put(ImmutableSetMultimap.class, ImmutableSetMultimap.of())
          .put(
              SortedSetMultimap.class,
              Multimaps.unmodifiableSortedSetMultimap(TreeMultimap.create()))
          .put(Multiset.class, ImmutableMultiset.of())
          .put(ImmutableMultiset.class, ImmutableMultiset.of())
          .put(SortedMultiset.class, ImmutableSortedMultiset.of())
          .put(ImmutableSortedMultiset.class, ImmutableSortedMultiset.of())
          .put(BiMap.class, ImmutableBiMap.of())
          .put(ImmutableBiMap.class, ImmutableBiMap.of())
          .put(Table.class, ImmutableTable.of())
          .put(ImmutableTable.class, ImmutableTable.of())
          .put(RowSortedTable.class, Tables.unmodifiableRowSortedTable(TreeBasedTable.create()))
          .put(ClassToInstanceMap.class, ImmutableClassToInstanceMap.builder().build())
          .put(ImmutableClassToInstanceMap.class, ImmutableClassToInstanceMap.builder().build())
          .put(Comparable.class, ByToString.INSTANCE)
          .put(Comparator.class, AlwaysEqual.INSTANCE)
          .put(Ordering.class, AlwaysEqual.INSTANCE)
          .put(Range.class, Range.all())
          .put(MapConstraint.class, MapConstraints.notNull())
          .put(MapDifference.class, Maps.difference(ImmutableMap.of(), ImmutableMap.of()))
          .put(
              SortedMapDifference.class,
              Maps.difference(ImmutableSortedMap.of(), ImmutableSortedMap.of()))
          // reflect
          .put(AnnotatedElement.class, Object.class)
          .put(GenericDeclaration.class, Object.class)
          .put(Type.class, Object.class)
          .build();

  /**
   * type -> implementation. Inherently mutable interfaces and abstract classes are mapped to their
   * default implementations and are "new"d upon get().
   */
  private static final ConcurrentMap<Class<?>, Class<?>> implementations = Maps.newConcurrentMap();

  private static <T> void setImplementation(Class<T> type, Class<? extends T> implementation) {
    checkArgument(type != implementation, "Don't register %s to itself!", type);
    checkArgument(
        !DEFAULTS.containsKey(type), "A default value was already registered for %s", type);
    checkArgument(
        implementations.put(type, implementation) == null,
        "Implementation for %s was already registered",
        type);
  }

  static {
    setImplementation(Appendable.class, StringBuilder.class);
    setImplementation(BlockingQueue.class, LinkedBlockingDeque.class);
    setImplementation(BlockingDeque.class, LinkedBlockingDeque.class);
    setImplementation(ConcurrentMap.class, ConcurrentHashMap.class);
    setImplementation(ConcurrentNavigableMap.class, ConcurrentSkipListMap.class);
    setImplementation(CountDownLatch.class, Dummies.DummyCountDownLatch.class);
    setImplementation(Deque.class, ArrayDeque.class);
    setImplementation(OutputStream.class, ByteArrayOutputStream.class);
    setImplementation(PrintStream.class, Dummies.InMemoryPrintStream.class);
    setImplementation(PrintWriter.class, Dummies.InMemoryPrintWriter.class);
    setImplementation(Queue.class, ArrayDeque.class);
    setImplementation(Random.class, Dummies.DeterministicRandom.class);
    setImplementation(
        ScheduledThreadPoolExecutor.class, Dummies.DummyScheduledThreadPoolExecutor.class);
    setImplementation(ThreadPoolExecutor.class, Dummies.DummyScheduledThreadPoolExecutor.class);
    setImplementation(Writer.class, StringWriter.class);
    setImplementation(Runnable.class, Dummies.DummyRunnable.class);
    setImplementation(ThreadFactory.class, Dummies.DummyThreadFactory.class);
    setImplementation(Executor.class, Dummies.DummyExecutor.class);
  }

  @SuppressWarnings("unchecked") // it's a subtype map
  @Nullable
  private static <T> Class<? extends T> getImplementation(Class<T> type) {
    return (Class<? extends T>) implementations.get(type);
  }

  private static final Logger logger = Logger.getLogger(ArbitraryInstances.class.getName());

  /**
   * Returns an arbitrary instance for {@code type}, or {@code null} if no arbitrary instance can be
   * determined.
   */
  @Nullable
  public static <T> T get(Class<T> type) {
    T defaultValue = DEFAULTS.getInstance(type);
    if (defaultValue != null) {
      return defaultValue;
    }
    Class<? extends T> implementation = getImplementation(type);
    if (implementation != null) {
      return get(implementation);
    }
    if (type.isEnum()) {
      T[] enumConstants = type.getEnumConstants();
      return (enumConstants.length == 0) ? null : enumConstants[0];
    }
    if (type.isArray()) {
      return createEmptyArray(type);
    }
    T jvmDefault = Defaults.defaultValue(Primitives.unwrap(type));
    if (jvmDefault != null) {
      return jvmDefault;
    }
    if (Modifier.isAbstract(type.getModifiers()) || !Modifier.isPublic(type.getModifiers())) {
      return arbitraryConstantInstanceOrNull(type);
    }
    final Constructor<T> constructor;
    try {
      constructor = type.getConstructor();
    } catch (NoSuchMethodException e) {
      return arbitraryConstantInstanceOrNull(type);
    }
    constructor.setAccessible(true); // accessibility check is too slow
    try {
      return constructor.newInstance();
    } catch (InstantiationException impossible) {
      throw new AssertionError(impossible);
    } catch (IllegalAccessException impossible) {
      throw new AssertionError(impossible);
    } catch (InvocationTargetException e) {
      logger.log(Level.WARNING, "Exception while invoking default constructor.", e.getCause());
      return arbitraryConstantInstanceOrNull(type);
    }
  }

  @Nullable
  private static <T> T arbitraryConstantInstanceOrNull(Class<T> type) {
    Field[] fields = type.getDeclaredFields();
    Arrays.sort(fields, BY_FIELD_NAME);
    for (Field field : fields) {
      if (Modifier.isPublic(field.getModifiers())
          && Modifier.isStatic(field.getModifiers())
          && Modifier.isFinal(field.getModifiers())) {
        if (field.getGenericType() == field.getType() && type.isAssignableFrom(field.getType())) {
          field.setAccessible(true);
          try {
            T constant = type.cast(field.get(null));
            if (constant != null) {
              return constant;
            }
          } catch (IllegalAccessException impossible) {
            throw new AssertionError(impossible);
          }
        }
      }
    }
    return null;
  }

  private static <T> T createEmptyArray(Class<T> arrayType) {
    return arrayType.cast(Array.newInstance(arrayType.getComponentType(), 0));
  }

  // Internal implementations of some classes, with public default constructor that get() needs.
  private static final class Dummies {

    public static final class InMemoryPrintStream extends PrintStream {
      public InMemoryPrintStream() {
        super(new ByteArrayOutputStream());
      }
    }

    public static final class InMemoryPrintWriter extends PrintWriter {
      public InMemoryPrintWriter() {
        super(new StringWriter());
      }
    }

    public static final class DeterministicRandom extends Random {
      public DeterministicRandom() {
        super(0);
      }
    }

    public static final class DummyScheduledThreadPoolExecutor extends ScheduledThreadPoolExecutor {
      public DummyScheduledThreadPoolExecutor() {
        super(1);
      }
    }

    public static final class DummyCountDownLatch extends CountDownLatch {
      public DummyCountDownLatch() {
        super(0);
      }
    }

    public static final class DummyRunnable implements Runnable, Serializable {
      @Override
      public void run() {}
    }

    public static final class DummyThreadFactory implements ThreadFactory, Serializable {
      @Override
      public Thread newThread(Runnable r) {
        return new Thread(r);
      }
    }

    public static final class DummyExecutor implements Executor, Serializable {
      @Override
      public void execute(Runnable command) {}
    }
  }

  private static final class NullByteSink extends ByteSink implements Serializable {
    private static final NullByteSink INSTANCE = new NullByteSink();

    @Override
    public OutputStream openStream() {
      return ByteStreams.nullOutputStream();
    }
  }

  // Compare by toString() to satisfy 2 properties:
  // 1. compareTo(null) should throw NullPointerException
  // 2. the order is deterministic and easy to understand, for debugging purpose.
  private static final class ByToString implements Comparable<Object>, Serializable {
    private static final ByToString INSTANCE = new ByToString();

    @Override
    public int compareTo(Object o) {
      return toString().compareTo(o.toString());
    }

    @Override
    public String toString() {
      return "BY_TO_STRING";
    }

    private Object readResolve() {
      return INSTANCE;
    }
  }

  // Always equal is a valid total ordering. And it works for any Object.
  private static final class AlwaysEqual extends Ordering<Object> implements Serializable {
    private static final AlwaysEqual INSTANCE = new AlwaysEqual();

    @Override
    public int compare(Object o1, Object o2) {
      return 0;
    }

    @Override
    public String toString() {
      return "ALWAYS_EQUAL";
    }

    private Object readResolve() {
      return INSTANCE;
    }
  }

  private ArbitraryInstances() {}
}
 public static void startTimer(String name) {
   Stopwatch stopwatch = Stopwatch.createUnstarted();
   timers.put(name + Thread.currentThread().getId(), stopwatch);
   stopwatch.start();
 }
public class CountdownTimer {

  Stopwatch stopwatch = Stopwatch.createUnstarted();
  Duration limit;

  private CountdownTimer(Duration limit) {
    this.limit = limit;
  }

  /** starts the timer, either initially or if {@link #pause()}d; no-op if already running */
  public synchronized CountdownTimer start() {
    if (!stopwatch.isRunning()) stopwatch.start();
    return this;
  }

  /** pauses the timer, if running; no-op if not running */
  public synchronized CountdownTimer pause() {
    if (stopwatch.isRunning()) stopwatch.stop();
    return this;
  }

  /** returns underlying stopwatch, which caller can inspect for more details or modify */
  public Stopwatch getStopwatch() {
    return stopwatch;
  }

  /** how much total time this timer should run for */
  public Duration getLimit() {
    return limit;
  }

  /**
   * return how long the timer has been running (may be longer than {@link #getLimit()} if {@link
   * #isExpired()})
   */
  public Duration getDurationElapsed() {
    return Duration.nanos(stopwatch.elapsed(TimeUnit.NANOSECONDS));
  }

  /** returns how much time is left (negative if {@link #isExpired()}) */
  public Duration getDurationRemaining() {
    return Duration.millis(limit.toMilliseconds() - stopwatch.elapsed(TimeUnit.MILLISECONDS));
  }

  /** true iff the timer has run for more than the duration specified at creation time */
  public boolean isExpired() {
    return stopwatch.elapsed(TimeUnit.MILLISECONDS) > limit.toMilliseconds();
  }

  /** true iff {@link #isNotPaused()} and not {@link #isExpired()} */
  public boolean isLive() {
    return isNotPaused() && isNotExpired();
  }

  /** true iff not {@link #isExpired()} */
  public boolean isNotExpired() {
    return !isExpired();
  }

  /**
   * false if started or paused, true otherwise (ie the timer is counting down, even if it is
   * expired)
   */
  public boolean isNotPaused() {
    return stopwatch.isRunning();
  }

  /** @deprecated since 0.9.0 use better named {@link #isNotPaused()} */
  @Deprecated
  public boolean isRunning() {
    return isNotPaused();
  }

  // --- constructor methods

  public static CountdownTimer newInstanceStarted(Duration duration) {
    return new CountdownTimer(duration).start();
  }

  public static CountdownTimer newInstancePaused(Duration duration) {
    return new CountdownTimer(duration).pause();
  }

  /**
   * block (on this object) until completed
   *
   * @throws InterruptedException
   */
  public synchronized void waitForExpiry() throws InterruptedException {
    while (waitOnForExpiry(this)) {}
    ;
  }

  /**
   * as {@link #waitForExpiry()} but catches and wraps InterruptedException as unchecked
   * RuntimeInterruptedExcedption
   */
  public synchronized void waitForExpiryUnchecked() {
    waitOnForExpiryUnchecked(this);
  }

  /**
   * block on the given argument until the timer is completed or the object receives a notified;
   * callers must be synchronized on the waitTarget
   *
   * @return true if the object is notified (or receives a spurious wake), false if the duration is
   *     expired
   * @throws InterruptedException
   */
  public boolean waitOnForExpiry(Object waitTarget) throws InterruptedException {
    Duration remainder = getDurationRemaining();
    if (remainder.toMilliseconds() <= 0) return false;
    waitTarget.wait(remainder.toMilliseconds());
    return true;
  }
  /**
   * as {@link #waitOnForExpiry(Object)} but catches and wraps InterruptedException as unchecked
   * RuntimeInterruptedExcedption
   */
  public boolean waitOnForExpiryUnchecked(Object waitTarget) {
    try {
      return waitOnForExpiry(waitTarget);
    } catch (InterruptedException e) {
      throw Exceptions.propagate(e);
    }
  }
}
  /**
   * Runs a filter.
   *
   * @param pipelineConfigurationFile Pipeline configuration file.
   * @param duration Timeout period.
   * @param variables Substitution key-value pairs into pipeline configuration file.
   * @throws IOException if configuration cannot be loaded.
   */
  protected void benchmark(
      final String pipelineConfigurationFile,
      final Duration duration,
      final ImmutableMap<String, String> variables)
      throws IOException {
    // Replace any variables in the configuration file
    String configuration =
        Resources.toString(Resources.getResource(pipelineConfigurationFile), Charsets.UTF_8);
    for (final Map.Entry<String, String> entry : variables.entrySet()) {
      configuration = configuration.replace(entry.getKey(), entry.getValue());
    }

    // Load the specified stock configuration
    final PipelineConfiguration stockPipelineConfiguration =
        new StaticConfiguration.Builder()
            .addSource(new JsonNodeLiteralSource.Builder().setSource(configuration).build())
            .setObjectMapper(PipelineConfiguration.createObjectMapper(_injector))
            .build()
            .getRequiredAs(PipelineConfiguration.class);

    // Canary tracking
    LOGGER.info(
        String.format("Expected canaries; periods=%s", stockPipelineConfiguration.getPeriods()));
    final CountDownLatch latch = new CountDownLatch(stockPipelineConfiguration.getPeriods().size());
    final Set<Period> periods = Sets.newConcurrentHashSet();

    // Create custom "canary" sink
    final ListeningSink sink =
        new ListeningSink(
            (periodicData) -> {
              if (periodicData != null) {
                for (final String metricName : periodicData.getData().keys()) {
                  if (TestFileGenerator.CANARY.equals(metricName)) {
                    if (periods.add(periodicData.getPeriod())) {
                      LOGGER.info(
                          String.format(
                              "Canary flew; filter=%s, period=%s",
                              this.getClass(), periodicData.getPeriod()));
                      latch.countDown();
                    }
                  }
                }
              }
              return null;
            });

    // Add the custom "canary" sink
    final List<Sink> benchmarkSinks = Lists.newArrayList(stockPipelineConfiguration.getSinks());
    benchmarkSinks.add(sink);

    // Create the custom configuration
    final PipelineConfiguration benchmarkPipelineConfiguration =
        OvalBuilder.<PipelineConfiguration, PipelineConfiguration.Builder>clone(
                stockPipelineConfiguration)
            .setSinks(benchmarkSinks)
            .build();

    // Instantiate the pipeline
    final Pipeline pipeline = new Pipeline(benchmarkPipelineConfiguration);

    // Execute the pipeline until the canary flies the coop
    try {
      LOGGER.debug(
          String.format("Launching pipeline; configuration=%s", pipelineConfigurationFile));
      final Stopwatch timer = Stopwatch.createUnstarted();
      timer.start();
      pipeline.launch();

      if (!latch.await(duration.getMillis(), TimeUnit.MILLISECONDS)) {
        LOGGER.error("Test timed out");
        throw new RuntimeException("Test timed out");
      }

      timer.stop();
      LOGGER.info(
          String.format(
              "Performance filter result; filter=%s, seconds=%s",
              this.getClass(), timer.elapsed(TimeUnit.SECONDS)));

    } catch (final InterruptedException e) {
      Thread.interrupted();
      throw new RuntimeException("Test interrupted");
    } finally {
      pipeline.shutdown();
    }
  }
 TimingProducerMonitor(
     ProducerTimingRecorder recorder, Ticker ticker, Stopwatch componentStopwatch) {
   this.recorder = recorder;
   this.stopwatch = Stopwatch.createUnstarted(ticker);
   this.componentStopwatch = componentStopwatch;
 }
  @Test
  public void testHappyPath() throws Exception {
    Page expectedPage = new Page(100);

    DataSize expectedMaxSize = new DataSize(11, Unit.MEGABYTE);
    MockExchangeRequestProcessor processor = new MockExchangeRequestProcessor(expectedMaxSize);

    CyclicBarrier requestComplete = new CyclicBarrier(2);

    TestingClientCallback callback = new TestingClientCallback(requestComplete);

    URI location = URI.create("http://localhost:8080");
    HttpPageBufferClient client =
        new HttpPageBufferClient(
            new TestingHttpClient(processor, executor),
            expectedMaxSize,
            new Duration(1, TimeUnit.MINUTES),
            location,
            callback,
            blockEncodingManager,
            executor,
            Stopwatch.createUnstarted());

    assertStatus(client, location, "queued", 0, 0, 0, 0, "not scheduled");

    // fetch a page and verify
    processor.addPage(location, expectedPage);
    callback.resetStats();
    client.scheduleRequest();
    requestComplete.await(10, TimeUnit.SECONDS);

    assertEquals(callback.getPages().size(), 1);
    assertPageEquals(expectedPage, callback.getPages().get(0));
    assertEquals(callback.getCompletedRequests(), 1);
    assertEquals(callback.getFinishedBuffers(), 0);
    assertStatus(client, location, "queued", 1, 1, 1, 0, "not scheduled");

    // fetch no data and verify
    callback.resetStats();
    client.scheduleRequest();
    requestComplete.await(10, TimeUnit.SECONDS);

    assertEquals(callback.getPages().size(), 0);
    assertEquals(callback.getCompletedRequests(), 1);
    assertEquals(callback.getFinishedBuffers(), 0);
    assertStatus(client, location, "queued", 1, 2, 2, 0, "not scheduled");

    // fetch two more pages and verify
    processor.addPage(location, expectedPage);
    processor.addPage(location, expectedPage);
    callback.resetStats();
    client.scheduleRequest();
    requestComplete.await(10, TimeUnit.SECONDS);

    assertEquals(callback.getPages().size(), 2);
    assertPageEquals(expectedPage, callback.getPages().get(0));
    assertPageEquals(expectedPage, callback.getPages().get(1));
    assertEquals(callback.getCompletedRequests(), 1);
    assertEquals(callback.getFinishedBuffers(), 0);
    assertEquals(callback.getFailedBuffers(), 0);
    callback.resetStats();
    assertStatus(client, location, "queued", 3, 3, 3, 0, "not scheduled");

    // finish and verify
    callback.resetStats();
    processor.setComplete(location);
    client.scheduleRequest();
    requestComplete.await(10, TimeUnit.SECONDS);

    // get the buffer complete signal
    assertEquals(callback.getPages().size(), 0);
    assertEquals(callback.getCompletedRequests(), 1);

    // schedule the delete call to the buffer
    callback.resetStats();
    client.scheduleRequest();
    requestComplete.await(10, TimeUnit.SECONDS);
    assertEquals(callback.getFinishedBuffers(), 1);

    assertEquals(callback.getPages().size(), 0);
    assertEquals(callback.getCompletedRequests(), 0);
    assertEquals(callback.getFailedBuffers(), 0);

    assertStatus(client, location, "closed", 3, 5, 5, 0, "not scheduled");
  }
  @Test
  public void testExceptionFromResponseHandler() throws Exception {
    TestingTicker ticker = new TestingTicker();
    AtomicReference<Duration> tickerIncrement =
        new AtomicReference<>(new Duration(0, TimeUnit.SECONDS));

    TestingHttpClient.Processor processor =
        (input) -> {
          Duration delta = tickerIncrement.get();
          ticker.increment(delta.toMillis(), TimeUnit.MILLISECONDS);
          throw new RuntimeException("Foo");
        };

    CyclicBarrier requestComplete = new CyclicBarrier(2);
    TestingClientCallback callback = new TestingClientCallback(requestComplete);

    URI location = URI.create("http://localhost:8080");
    HttpPageBufferClient client =
        new HttpPageBufferClient(
            new TestingHttpClient(processor, executor),
            new DataSize(10, Unit.MEGABYTE),
            new Duration(1, TimeUnit.MINUTES),
            location,
            callback,
            blockEncodingManager,
            executor,
            Stopwatch.createUnstarted(ticker));

    assertStatus(client, location, "queued", 0, 0, 0, 0, "not scheduled");

    // request processor will throw exception, verify the request is marked a completed
    // this starts the error stopwatch
    client.scheduleRequest();
    requestComplete.await(10, TimeUnit.SECONDS);
    assertEquals(callback.getPages().size(), 0);
    assertEquals(callback.getCompletedRequests(), 1);
    assertEquals(callback.getFinishedBuffers(), 0);
    assertEquals(callback.getFailedBuffers(), 0);
    assertStatus(client, location, "queued", 0, 1, 1, 1, "not scheduled");

    // advance time forward, but not enough to fail the client
    tickerIncrement.set(new Duration(30, TimeUnit.SECONDS));

    // verify that the client has not failed
    client.scheduleRequest();
    requestComplete.await(10, TimeUnit.SECONDS);
    assertEquals(callback.getPages().size(), 0);
    assertEquals(callback.getCompletedRequests(), 2);
    assertEquals(callback.getFinishedBuffers(), 0);
    assertEquals(callback.getFailedBuffers(), 0);
    assertStatus(client, location, "queued", 0, 2, 2, 2, "not scheduled");

    // advance time forward beyond the minimum error duration
    tickerIncrement.set(new Duration(31, TimeUnit.SECONDS));

    // verify that the client has failed
    client.scheduleRequest();
    requestComplete.await(10, TimeUnit.SECONDS);
    assertEquals(callback.getPages().size(), 0);
    assertEquals(callback.getCompletedRequests(), 3);
    assertEquals(callback.getFinishedBuffers(), 0);
    assertEquals(callback.getFailedBuffers(), 1);
    assertInstanceOf(callback.getFailure(), PageTransportTimeoutException.class);
    assertContains(
        callback.getFailure().getMessage(),
        WORKER_NODE_ERROR + " (http://localhost:8080/0 - requests failed for 61.00s)");
    assertStatus(client, location, "queued", 0, 3, 3, 3, "not scheduled");
  }
  @Test
  public void testInvalidResponses() throws Exception {
    CyclicBarrier beforeRequest = new CyclicBarrier(1);
    CyclicBarrier afterRequest = new CyclicBarrier(1);
    StaticRequestProcessor processor = new StaticRequestProcessor(beforeRequest, afterRequest);

    CyclicBarrier requestComplete = new CyclicBarrier(2);
    TestingClientCallback callback = new TestingClientCallback(requestComplete);

    URI location = URI.create("http://localhost:8080");
    HttpPageBufferClient client =
        new HttpPageBufferClient(
            new TestingHttpClient(processor, executor),
            new DataSize(10, Unit.MEGABYTE),
            new Duration(1, TimeUnit.MINUTES),
            location,
            callback,
            blockEncodingManager,
            executor,
            Stopwatch.createUnstarted());

    assertStatus(client, location, "queued", 0, 0, 0, 0, "not scheduled");

    // send not found response and verify response was ignored
    processor.setResponse(
        new TestingResponse(
            HttpStatus.NOT_FOUND,
            ImmutableListMultimap.of(CONTENT_TYPE, PRESTO_PAGES),
            new byte[0]));
    client.scheduleRequest();
    requestComplete.await(10, TimeUnit.SECONDS);
    assertEquals(callback.getPages().size(), 0);
    assertEquals(callback.getCompletedRequests(), 1);
    assertEquals(callback.getFinishedBuffers(), 0);
    assertEquals(callback.getFailedBuffers(), 1);
    assertInstanceOf(callback.getFailure(), PageTransportErrorException.class);
    assertContains(
        callback.getFailure().getMessage(),
        "Expected response code to be 200, but was 404 Not Found");
    assertStatus(client, location, "queued", 0, 1, 1, 1, "not scheduled");

    // send invalid content type response and verify response was ignored
    callback.resetStats();
    processor.setResponse(
        new TestingResponse(
            HttpStatus.OK, ImmutableListMultimap.of(CONTENT_TYPE, "INVALID_TYPE"), new byte[0]));
    client.scheduleRequest();
    requestComplete.await(10, TimeUnit.SECONDS);
    assertEquals(callback.getPages().size(), 0);
    assertEquals(callback.getCompletedRequests(), 1);
    assertEquals(callback.getFinishedBuffers(), 0);
    assertEquals(callback.getFailedBuffers(), 1);
    assertInstanceOf(callback.getFailure(), PageTransportErrorException.class);
    assertContains(
        callback.getFailure().getMessage(),
        "Expected application/x-presto-pages response from server but got INVALID_TYPE");
    assertStatus(client, location, "queued", 0, 2, 2, 2, "not scheduled");

    // send unexpected content type response and verify response was ignored
    callback.resetStats();
    processor.setResponse(
        new TestingResponse(
            HttpStatus.OK, ImmutableListMultimap.of(CONTENT_TYPE, "text/plain"), new byte[0]));
    client.scheduleRequest();
    requestComplete.await(10, TimeUnit.SECONDS);
    assertEquals(callback.getPages().size(), 0);
    assertEquals(callback.getCompletedRequests(), 1);
    assertEquals(callback.getFinishedBuffers(), 0);
    assertEquals(callback.getFailedBuffers(), 1);
    assertInstanceOf(callback.getFailure(), PageTransportErrorException.class);
    assertContains(
        callback.getFailure().getMessage(),
        "Expected application/x-presto-pages response from server but got text/plain");
    assertStatus(client, location, "queued", 0, 3, 3, 3, "not scheduled");

    // close client and verify
    client.close();
    requestComplete.await(10, TimeUnit.SECONDS);
    assertStatus(client, location, "closed", 0, 3, 4, 3, "not scheduled");
  }