1 /* 2 * Copyright (C) 2016, Google Inc. 3 * and other copyright owners as documented in the project's IP log. 4 * 5 * This program and the accompanying materials are made available 6 * under the terms of the Eclipse Distribution License v1.0 which 7 * accompanies this distribution, is reproduced below, and is 8 * available at http://www.eclipse.org/org/documents/edl-v10.php 9 * 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or 13 * without modification, are permitted provided that the following 14 * conditions are met: 15 * 16 * - Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 19 * - Redistributions in binary form must reproduce the above 20 * copyright notice, this list of conditions and the following 21 * disclaimer in the documentation and/or other materials provided 22 * with the distribution. 23 * 24 * - Neither the name of the Eclipse Foundation, Inc. nor the 25 * names of its contributors may be used to endorse or promote 26 * products derived from this software without specific prior 27 * written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 30 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 31 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 32 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 33 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 34 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 35 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 36 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 37 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 38 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 40 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 41 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 42 */ 43 44 package org.eclipse.jgit.util.time; 45 46 import static java.util.concurrent.TimeUnit.MICROSECONDS; 47 import static java.util.concurrent.TimeUnit.MILLISECONDS; 48 49 import java.sql.Timestamp; 50 import java.time.Duration; 51 import java.time.Instant; 52 import java.util.Date; 53 import java.util.Iterator; 54 import java.util.concurrent.TimeUnit; 55 import java.util.concurrent.TimeoutException; 56 57 /** 58 * A timestamp generated by 59 * {@link org.eclipse.jgit.util.time.MonotonicClock#propose()}. 60 * <p> 61 * ProposedTimestamp implements AutoCloseable so that implementations can 62 * release resources associated with obtaining certainty about time elapsing. 63 * For example the constructing MonotonicClock may start network IO with peers 64 * when creating the ProposedTimestamp, and {@link #close()} can ensure those 65 * network resources are released in a timely fashion. 66 * 67 * @since 4.6 68 */ 69 public abstract class ProposedTimestamp implements AutoCloseable { 70 /** 71 * Wait for several timestamps. 72 * 73 * @param times 74 * timestamps to wait on. 75 * @param maxWait 76 * how long to wait for the timestamps. 77 * @throws java.lang.InterruptedException 78 * current thread was interrupted before the waiting process 79 * completed normally. 80 * @throws java.util.concurrent.TimeoutException 81 * the timeout was reached without the proposed timestamp become 82 * certainly in the past. 83 */ 84 public static void blockUntil(Iterable<ProposedTimestamp> times, 85 Duration maxWait) throws TimeoutException, InterruptedException { 86 Iterator<ProposedTimestamp> itr = times.iterator(); 87 if (!itr.hasNext()) { 88 return; 89 } 90 91 long now = System.currentTimeMillis(); 92 long deadline = now + maxWait.toMillis(); 93 for (;;) { 94 long w = deadline - now; 95 if (w < 0) { 96 throw new TimeoutException(); 97 } 98 itr.next().blockUntil(Duration.ofMillis(w)); 99 if (itr.hasNext()) { 100 now = System.currentTimeMillis(); 101 } else { 102 break; 103 } 104 } 105 } 106 107 /** 108 * Read the timestamp as {@code unit} since the epoch. 109 * <p> 110 * The timestamp value for a specific {@code ProposedTimestamp} object never 111 * changes, and can be read before {@link #blockUntil(Duration)}. 112 * 113 * @param unit 114 * what unit to return the timestamp in. The timestamp will be 115 * rounded if the unit is bigger than the clock's granularity. 116 * @return {@code unit} since the epoch. 117 */ 118 public abstract long read(TimeUnit unit); 119 120 /** 121 * Wait for this proposed timestamp to be certainly in the recent past. 122 * <p> 123 * This method forces the caller to wait up to {@code timeout} for 124 * {@code this} to pass sufficiently into the past such that the creating 125 * {@link org.eclipse.jgit.util.time.MonotonicClock} instance will not 126 * create an earlier timestamp. 127 * 128 * @param maxWait 129 * how long the implementation may block the caller. 130 * @throws java.lang.InterruptedException 131 * current thread was interrupted before the waiting process 132 * completed normally. 133 * @throws java.util.concurrent.TimeoutException 134 * the timeout was reached without the proposed timestamp 135 * becoming certainly in the past. 136 */ 137 public abstract void blockUntil(Duration maxWait) 138 throws InterruptedException, TimeoutException; 139 140 /** 141 * Get milliseconds since epoch; {@code read(MILLISECONDS}). 142 * 143 * @return milliseconds since epoch; {@code read(MILLISECONDS}). 144 */ 145 public long millis() { 146 return read(MILLISECONDS); 147 } 148 149 /** 150 * Get microseconds since epoch; {@code read(MICROSECONDS}). 151 * 152 * @return microseconds since epoch; {@code read(MICROSECONDS}). 153 */ 154 public long micros() { 155 return read(MICROSECONDS); 156 } 157 158 /** 159 * Get time since epoch, with up to microsecond resolution. 160 * 161 * @return time since epoch, with up to microsecond resolution. 162 */ 163 public Instant instant() { 164 long usec = micros(); 165 long secs = usec / 1000000L; 166 long nanos = (usec % 1000000L) * 1000L; 167 return Instant.ofEpochSecond(secs, nanos); 168 } 169 170 /** 171 * Get time since epoch, with up to microsecond resolution. 172 * 173 * @return time since epoch, with up to microsecond resolution. 174 */ 175 public Timestamp timestamp() { 176 return Timestamp.from(instant()); 177 } 178 179 /** 180 * Get time since epoch, with up to millisecond resolution. 181 * 182 * @return time since epoch, with up to millisecond resolution. 183 */ 184 public Date date() { 185 return new Date(millis()); 186 } 187 188 /** 189 * {@inheritDoc} 190 * <p> 191 * Release resources allocated by this timestamp. 192 */ 193 @Override 194 public void close() { 195 // Do nothing by default. 196 } 197 198 /** {@inheritDoc} */ 199 @Override 200 public String toString() { 201 return instant().toString(); 202 } 203 }