001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019package org.apache.hadoop.hbase.io;
020
021import org.apache.hadoop.hbase.util.Bytes;
022import org.apache.yetus.audience.InterfaceAudience;
023
024/**
025 * Represents an interval of version timestamps. Presumes timestamps between
026 * {@link #INITIAL_MIN_TIMESTAMP} and {@link #INITIAL_MAX_TIMESTAMP} only. Gets freaked out if
027 * passed a timestamp that is < {@link #INITIAL_MIN_TIMESTAMP},
028 * <p>
029 * Evaluated according to minStamp &lt;= timestamp &lt; maxStamp or [minStamp,maxStamp) in interval
030 * notation.
031 * <p>
032 * Can be returned and read by clients. Should not be directly created by clients. Thus, all
033 * constructors are purposely @InterfaceAudience.Private.
034 * <p>
035 * Immutable. Thread-safe.
036 */
037@InterfaceAudience.Public
038public class TimeRange {
039  public static final long INITIAL_MIN_TIMESTAMP = 0L;
040  public static final long INITIAL_MAX_TIMESTAMP = Long.MAX_VALUE;
041  private static final TimeRange ALL_TIME = new TimeRange(INITIAL_MIN_TIMESTAMP,
042    INITIAL_MAX_TIMESTAMP);
043
044  public static TimeRange allTime() {
045    return ALL_TIME;
046  }
047
048  public static TimeRange at(long ts) {
049    if (ts < 0 || ts == Long.MAX_VALUE) {
050      throw new IllegalArgumentException("invalid ts:" + ts);
051    }
052    return new TimeRange(ts, ts + 1);
053  }
054
055  /**
056   * Represents the time interval [minStamp, Long.MAX_VALUE)
057   * @param minStamp the minimum timestamp value, inclusive
058   */
059  public static TimeRange from(long minStamp) {
060    check(minStamp, INITIAL_MAX_TIMESTAMP);
061    return new TimeRange(minStamp, INITIAL_MAX_TIMESTAMP);
062  }
063
064  /**
065   * Represents the time interval [0, maxStamp)
066   * @param maxStamp the minimum timestamp value, exclusive
067   */
068  public static TimeRange until(long maxStamp) {
069    check(INITIAL_MIN_TIMESTAMP, maxStamp);
070    return new TimeRange(INITIAL_MIN_TIMESTAMP, maxStamp);
071  }
072
073  /**
074   * Represents the time interval [minStamp, maxStamp)
075   * @param minStamp the minimum timestamp, inclusive
076   * @param maxStamp the maximum timestamp, exclusive
077   */
078  public static TimeRange between(long minStamp, long maxStamp) {
079    check(minStamp, maxStamp);
080    return new TimeRange(minStamp, maxStamp);
081  }
082
083  private final long minStamp;
084  private final long maxStamp;
085  private final boolean allTime;
086
087  /**
088   * Default constructor.
089   * Represents interval [0, Long.MAX_VALUE) (allTime)
090   * @deprecated This is made @InterfaceAudience.Private in the 2.0 line and above and may be
091   * changed to private or removed in 3.0.
092   */
093  @Deprecated
094  @InterfaceAudience.Private
095  public TimeRange() {
096    this(INITIAL_MIN_TIMESTAMP, INITIAL_MAX_TIMESTAMP);
097  }
098
099  /**
100   * Represents interval [minStamp, Long.MAX_VALUE)
101   * @param minStamp the minimum timestamp value, inclusive
102   * @deprecated This is made @InterfaceAudience.Private in the 2.0 line and above and may be
103   * changed to private or removed in 3.0.
104   */
105  @Deprecated
106  @InterfaceAudience.Private
107  public TimeRange(long minStamp) {
108    this(minStamp, INITIAL_MAX_TIMESTAMP);
109  }
110
111  /**
112   * Represents interval [minStamp, Long.MAX_VALUE)
113   * @param minStamp the minimum timestamp value, inclusive
114   * @deprecated This is made @InterfaceAudience.Private in the 2.0 line and above and may be
115   * changed to private or removed in 3.0.
116   */
117  @Deprecated
118  @InterfaceAudience.Private
119  public TimeRange(byte [] minStamp) {
120    this(Bytes.toLong(minStamp));
121  }
122
123  /**
124   * Represents interval [minStamp, maxStamp)
125   * @param minStamp the minimum timestamp, inclusive
126   * @param maxStamp the maximum timestamp, exclusive
127   * @deprecated This is made @InterfaceAudience.Private in the 2.0 line and above and may be
128   * changed to private or removed in 3.0.
129   */
130  @Deprecated
131  @InterfaceAudience.Private
132  public TimeRange(byte [] minStamp, byte [] maxStamp) {
133    this(Bytes.toLong(minStamp), Bytes.toLong(maxStamp));
134  }
135
136  /**
137   * Represents interval [minStamp, maxStamp)
138   * @param minStamp the minimum timestamp, inclusive
139   * @param maxStamp the maximum timestamp, exclusive
140   * @throws IllegalArgumentException if either <0,
141   * @deprecated This is made @InterfaceAudience.Private in the 2.0 line and above and may be
142   * changed to private or removed in 3.0.
143   */
144  @Deprecated
145  @InterfaceAudience.Private
146  public TimeRange(long minStamp, long maxStamp) {
147    check(minStamp, maxStamp);
148    this.minStamp = minStamp;
149    this.maxStamp = maxStamp;
150    this.allTime = isAllTime(minStamp, maxStamp);
151  }
152
153  private static boolean isAllTime(long minStamp, long maxStamp) {
154    return minStamp == INITIAL_MIN_TIMESTAMP && maxStamp == INITIAL_MAX_TIMESTAMP;
155  }
156
157  private static void check(long minStamp, long maxStamp) {
158    if (minStamp < 0 || maxStamp < 0) {
159      throw new IllegalArgumentException("Timestamp cannot be negative. minStamp:" + minStamp
160        + ", maxStamp:" + maxStamp);
161    }
162    if (maxStamp < minStamp) {
163      throw new IllegalArgumentException("maxStamp is smaller than minStamp");
164    }
165  }
166
167  /**
168   * @return the smallest timestamp that should be considered
169   */
170  public long getMin() {
171    return minStamp;
172  }
173
174  /**
175   * @return the biggest timestamp that should be considered
176   */
177  public long getMax() {
178    return maxStamp;
179  }
180
181  /**
182   * Check if it is for all time
183   * @return true if it is for all time
184   */
185  public boolean isAllTime() {
186    return allTime;
187  }
188
189  /**
190   * Check if the specified timestamp is within this TimeRange.
191   * <p>
192   * Returns true if within interval [minStamp, maxStamp), false if not.
193   * @param bytes timestamp to check
194   * @param offset offset into the bytes
195   * @return true if within TimeRange, false if not
196   * @deprecated This is made @InterfaceAudience.Private in the 2.0 line and above and may be
197   *   changed to private or removed in 3.0. Use {@link #withinTimeRange(long)} instead
198   */
199  @Deprecated
200  public boolean withinTimeRange(byte [] bytes, int offset) {
201    if (allTime) {
202      return true;
203    }
204    return withinTimeRange(Bytes.toLong(bytes, offset));
205  }
206
207  /**
208   * Check if the specified timestamp is within this TimeRange.
209   * <p>
210   * Returns true if within interval [minStamp, maxStamp), false
211   * if not.
212   * @param timestamp timestamp to check
213   * @return true if within TimeRange, false if not
214   */
215  public boolean withinTimeRange(long timestamp) {
216    assert timestamp >= 0;
217    if (this.allTime) {
218      return true;
219    }
220    // check if >= minStamp
221    return (minStamp <= timestamp && timestamp < maxStamp);
222  }
223
224  /**
225   * Check if the range has any overlap with TimeRange
226   * @param tr TimeRange
227   * @return True if there is overlap, false otherwise
228   */
229  // This method came from TimeRangeTracker. We used to go there for this function but better
230  // to come here to the immutable, unsynchronized datastructure at read time.
231  public boolean includesTimeRange(final TimeRange tr) {
232    if (this.allTime) {
233      return true;
234    }
235    assert tr.getMin() >= 0;
236    return getMin() < tr.getMax() && getMax() >= tr.getMin();
237  }
238
239  /**
240   * Check if the specified timestamp is within or after this TimeRange.
241   * <p>
242   * Returns true if greater than minStamp, false if not.
243   * @param timestamp timestamp to check
244   * @return true if within or after TimeRange, false if not
245   */
246  public boolean withinOrAfterTimeRange(long timestamp) {
247    assert timestamp >= 0;
248    if (allTime) {
249      return true;
250    }
251    // check if >= minStamp
252    return timestamp >= minStamp;
253  }
254
255  /**
256   * Compare the timestamp to timerange.
257   * @return -1 if timestamp is less than timerange,
258   * 0 if timestamp is within timerange,
259   * 1 if timestamp is greater than timerange
260   */
261  public int compare(long timestamp) {
262    assert timestamp >= 0;
263    if (this.allTime) {
264      return 0;
265    }
266    if (timestamp < minStamp) {
267      return -1;
268    }
269    return timestamp >= maxStamp? 1: 0;
270  }
271
272  @Override
273  public String toString() {
274    StringBuilder sb = new StringBuilder();
275    sb.append("maxStamp=");
276    sb.append(this.maxStamp);
277    sb.append(", minStamp=");
278    sb.append(this.minStamp);
279    return sb.toString();
280  }
281}