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