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 package org.apache.hadoop.hdfs.protocol;
019
020 import java.util.Date;
021
022 import org.apache.commons.lang.builder.EqualsBuilder;
023 import org.apache.commons.lang.builder.HashCodeBuilder;
024 import org.apache.hadoop.classification.InterfaceAudience;
025 import org.apache.hadoop.classification.InterfaceStability;
026 import org.apache.hadoop.fs.Path;
027 import org.apache.hadoop.hdfs.DFSUtil;
028
029 import com.google.common.base.Preconditions;
030
031 /**
032 * Describes a path-based cache directive.
033 */
034 @InterfaceStability.Evolving
035 @InterfaceAudience.Public
036 public class CacheDirectiveInfo {
037 /**
038 * A builder for creating new CacheDirectiveInfo instances.
039 */
040 public static class Builder {
041 private Long id;
042 private Path path;
043 private Short replication;
044 private String pool;
045 private Expiration expiration;
046
047 /**
048 * Builds a new CacheDirectiveInfo populated with the set properties.
049 *
050 * @return New CacheDirectiveInfo.
051 */
052 public CacheDirectiveInfo build() {
053 return new CacheDirectiveInfo(id, path, replication, pool, expiration);
054 }
055
056 /**
057 * Creates an empty builder.
058 */
059 public Builder() {
060 }
061
062 /**
063 * Creates a builder with all elements set to the same values as the
064 * given CacheDirectiveInfo.
065 */
066 public Builder(CacheDirectiveInfo directive) {
067 this.id = directive.getId();
068 this.path = directive.getPath();
069 this.replication = directive.getReplication();
070 this.pool = directive.getPool();
071 this.expiration = directive.getExpiration();
072 }
073
074 /**
075 * Sets the id used in this request.
076 *
077 * @param id The id used in this request.
078 * @return This builder, for call chaining.
079 */
080 public Builder setId(Long id) {
081 this.id = id;
082 return this;
083 }
084
085 /**
086 * Sets the path used in this request.
087 *
088 * @param path The path used in this request.
089 * @return This builder, for call chaining.
090 */
091 public Builder setPath(Path path) {
092 this.path = path;
093 return this;
094 }
095
096 /**
097 * Sets the replication used in this request.
098 *
099 * @param replication The replication used in this request.
100 * @return This builder, for call chaining.
101 */
102 public Builder setReplication(Short replication) {
103 this.replication = replication;
104 return this;
105 }
106
107 /**
108 * Sets the pool used in this request.
109 *
110 * @param pool The pool used in this request.
111 * @return This builder, for call chaining.
112 */
113 public Builder setPool(String pool) {
114 this.pool = pool;
115 return this;
116 }
117
118 /**
119 * Sets when the CacheDirective should expire. A
120 * {@link CacheDirectiveInfo.Expiration} can specify either an absolute or
121 * relative expiration time.
122 *
123 * @param expiration when this CacheDirective should expire
124 * @return This builder, for call chaining
125 */
126 public Builder setExpiration(Expiration expiration) {
127 this.expiration = expiration;
128 return this;
129 }
130 }
131
132 /**
133 * Denotes a relative or absolute expiration time for a CacheDirective. Use
134 * factory methods {@link CacheDirectiveInfo.Expiration#newAbsolute(Date)} and
135 * {@link CacheDirectiveInfo.Expiration#newRelative(long)} to create an
136 * Expiration.
137 * <p>
138 * In either case, the server-side clock is used to determine when a
139 * CacheDirective expires.
140 */
141 public static class Expiration {
142
143 /**
144 * The maximum value we accept for a relative expiry.
145 */
146 public static final long MAX_RELATIVE_EXPIRY_MS =
147 Long.MAX_VALUE / 4; // This helps prevent weird overflow bugs
148
149 /**
150 * An relative Expiration that never expires.
151 */
152 public static final Expiration NEVER = newRelative(MAX_RELATIVE_EXPIRY_MS);
153
154 /**
155 * Create a new relative Expiration.
156 * <p>
157 * Use {@link Expiration#NEVER} to indicate an Expiration that never
158 * expires.
159 *
160 * @param ms how long until the CacheDirective expires, in milliseconds
161 * @return A relative Expiration
162 */
163 public static Expiration newRelative(long ms) {
164 return new Expiration(ms, true);
165 }
166
167 /**
168 * Create a new absolute Expiration.
169 * <p>
170 * Use {@link Expiration#NEVER} to indicate an Expiration that never
171 * expires.
172 *
173 * @param date when the CacheDirective expires
174 * @return An absolute Expiration
175 */
176 public static Expiration newAbsolute(Date date) {
177 return new Expiration(date.getTime(), false);
178 }
179
180 /**
181 * Create a new absolute Expiration.
182 * <p>
183 * Use {@link Expiration#NEVER} to indicate an Expiration that never
184 * expires.
185 *
186 * @param ms when the CacheDirective expires, in milliseconds since the Unix
187 * epoch.
188 * @return An absolute Expiration
189 */
190 public static Expiration newAbsolute(long ms) {
191 return new Expiration(ms, false);
192 }
193
194 private final long ms;
195 private final boolean isRelative;
196
197 private Expiration(long ms, boolean isRelative) {
198 if (isRelative) {
199 Preconditions.checkArgument(ms <= MAX_RELATIVE_EXPIRY_MS,
200 "Expiration time is too far in the future!");
201 }
202 this.ms = ms;
203 this.isRelative = isRelative;
204 }
205
206 /**
207 * @return true if Expiration was specified as a relative duration, false if
208 * specified as an absolute time.
209 */
210 public boolean isRelative() {
211 return isRelative;
212 }
213
214 /**
215 * @return The raw underlying millisecond value, either a relative duration
216 * or an absolute time as milliseconds since the Unix epoch.
217 */
218 public long getMillis() {
219 return ms;
220 }
221
222 /**
223 * @return Expiration time as a {@link Date} object. This converts a
224 * relative Expiration into an absolute Date based on the local
225 * clock.
226 */
227 public Date getAbsoluteDate() {
228 return new Date(getAbsoluteMillis());
229 }
230
231 /**
232 * @return Expiration time in milliseconds from the Unix epoch. This
233 * converts a relative Expiration into an absolute time based on the
234 * local clock.
235 */
236 public long getAbsoluteMillis() {
237 if (!isRelative) {
238 return ms;
239 } else {
240 return new Date().getTime() + ms;
241 }
242 }
243
244 @Override
245 public String toString() {
246 if (isRelative) {
247 return DFSUtil.durationToString(ms);
248 }
249 return DFSUtil.dateToIso8601String(new Date(ms));
250 }
251 }
252
253 private final Long id;
254 private final Path path;
255 private final Short replication;
256 private final String pool;
257 private final Expiration expiration;
258
259 CacheDirectiveInfo(Long id, Path path, Short replication, String pool,
260 Expiration expiration) {
261 this.id = id;
262 this.path = path;
263 this.replication = replication;
264 this.pool = pool;
265 this.expiration = expiration;
266 }
267
268 /**
269 * @return The ID of this directive.
270 */
271 public Long getId() {
272 return id;
273 }
274
275 /**
276 * @return The path used in this request.
277 */
278 public Path getPath() {
279 return path;
280 }
281
282 /**
283 * @return The number of times the block should be cached.
284 */
285 public Short getReplication() {
286 return replication;
287 }
288
289 /**
290 * @return The pool used in this request.
291 */
292 public String getPool() {
293 return pool;
294 }
295
296 /**
297 * @return When this directive expires.
298 */
299 public Expiration getExpiration() {
300 return expiration;
301 }
302
303 @Override
304 public boolean equals(Object o) {
305 if (o == null) {
306 return false;
307 }
308 if (getClass() != o.getClass()) {
309 return false;
310 }
311 CacheDirectiveInfo other = (CacheDirectiveInfo)o;
312 return new EqualsBuilder().append(getId(), other.getId()).
313 append(getPath(), other.getPath()).
314 append(getReplication(), other.getReplication()).
315 append(getPool(), other.getPool()).
316 append(getExpiration(), other.getExpiration()).
317 isEquals();
318 }
319
320 @Override
321 public int hashCode() {
322 return new HashCodeBuilder().append(id).
323 append(path).
324 append(replication).
325 append(pool).
326 append(expiration).
327 hashCode();
328 }
329
330 @Override
331 public String toString() {
332 StringBuilder builder = new StringBuilder();
333 builder.append("{");
334 String prefix = "";
335 if (id != null) {
336 builder.append(prefix).append("id: ").append(id);
337 prefix = ", ";
338 }
339 if (path != null) {
340 builder.append(prefix).append("path: ").append(path);
341 prefix = ", ";
342 }
343 if (replication != null) {
344 builder.append(prefix).append("replication: ").append(replication);
345 prefix = ", ";
346 }
347 if (pool != null) {
348 builder.append(prefix).append("pool: ").append(pool);
349 prefix = ", ";
350 }
351 if (expiration != null) {
352 builder.append(prefix).append("expiration: ").append(expiration);
353 prefix = ", ";
354 }
355 builder.append("}");
356 return builder.toString();
357 }
358 };