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
030 * or [minStamp,maxStamp) in interval notation.
031 * <p>
032 * Can be returned and read by clients.  Should not be directly created by clients.
033 * Thus, all constructors are purposely @InterfaceAudience.Private.
034 *<p>Immutable. Thread-safe.
035 */
036@InterfaceAudience.Public
037public class TimeRange {
038  public static final long INITIAL_MIN_TIMESTAMP = 0L;
039  public static final long INITIAL_MAX_TIMESTAMP = Long.MAX_VALUE;
040  private static final TimeRange ALL_TIME = new TimeRange(INITIAL_MIN_TIMESTAMP,
041    INITIAL_MAX_TIMESTAMP);
042
043  public static TimeRange allTime() {
044    return ALL_TIME;
045  }
046
047  public static TimeRange at(long ts) {
048    if (ts < 0 || ts == Long.MAX_VALUE) {
049      throw new IllegalArgumentException("invalid ts:" + ts);
050    }
051    return new TimeRange(ts, ts + 1);
052  }
053
054  private final long minStamp;
055  private final long maxStamp;
056  private final boolean allTime;
057
058  /**
059   * Default constructor.
060   * Represents interval [0, Long.MAX_VALUE) (allTime)
061   * @deprecated This is made @InterfaceAudience.Private in the 2.0 line and above and may be
062   * changed to private or removed in 3.0.
063   */
064  @Deprecated
065  @InterfaceAudience.Private
066  public TimeRange() {
067    this(INITIAL_MIN_TIMESTAMP, INITIAL_MAX_TIMESTAMP);
068  }
069
070  /**
071   * Represents interval [minStamp, Long.MAX_VALUE)
072   * @param minStamp the minimum timestamp value, inclusive
073   * @deprecated This is made @InterfaceAudience.Private in the 2.0 line and above and may be
074   * changed to private or removed in 3.0.
075   */
076  @Deprecated
077  @InterfaceAudience.Private
078  public TimeRange(long minStamp) {
079    this(minStamp, INITIAL_MAX_TIMESTAMP);
080  }
081
082  /**
083   * Represents interval [minStamp, Long.MAX_VALUE)
084   * @param minStamp the minimum timestamp value, inclusive
085   * @deprecated This is made @InterfaceAudience.Private in the 2.0 line and above and may be
086   * changed to private or removed in 3.0.
087   */
088  @Deprecated
089  @InterfaceAudience.Private
090  public TimeRange(byte [] minStamp) {
091    this(Bytes.toLong(minStamp));
092  }
093
094  /**
095   * Represents interval [minStamp, maxStamp)
096   * @param minStamp the minimum timestamp, inclusive
097   * @param maxStamp the maximum timestamp, exclusive
098   * @deprecated This is made @InterfaceAudience.Private in the 2.0 line and above and may be
099   * changed to private or removed in 3.0.
100   */
101  @Deprecated
102  @InterfaceAudience.Private
103  public TimeRange(byte [] minStamp, byte [] maxStamp) {
104    this(Bytes.toLong(minStamp), Bytes.toLong(maxStamp));
105  }
106
107  /**
108   * Represents interval [minStamp, maxStamp)
109   * @param minStamp the minimum timestamp, inclusive
110   * @param maxStamp the maximum timestamp, exclusive
111   * @throws IllegalArgumentException if either <0,
112   * @deprecated This is made @InterfaceAudience.Private in the 2.0 line and above and may be
113   * changed to private or removed in 3.0.
114   */
115  @Deprecated
116  @InterfaceAudience.Private
117  public TimeRange(long minStamp, long maxStamp) {
118    check(minStamp, maxStamp);
119    this.minStamp = minStamp;
120    this.maxStamp = maxStamp;
121    this.allTime = isAllTime(minStamp, maxStamp);
122  }
123
124  private static boolean isAllTime(long minStamp, long maxStamp) {
125    return minStamp == INITIAL_MIN_TIMESTAMP && maxStamp == INITIAL_MAX_TIMESTAMP;
126  }
127
128  private static void check(long minStamp, long maxStamp) {
129    if (minStamp < 0 || maxStamp < 0) {
130      throw new IllegalArgumentException("Timestamp cannot be negative. minStamp:" + minStamp
131        + ", maxStamp:" + maxStamp);
132    }
133    if (maxStamp < minStamp) {
134      throw new IllegalArgumentException("maxStamp is smaller than minStamp");
135    }
136  }
137
138  /**
139   * @return the smallest timestamp that should be considered
140   */
141  public long getMin() {
142    return minStamp;
143  }
144
145  /**
146   * @return the biggest timestamp that should be considered
147   */
148  public long getMax() {
149    return maxStamp;
150  }
151
152  /**
153   * Check if it is for all time
154   * @return true if it is for all time
155   */
156  public boolean isAllTime() {
157    return allTime;
158  }
159
160  /**
161   * Check if the specified timestamp is within this TimeRange.
162   * <p>
163   * Returns true if within interval [minStamp, maxStamp), false if not.
164   * @param bytes timestamp to check
165   * @param offset offset into the bytes
166   * @return true if within TimeRange, false if not
167   * @deprecated This is made @InterfaceAudience.Private in the 2.0 line and above and may be
168   *   changed to private or removed in 3.0. Use {@link #withinTimeRange(long)} instead
169   */
170  @Deprecated
171  public boolean withinTimeRange(byte [] bytes, int offset) {
172    if (allTime) {
173      return true;
174    }
175    return withinTimeRange(Bytes.toLong(bytes, offset));
176  }
177
178  /**
179   * Check if the specified timestamp is within this TimeRange.
180   * <p>
181   * Returns true if within interval [minStamp, maxStamp), false
182   * if not.
183   * @param timestamp timestamp to check
184   * @return true if within TimeRange, false if not
185   */
186  public boolean withinTimeRange(long timestamp) {
187    assert timestamp >= 0;
188    if (this.allTime) {
189      return true;
190    }
191    // check if >= minStamp
192    return (minStamp <= timestamp && timestamp < maxStamp);
193  }
194
195  /**
196   * Check if the range has any overlap with TimeRange
197   * @param tr TimeRange
198   * @return True if there is overlap, false otherwise
199   */
200  // This method came from TimeRangeTracker. We used to go there for this function but better
201  // to come here to the immutable, unsynchronized datastructure at read time.
202  public boolean includesTimeRange(final TimeRange tr) {
203    if (this.allTime) {
204      return true;
205    }
206    assert tr.getMin() >= 0;
207    return getMin() < tr.getMax() && getMax() >= tr.getMin();
208  }
209
210  /**
211   * Check if the specified timestamp is within or after this TimeRange.
212   * <p>
213   * Returns true if greater than minStamp, false if not.
214   * @param timestamp timestamp to check
215   * @return true if within or after TimeRange, false if not
216   */
217  public boolean withinOrAfterTimeRange(long timestamp) {
218    assert timestamp >= 0;
219    if (allTime) {
220      return true;
221    }
222    // check if >= minStamp
223    return timestamp >= minStamp;
224  }
225
226  /**
227   * Compare the timestamp to timerange.
228   * @return -1 if timestamp is less than timerange,
229   * 0 if timestamp is within timerange,
230   * 1 if timestamp is greater than timerange
231   */
232  public int compare(long timestamp) {
233    assert timestamp >= 0;
234    if (this.allTime) {
235      return 0;
236    }
237    if (timestamp < minStamp) {
238      return -1;
239    }
240    return timestamp >= maxStamp? 1: 0;
241  }
242
243  @Override
244  public String toString() {
245    StringBuilder sb = new StringBuilder();
246    sb.append("maxStamp=");
247    sb.append(this.maxStamp);
248    sb.append(", minStamp=");
249    sb.append(this.minStamp);
250    return sb.toString();
251  }
252}