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  public static final short DEFAULT_REPLICATION_NUM = 1;
058
059  final String poolName;
060
061  @Nullable
062  String ownerName;
063
064  @Nullable
065  String groupName;
066
067  @Nullable
068  FsPermission mode;
069
070  @Nullable
071  Long limit;
072
073  @Nullable
074  private Short defaultReplication;
075
076  @Nullable
077  Long maxRelativeExpiryMs;
078
079  public CachePoolInfo(String poolName) {
080    this.poolName = poolName;
081  }
082
083  /**
084   * @return Name of the pool.
085   */
086  public String getPoolName() {
087    return poolName;
088  }
089
090  /**
091   * @return The owner of the pool. Along with the group and mode, determines
092   *         who has access to view and modify the pool.
093   */
094  public String getOwnerName() {
095    return ownerName;
096  }
097
098  public CachePoolInfo setOwnerName(String ownerName) {
099    this.ownerName = ownerName;
100    return this;
101  }
102
103  /**
104   * @return The group of the pool. Along with the owner and mode, determines
105   *         who has access to view and modify the pool.
106   */
107  public String getGroupName() {
108    return groupName;
109  }
110
111  public CachePoolInfo setGroupName(String groupName) {
112    this.groupName = groupName;
113    return this;
114  }
115
116  /**
117   * @return Unix-style permissions of the pool. Along with the owner and group,
118   *         determines who has access to view and modify the pool.
119   */
120  public FsPermission getMode() {
121    return mode;
122  }
123
124  public CachePoolInfo setMode(FsPermission mode) {
125    this.mode = mode;
126    return this;
127  }
128
129  /**
130   * @return The maximum aggregate number of bytes that can be cached by
131   *         directives in this pool.
132   */
133  public Long getLimit() {
134    return limit;
135  }
136
137  public CachePoolInfo setLimit(Long bytes) {
138    this.limit = bytes;
139    return this;
140  }
141
142  /**
143   * @return The default replication num for CacheDirective in this pool
144     */
145  public Short getDefaultReplication() {
146    return defaultReplication;
147  }
148
149  public CachePoolInfo setDefaultReplication(Short repl) {
150    this.defaultReplication = repl;
151    return this;
152  }
153
154  /**
155   * @return The maximum relative expiration of directives of this pool in
156   *         milliseconds
157   */
158  public Long getMaxRelativeExpiryMs() {
159    return maxRelativeExpiryMs;
160  }
161
162  /**
163   * Set the maximum relative expiration of directives of this pool in
164   * milliseconds.
165   *
166   * @param ms in milliseconds
167   * @return This builder, for call chaining.
168   */
169  public CachePoolInfo setMaxRelativeExpiryMs(Long ms) {
170    this.maxRelativeExpiryMs = ms;
171    return this;
172  }
173
174  public String toString() {
175    return "{" + "poolName:" + poolName
176        + ", ownerName:" + ownerName
177        + ", groupName:" + groupName
178        + ", mode:"
179        + ((mode == null) ? "null" : String.format("0%03o", mode.toShort()))
180        + ", limit:" + limit
181        + ", defaultReplication:" + defaultReplication
182        + ", maxRelativeExpiryMs:" + maxRelativeExpiryMs + "}";
183  }
184
185  @Override
186  public boolean equals(Object o) {
187    if (o == null) { return false; }
188    if (o == this) { return true; }
189    if (o.getClass() != getClass()) {
190      return false;
191    }
192    CachePoolInfo other = (CachePoolInfo)o;
193    return new EqualsBuilder().
194        append(poolName, other.poolName).
195        append(ownerName, other.ownerName).
196        append(groupName, other.groupName).
197        append(mode, other.mode).
198        append(limit, other.limit).
199        append(defaultReplication, other.defaultReplication).
200        append(maxRelativeExpiryMs, other.maxRelativeExpiryMs).
201        isEquals();
202  }
203
204  @Override
205  public int hashCode() {
206    return new HashCodeBuilder().
207        append(poolName).
208        append(ownerName).
209        append(groupName).
210        append(mode).
211        append(limit).
212        append(defaultReplication).
213        append(maxRelativeExpiryMs).
214        hashCode();
215  }
216
217  public static void validate(CachePoolInfo info) throws IOException {
218    if (info == null) {
219      throw new InvalidRequestException("CachePoolInfo is null");
220    }
221    if ((info.getLimit() != null) && (info.getLimit() < 0)) {
222      throw new InvalidRequestException("Limit is negative.");
223    }
224    if ((info.getDefaultReplication() != null)
225            && (info.getDefaultReplication() < 0)) {
226      throw new InvalidRequestException("Default Replication is negative");
227    }
228
229    if (info.getMaxRelativeExpiryMs() != null) {
230      long maxRelativeExpiryMs = info.getMaxRelativeExpiryMs();
231      if (maxRelativeExpiryMs < 0l) {
232        throw new InvalidRequestException("Max relative expiry is negative.");
233      }
234      if (maxRelativeExpiryMs > Expiration.MAX_RELATIVE_EXPIRY_MS) {
235        throw new InvalidRequestException("Max relative expiry is too big.");
236      }
237    }
238    validateName(info.poolName);
239  }
240
241  public static void validateName(String poolName) throws IOException {
242    if (poolName == null || poolName.isEmpty()) {
243      // Empty pool names are not allowed because they would be highly
244      // confusing.  They would also break the ability to list all pools
245      // by starting with prevKey = ""
246      throw new IOException("invalid empty cache pool name");
247    }
248  }
249}