ProposedTimestamp.java

  1. /*
  2.  * Copyright (C) 2016, Google Inc. and others
  3.  *
  4.  * This program and the accompanying materials are made available under the
  5.  * terms of the Eclipse Distribution License v. 1.0 which is available at
  6.  * https://www.eclipse.org/org/documents/edl-v10.php.
  7.  *
  8.  * SPDX-License-Identifier: BSD-3-Clause
  9.  */

  10. package org.eclipse.jgit.util.time;

  11. import static java.util.concurrent.TimeUnit.MICROSECONDS;
  12. import static java.util.concurrent.TimeUnit.MILLISECONDS;

  13. import java.sql.Timestamp;
  14. import java.time.Duration;
  15. import java.time.Instant;
  16. import java.util.Date;
  17. import java.util.Iterator;
  18. import java.util.concurrent.TimeUnit;
  19. import java.util.concurrent.TimeoutException;

  20. /**
  21.  * A timestamp generated by
  22.  * {@link org.eclipse.jgit.util.time.MonotonicClock#propose()}.
  23.  * <p>
  24.  * ProposedTimestamp implements AutoCloseable so that implementations can
  25.  * release resources associated with obtaining certainty about time elapsing.
  26.  * For example the constructing MonotonicClock may start network IO with peers
  27.  * when creating the ProposedTimestamp, and {@link #close()} can ensure those
  28.  * network resources are released in a timely fashion.
  29.  *
  30.  * @since 4.6
  31.  */
  32. public abstract class ProposedTimestamp implements AutoCloseable {
  33.     /**
  34.      * Wait for several timestamps.
  35.      *
  36.      * @param times
  37.      *            timestamps to wait on.
  38.      * @param maxWait
  39.      *            how long to wait for the timestamps.
  40.      * @throws java.lang.InterruptedException
  41.      *             current thread was interrupted before the waiting process
  42.      *             completed normally.
  43.      * @throws java.util.concurrent.TimeoutException
  44.      *             the timeout was reached without the proposed timestamp become
  45.      *             certainly in the past.
  46.      */
  47.     public static void blockUntil(Iterable<ProposedTimestamp> times,
  48.             Duration maxWait) throws TimeoutException, InterruptedException {
  49.         Iterator<ProposedTimestamp> itr = times.iterator();
  50.         if (!itr.hasNext()) {
  51.             return;
  52.         }

  53.         long now = System.currentTimeMillis();
  54.         long deadline = now + maxWait.toMillis();
  55.         for (;;) {
  56.             long w = deadline - now;
  57.             if (w < 0) {
  58.                 throw new TimeoutException();
  59.             }
  60.             itr.next().blockUntil(Duration.ofMillis(w));
  61.             if (itr.hasNext()) {
  62.                 now = System.currentTimeMillis();
  63.             } else {
  64.                 break;
  65.             }
  66.         }
  67.     }

  68.     /**
  69.      * Read the timestamp as {@code unit} since the epoch.
  70.      * <p>
  71.      * The timestamp value for a specific {@code ProposedTimestamp} object never
  72.      * changes, and can be read before {@link #blockUntil(Duration)}.
  73.      *
  74.      * @param unit
  75.      *            what unit to return the timestamp in. The timestamp will be
  76.      *            rounded if the unit is bigger than the clock's granularity.
  77.      * @return {@code unit} since the epoch.
  78.      */
  79.     public abstract long read(TimeUnit unit);

  80.     /**
  81.      * Wait for this proposed timestamp to be certainly in the recent past.
  82.      * <p>
  83.      * This method forces the caller to wait up to {@code timeout} for
  84.      * {@code this} to pass sufficiently into the past such that the creating
  85.      * {@link org.eclipse.jgit.util.time.MonotonicClock} instance will not
  86.      * create an earlier timestamp.
  87.      *
  88.      * @param maxWait
  89.      *            how long the implementation may block the caller.
  90.      * @throws java.lang.InterruptedException
  91.      *             current thread was interrupted before the waiting process
  92.      *             completed normally.
  93.      * @throws java.util.concurrent.TimeoutException
  94.      *             the timeout was reached without the proposed timestamp
  95.      *             becoming certainly in the past.
  96.      */
  97.     public abstract void blockUntil(Duration maxWait)
  98.             throws InterruptedException, TimeoutException;

  99.     /**
  100.      * Get milliseconds since epoch; {@code read(MILLISECONDS}).
  101.      *
  102.      * @return milliseconds since epoch; {@code read(MILLISECONDS}).
  103.      */
  104.     public long millis() {
  105.         return read(MILLISECONDS);
  106.     }

  107.     /**
  108.      * Get microseconds since epoch; {@code read(MICROSECONDS}).
  109.      *
  110.      * @return microseconds since epoch; {@code read(MICROSECONDS}).
  111.      */
  112.     public long micros() {
  113.         return read(MICROSECONDS);
  114.     }

  115.     /**
  116.      * Get time since epoch, with up to microsecond resolution.
  117.      *
  118.      * @return time since epoch, with up to microsecond resolution.
  119.      */
  120.     public Instant instant() {
  121.         long usec = micros();
  122.         long secs = usec / 1000000L;
  123.         long nanos = (usec % 1000000L) * 1000L;
  124.         return Instant.ofEpochSecond(secs, nanos);
  125.     }

  126.     /**
  127.      * Get time since epoch, with up to microsecond resolution.
  128.      *
  129.      * @return time since epoch, with up to microsecond resolution.
  130.      */
  131.     public Timestamp timestamp() {
  132.         return Timestamp.from(instant());
  133.     }

  134.     /**
  135.      * Get time since epoch, with up to millisecond resolution.
  136.      *
  137.      * @return time since epoch, with up to millisecond resolution.
  138.      */
  139.     public Date date() {
  140.         return new Date(millis());
  141.     }

  142.     /**
  143.      * {@inheritDoc}
  144.      * <p>
  145.      * Release resources allocated by this timestamp.
  146.      */
  147.     @Override
  148.     public void close() {
  149.         // Do nothing by default.
  150.     }

  151.     /** {@inheritDoc} */
  152.     @Override
  153.     public String toString() {
  154.         return instant().toString();
  155.     }
  156. }