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 */ 018package org.apache.hadoop.hbase.io; 019 020import org.apache.yetus.audience.InterfaceAudience; 021 022/** 023 * Represents an interval of version timestamps. Presumes timestamps between 024 * {@link #INITIAL_MIN_TIMESTAMP} and {@link #INITIAL_MAX_TIMESTAMP} only. Gets freaked out if 025 * passed a timestamp that is < {@link #INITIAL_MIN_TIMESTAMP}, 026 * <p/> 027 * Evaluated according to minStamp <= timestamp < maxStamp or [minStamp,maxStamp) in interval 028 * notation. 029 * <p/> 030 * Can be returned and read by clients. Should not be directly created by clients. Thus, all 031 * constructors are purposely @InterfaceAudience.Private. 032 * <p/> 033 * Immutable. Thread-safe. 034 */ 035@InterfaceAudience.Public 036public final class TimeRange { 037 public static final long INITIAL_MIN_TIMESTAMP = 0L; 038 public static final long INITIAL_MAX_TIMESTAMP = Long.MAX_VALUE; 039 private static final TimeRange ALL_TIME = 040 new TimeRange(INITIAL_MIN_TIMESTAMP, INITIAL_MAX_TIMESTAMP); 041 042 public static TimeRange allTime() { 043 return ALL_TIME; 044 } 045 046 public static TimeRange at(long ts) { 047 if (ts < 0 || ts == Long.MAX_VALUE) { 048 throw new IllegalArgumentException("invalid ts:" + ts); 049 } 050 return new TimeRange(ts, ts + 1); 051 } 052 053 /** 054 * Represents the time interval [minStamp, Long.MAX_VALUE) 055 * @param minStamp the minimum timestamp value, inclusive 056 */ 057 public static TimeRange from(long minStamp) { 058 check(minStamp, INITIAL_MAX_TIMESTAMP); 059 return new TimeRange(minStamp, INITIAL_MAX_TIMESTAMP); 060 } 061 062 /** 063 * Represents the time interval [0, maxStamp) 064 * @param maxStamp the minimum timestamp value, exclusive 065 */ 066 public static TimeRange until(long maxStamp) { 067 check(INITIAL_MIN_TIMESTAMP, maxStamp); 068 return new TimeRange(INITIAL_MIN_TIMESTAMP, maxStamp); 069 } 070 071 /** 072 * Represents the time interval [minStamp, maxStamp) 073 * @param minStamp the minimum timestamp, inclusive 074 * @param maxStamp the maximum timestamp, exclusive 075 */ 076 public static TimeRange between(long minStamp, long maxStamp) { 077 check(minStamp, maxStamp); 078 return new TimeRange(minStamp, maxStamp); 079 } 080 081 private final long minStamp; 082 private final long maxStamp; 083 private final boolean allTime; 084 085 /** 086 * Represents interval [minStamp, maxStamp) 087 * @param minStamp the minimum timestamp, inclusive 088 * @param maxStamp the maximum timestamp, exclusive 089 * @throws IllegalArgumentException if either <0, 090 */ 091 private TimeRange(long minStamp, long maxStamp) { 092 this.minStamp = minStamp; 093 this.maxStamp = maxStamp; 094 this.allTime = isAllTime(minStamp, maxStamp); 095 } 096 097 private static boolean isAllTime(long minStamp, long maxStamp) { 098 return minStamp == INITIAL_MIN_TIMESTAMP && maxStamp == INITIAL_MAX_TIMESTAMP; 099 } 100 101 private static void check(long minStamp, long maxStamp) { 102 if (minStamp < 0 || maxStamp < 0) { 103 throw new IllegalArgumentException( 104 "Timestamp cannot be negative. minStamp:" + minStamp + ", maxStamp:" + maxStamp); 105 } 106 if (maxStamp < minStamp) { 107 throw new IllegalArgumentException("maxStamp is smaller than minStamp"); 108 } 109 } 110 111 /** Returns the smallest timestamp that should be considered */ 112 public long getMin() { 113 return minStamp; 114 } 115 116 /** Returns the biggest timestamp that should be considered */ 117 public long getMax() { 118 return maxStamp; 119 } 120 121 /** 122 * Check if it is for all time 123 * @return true if it is for all time 124 */ 125 public boolean isAllTime() { 126 return allTime; 127 } 128 129 /** 130 * Check if the specified timestamp is within this TimeRange. 131 * <p/> 132 * Returns true if within interval [minStamp, maxStamp), false if not. 133 * @param timestamp timestamp to check 134 * @return true if within TimeRange, false if not 135 */ 136 public boolean withinTimeRange(long timestamp) { 137 assert timestamp >= 0; 138 if (this.allTime) { 139 return true; 140 } 141 // check if >= minStamp 142 return (minStamp <= timestamp && timestamp < maxStamp); 143 } 144 145 /** 146 * Check if the range has any overlap with TimeRange 147 * @param tr TimeRange 148 * @return True if there is overlap, false otherwise 149 */ 150 // This method came from TimeRangeTracker. We used to go there for this function but better 151 // to come here to the immutable, unsynchronized datastructure at read time. 152 public boolean includesTimeRange(final TimeRange tr) { 153 if (this.allTime) { 154 return true; 155 } 156 assert tr.getMin() >= 0; 157 return getMin() < tr.getMax() && getMax() >= tr.getMin(); 158 } 159 160 /** 161 * Check if the specified timestamp is within or after this TimeRange. 162 * <p> 163 * Returns true if greater than minStamp, false if not. 164 * @param timestamp timestamp to check 165 * @return true if within or after TimeRange, false if not 166 */ 167 public boolean withinOrAfterTimeRange(long timestamp) { 168 assert timestamp >= 0; 169 if (allTime) { 170 return true; 171 } 172 // check if >= minStamp 173 return timestamp >= minStamp; 174 } 175 176 /** 177 * Compare the timestamp to timerange. 178 * @return -1 if timestamp is less than timerange, 0 if timestamp is within timerange, 1 if 179 * timestamp is greater than timerange 180 */ 181 public int compare(long timestamp) { 182 assert timestamp >= 0; 183 if (this.allTime) { 184 return 0; 185 } 186 if (timestamp < minStamp) { 187 return -1; 188 } 189 return timestamp >= maxStamp ? 1 : 0; 190 } 191 192 @Override 193 public String toString() { 194 StringBuilder sb = new StringBuilder(); 195 sb.append("maxStamp="); 196 sb.append(this.maxStamp); 197 sb.append(", minStamp="); 198 sb.append(this.minStamp); 199 return sb.toString(); 200 } 201}