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.hdfs.protocol;
020
021import java.io.IOException;
022
023import javax.annotation.Nullable;
024
025import org.apache.commons.lang.builder.EqualsBuilder;
026import org.apache.commons.lang.builder.HashCodeBuilder;
027import org.apache.hadoop.classification.InterfaceAudience;
028import org.apache.hadoop.classification.InterfaceStability;
029import org.apache.hadoop.fs.InvalidRequestException;
030import org.apache.hadoop.fs.permission.FsPermission;
031import org.apache.hadoop.hdfs.protocol.CacheDirectiveInfo.Expiration;
032
033/**
034 * CachePoolInfo describes a cache pool.
035 *
036 * This class is used in RPCs to create and modify cache pools.
037 * It is serializable and can be stored in the edit log.
038 */
039@InterfaceAudience.Public
040@InterfaceStability.Evolving
041public class CachePoolInfo {
042
043  /**
044   * Indicates that the pool does not have a maximum relative expiry.
045   */
046  public static final long RELATIVE_EXPIRY_NEVER =
047      Expiration.MAX_RELATIVE_EXPIRY_MS;
048  /**
049   * Default max relative expiry for cache pools.
050   */
051  public static final long DEFAULT_MAX_RELATIVE_EXPIRY =
052      RELATIVE_EXPIRY_NEVER;
053
054  public static final long LIMIT_UNLIMITED = Long.MAX_VALUE;
055  public static final long DEFAULT_LIMIT = LIMIT_UNLIMITED;
056
057  final String poolName;
058
059  @Nullable
060  String ownerName;
061
062  @Nullable
063  String groupName;
064
065  @Nullable
066  FsPermission mode;
067
068  @Nullable
069  Long limit;
070
071  @Nullable
072  Long maxRelativeExpiryMs;
073
074  public CachePoolInfo(String poolName) {
075    this.poolName = poolName;
076  }
077
078  /**
079   * @return Name of the pool.
080   */
081  public String getPoolName() {
082    return poolName;
083  }
084
085  /**
086   * @return The owner of the pool. Along with the group and mode, determines
087   *         who has access to view and modify the pool.
088   */
089  public String getOwnerName() {
090    return ownerName;
091  }
092
093  public CachePoolInfo setOwnerName(String ownerName) {
094    this.ownerName = ownerName;
095    return this;
096  }
097
098  /**
099   * @return The group of the pool. Along with the owner and mode, determines
100   *         who has access to view and modify the pool.
101   */
102  public String getGroupName() {
103    return groupName;
104  }
105
106  public CachePoolInfo setGroupName(String groupName) {
107    this.groupName = groupName;
108    return this;
109  }
110
111  /**
112   * @return Unix-style permissions of the pool. Along with the owner and group,
113   *         determines who has access to view and modify the pool.
114   */
115  public FsPermission getMode() {
116    return mode;
117  }
118
119  public CachePoolInfo setMode(FsPermission mode) {
120    this.mode = mode;
121    return this;
122  }
123
124  /**
125   * @return The maximum aggregate number of bytes that can be cached by
126   *         directives in this pool.
127   */
128  public Long getLimit() {
129    return limit;
130  }
131
132  public CachePoolInfo setLimit(Long bytes) {
133    this.limit = bytes;
134    return this;
135  }
136
137  /**
138   * @return The maximum relative expiration of directives of this pool in
139   *         milliseconds
140   */
141  public Long getMaxRelativeExpiryMs() {
142    return maxRelativeExpiryMs;
143  }
144
145  /**
146   * Set the maximum relative expiration of directives of this pool in
147   * milliseconds.
148   * 
149   * @param ms in milliseconds
150   * @return This builder, for call chaining.
151   */
152  public CachePoolInfo setMaxRelativeExpiryMs(Long ms) {
153    this.maxRelativeExpiryMs = ms;
154    return this;
155  }
156
157  public String toString() {
158    return new StringBuilder().append("{").
159      append("poolName:").append(poolName).
160      append(", ownerName:").append(ownerName).
161      append(", groupName:").append(groupName).
162      append(", mode:").append((mode == null) ? "null" :
163          String.format("0%03o", mode.toShort())).
164      append(", limit:").append(limit).
165      append(", maxRelativeExpiryMs:").append(maxRelativeExpiryMs).
166      append("}").toString();
167  }
168  
169  @Override
170  public boolean equals(Object o) {
171    if (o == null) { return false; }
172    if (o == this) { return true; }
173    if (o.getClass() != getClass()) {
174      return false;
175    }
176    CachePoolInfo other = (CachePoolInfo)o;
177    return new EqualsBuilder().
178        append(poolName, other.poolName).
179        append(ownerName, other.ownerName).
180        append(groupName, other.groupName).
181        append(mode, other.mode).
182        append(limit, other.limit).
183        append(maxRelativeExpiryMs, other.maxRelativeExpiryMs).
184        isEquals();
185  }
186
187  @Override
188  public int hashCode() {
189    return new HashCodeBuilder().
190        append(poolName).
191        append(ownerName).
192        append(groupName).
193        append(mode).
194        append(limit).
195        append(maxRelativeExpiryMs).
196        hashCode();
197  }
198
199  public static void validate(CachePoolInfo info) throws IOException {
200    if (info == null) {
201      throw new InvalidRequestException("CachePoolInfo is null");
202    }
203    if ((info.getLimit() != null) && (info.getLimit() < 0)) {
204      throw new InvalidRequestException("Limit is negative.");
205    }
206    if (info.getMaxRelativeExpiryMs() != null) {
207      long maxRelativeExpiryMs = info.getMaxRelativeExpiryMs();
208      if (maxRelativeExpiryMs < 0l) {
209        throw new InvalidRequestException("Max relative expiry is negative.");
210      }
211      if (maxRelativeExpiryMs > Expiration.MAX_RELATIVE_EXPIRY_MS) {
212        throw new InvalidRequestException("Max relative expiry is too big.");
213      }
214    }
215    validateName(info.poolName);
216  }
217
218  public static void validateName(String poolName) throws IOException {
219    if (poolName == null || poolName.isEmpty()) {
220      // Empty pool names are not allowed because they would be highly
221      // confusing.  They would also break the ability to list all pools
222      // by starting with prevKey = ""
223      throw new IOException("invalid empty cache pool name");
224    }
225  }
226}