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.server.namenode; 019 020import java.io.IOException; 021 022import javax.annotation.Nonnull; 023 024import org.apache.commons.logging.Log; 025import org.apache.commons.logging.LogFactory; 026import org.apache.hadoop.classification.InterfaceAudience; 027import org.apache.hadoop.fs.permission.FsAction; 028import org.apache.hadoop.fs.permission.FsPermission; 029import org.apache.hadoop.hdfs.protocol.CacheDirective; 030import org.apache.hadoop.hdfs.protocol.CachePoolEntry; 031import org.apache.hadoop.hdfs.protocol.CachePoolInfo; 032import org.apache.hadoop.hdfs.protocol.CachePoolStats; 033import org.apache.hadoop.security.AccessControlException; 034import org.apache.hadoop.security.UserGroupInformation; 035import org.apache.hadoop.util.IntrusiveCollection; 036 037import com.google.common.base.Preconditions; 038 039/** 040 * A CachePool describes a set of cache resources being managed by the NameNode. 041 * User caching requests are billed to the cache pool specified in the request. 042 * 043 * This is an internal class, only used on the NameNode. For identifying or 044 * describing a cache pool to clients, please use CachePoolInfo. 045 * 046 * CachePools must be accessed under the FSNamesystem lock. 047 */ 048@InterfaceAudience.Private 049public final class CachePool { 050 public static final Log LOG = LogFactory.getLog(CachePool.class); 051 052 @Nonnull 053 private final String poolName; 054 055 @Nonnull 056 private String ownerName; 057 058 @Nonnull 059 private String groupName; 060 061 /** 062 * Cache pool permissions. 063 * 064 * READ permission means that you can list the cache directives in this pool. 065 * WRITE permission means that you can add, remove, or modify cache directives 066 * in this pool. 067 * EXECUTE permission is unused. 068 */ 069 @Nonnull 070 private FsPermission mode; 071 072 /** 073 * Maximum number of bytes that can be cached in this pool. 074 */ 075 private long limit; 076 077 /** 078 * Maximum duration that a CacheDirective in this pool remains valid, 079 * in milliseconds. 080 */ 081 private long maxRelativeExpiryMs; 082 083 private long bytesNeeded; 084 private long bytesCached; 085 private long filesNeeded; 086 private long filesCached; 087 088 public final static class DirectiveList 089 extends IntrusiveCollection<CacheDirective> { 090 private CachePool cachePool; 091 092 private DirectiveList(CachePool cachePool) { 093 this.cachePool = cachePool; 094 } 095 096 public CachePool getCachePool() { 097 return cachePool; 098 } 099 } 100 101 @Nonnull 102 private final DirectiveList directiveList = new DirectiveList(this); 103 104 /** 105 * Create a new cache pool based on a CachePoolInfo object and the defaults. 106 * We will fill in information that was not supplied according to the 107 * defaults. 108 */ 109 static CachePool createFromInfoAndDefaults(CachePoolInfo info) 110 throws IOException { 111 UserGroupInformation ugi = null; 112 String ownerName = info.getOwnerName(); 113 if (ownerName == null) { 114 if (ugi == null) { 115 ugi = NameNode.getRemoteUser(); 116 } 117 ownerName = ugi.getShortUserName(); 118 } 119 String groupName = info.getGroupName(); 120 if (groupName == null) { 121 if (ugi == null) { 122 ugi = NameNode.getRemoteUser(); 123 } 124 groupName = ugi.getPrimaryGroupName(); 125 } 126 FsPermission mode = (info.getMode() == null) ? 127 FsPermission.getCachePoolDefault() : info.getMode(); 128 long limit = info.getLimit() == null ? 129 CachePoolInfo.DEFAULT_LIMIT : info.getLimit(); 130 long maxRelativeExpiry = info.getMaxRelativeExpiryMs() == null ? 131 CachePoolInfo.DEFAULT_MAX_RELATIVE_EXPIRY : 132 info.getMaxRelativeExpiryMs(); 133 return new CachePool(info.getPoolName(), 134 ownerName, groupName, mode, limit, maxRelativeExpiry); 135 } 136 137 /** 138 * Create a new cache pool based on a CachePoolInfo object. 139 * No fields in the CachePoolInfo can be blank. 140 */ 141 static CachePool createFromInfo(CachePoolInfo info) { 142 return new CachePool(info.getPoolName(), 143 info.getOwnerName(), info.getGroupName(), 144 info.getMode(), info.getLimit(), info.getMaxRelativeExpiryMs()); 145 } 146 147 CachePool(String poolName, String ownerName, String groupName, 148 FsPermission mode, long limit, long maxRelativeExpiry) { 149 Preconditions.checkNotNull(poolName); 150 Preconditions.checkNotNull(ownerName); 151 Preconditions.checkNotNull(groupName); 152 Preconditions.checkNotNull(mode); 153 this.poolName = poolName; 154 this.ownerName = ownerName; 155 this.groupName = groupName; 156 this.mode = new FsPermission(mode); 157 this.limit = limit; 158 this.maxRelativeExpiryMs = maxRelativeExpiry; 159 } 160 161 public String getPoolName() { 162 return poolName; 163 } 164 165 public String getOwnerName() { 166 return ownerName; 167 } 168 169 public CachePool setOwnerName(String ownerName) { 170 this.ownerName = ownerName; 171 return this; 172 } 173 174 public String getGroupName() { 175 return groupName; 176 } 177 178 public CachePool setGroupName(String groupName) { 179 this.groupName = groupName; 180 return this; 181 } 182 183 public FsPermission getMode() { 184 return mode; 185 } 186 187 public CachePool setMode(FsPermission mode) { 188 this.mode = new FsPermission(mode); 189 return this; 190 } 191 192 public long getLimit() { 193 return limit; 194 } 195 196 public CachePool setLimit(long bytes) { 197 this.limit = bytes; 198 return this; 199 } 200 201 public long getMaxRelativeExpiryMs() { 202 return maxRelativeExpiryMs; 203 } 204 205 public CachePool setMaxRelativeExpiryMs(long expiry) { 206 this.maxRelativeExpiryMs = expiry; 207 return this; 208 } 209 210 /** 211 * Get either full or partial information about this CachePool. 212 * 213 * @param fullInfo 214 * If true, only the name will be returned (i.e., what you 215 * would get if you didn't have read permission for this pool.) 216 * @return 217 * Cache pool information. 218 */ 219 CachePoolInfo getInfo(boolean fullInfo) { 220 CachePoolInfo info = new CachePoolInfo(poolName); 221 if (!fullInfo) { 222 return info; 223 } 224 return info.setOwnerName(ownerName). 225 setGroupName(groupName). 226 setMode(new FsPermission(mode)). 227 setLimit(limit). 228 setMaxRelativeExpiryMs(maxRelativeExpiryMs); 229 } 230 231 /** 232 * Resets statistics related to this CachePool 233 */ 234 public void resetStatistics() { 235 bytesNeeded = 0; 236 bytesCached = 0; 237 filesNeeded = 0; 238 filesCached = 0; 239 } 240 241 public void addBytesNeeded(long bytes) { 242 bytesNeeded += bytes; 243 } 244 245 public void addBytesCached(long bytes) { 246 bytesCached += bytes; 247 } 248 249 public void addFilesNeeded(long files) { 250 filesNeeded += files; 251 } 252 253 public void addFilesCached(long files) { 254 filesCached += files; 255 } 256 257 public long getBytesNeeded() { 258 return bytesNeeded; 259 } 260 261 public long getBytesCached() { 262 return bytesCached; 263 } 264 265 public long getBytesOverlimit() { 266 return Math.max(bytesNeeded-limit, 0); 267 } 268 269 public long getFilesNeeded() { 270 return filesNeeded; 271 } 272 273 public long getFilesCached() { 274 return filesCached; 275 } 276 277 /** 278 * Get statistics about this CachePool. 279 * 280 * @return Cache pool statistics. 281 */ 282 private CachePoolStats getStats() { 283 return new CachePoolStats.Builder(). 284 setBytesNeeded(bytesNeeded). 285 setBytesCached(bytesCached). 286 setBytesOverlimit(getBytesOverlimit()). 287 setFilesNeeded(filesNeeded). 288 setFilesCached(filesCached). 289 build(); 290 } 291 292 /** 293 * Returns a CachePoolInfo describing this CachePool based on the permissions 294 * of the calling user. Unprivileged users will see only minimal descriptive 295 * information about the pool. 296 * 297 * @param pc Permission checker to be used to validate the user's permissions, 298 * or null 299 * @return CachePoolEntry describing this CachePool 300 */ 301 public CachePoolEntry getEntry(FSPermissionChecker pc) { 302 boolean hasPermission = true; 303 if (pc != null) { 304 try { 305 pc.checkPermission(this, FsAction.READ); 306 } catch (AccessControlException e) { 307 hasPermission = false; 308 } 309 } 310 return new CachePoolEntry(getInfo(hasPermission), 311 hasPermission ? getStats() : new CachePoolStats.Builder().build()); 312 } 313 314 public String toString() { 315 return new StringBuilder(). 316 append("{ ").append("poolName:").append(poolName). 317 append(", ownerName:").append(ownerName). 318 append(", groupName:").append(groupName). 319 append(", mode:").append(mode). 320 append(", limit:").append(limit). 321 append(", maxRelativeExpiryMs:").append(maxRelativeExpiryMs). 322 append(" }").toString(); 323 } 324 325 public DirectiveList getDirectiveList() { 326 return directiveList; 327 } 328}