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    
019    package org.apache.hadoop.hdfs.protocol;
020    
021    import java.io.IOException;
022    
023    import javax.annotation.Nullable;
024    
025    import org.apache.commons.lang.builder.EqualsBuilder;
026    import org.apache.commons.lang.builder.HashCodeBuilder;
027    import org.apache.commons.logging.Log;
028    import org.apache.commons.logging.LogFactory;
029    import org.apache.hadoop.classification.InterfaceAudience;
030    import org.apache.hadoop.classification.InterfaceStability;
031    import org.apache.hadoop.fs.InvalidRequestException;
032    import org.apache.hadoop.fs.permission.FsPermission;
033    import 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
043    public 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    }