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