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.hdfs.protocol; 019 020import java.util.Date; 021 022import org.apache.commons.lang.builder.EqualsBuilder; 023import org.apache.commons.lang.builder.HashCodeBuilder; 024import org.apache.hadoop.classification.InterfaceAudience; 025import org.apache.hadoop.classification.InterfaceStability; 026import org.apache.hadoop.fs.Path; 027 028import com.google.common.base.Preconditions; 029import org.apache.hadoop.hdfs.DFSUtilClient; 030 031/** 032 * Describes a path-based cache directive. 033 */ 034@InterfaceStability.Evolving 035@InterfaceAudience.Public 036public 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 DFSUtilClient.durationToString(ms); 248 } 249 return DFSUtilClient.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};