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 ugi = NameNode.getRemoteUser(); 113 ownerName = ugi.getShortUserName(); 114 } 115 String groupName = info.getGroupName(); 116 if (groupName == null) { 117 if (ugi == null) { 118 ugi = NameNode.getRemoteUser(); 119 } 120 groupName = ugi.getPrimaryGroupName(); 121 } 122 FsPermission mode = (info.getMode() == null) ? 123 FsPermission.getCachePoolDefault() : info.getMode(); 124 long limit = info.getLimit() == null ? 125 CachePoolInfo.DEFAULT_LIMIT : info.getLimit(); 126 long maxRelativeExpiry = info.getMaxRelativeExpiryMs() == null ? 127 CachePoolInfo.DEFAULT_MAX_RELATIVE_EXPIRY : 128 info.getMaxRelativeExpiryMs(); 129 return new CachePool(info.getPoolName(), 130 ownerName, groupName, mode, limit, maxRelativeExpiry); 131 } 132 133 /** 134 * Create a new cache pool based on a CachePoolInfo object. 135 * No fields in the CachePoolInfo can be blank. 136 */ 137 static CachePool createFromInfo(CachePoolInfo info) { 138 return new CachePool(info.getPoolName(), 139 info.getOwnerName(), info.getGroupName(), 140 info.getMode(), info.getLimit(), info.getMaxRelativeExpiryMs()); 141 } 142 143 CachePool(String poolName, String ownerName, String groupName, 144 FsPermission mode, long limit, long maxRelativeExpiry) { 145 Preconditions.checkNotNull(poolName); 146 Preconditions.checkNotNull(ownerName); 147 Preconditions.checkNotNull(groupName); 148 Preconditions.checkNotNull(mode); 149 this.poolName = poolName; 150 this.ownerName = ownerName; 151 this.groupName = groupName; 152 this.mode = new FsPermission(mode); 153 this.limit = limit; 154 this.maxRelativeExpiryMs = maxRelativeExpiry; 155 } 156 157 public String getPoolName() { 158 return poolName; 159 } 160 161 public String getOwnerName() { 162 return ownerName; 163 } 164 165 public CachePool setOwnerName(String ownerName) { 166 this.ownerName = ownerName; 167 return this; 168 } 169 170 public String getGroupName() { 171 return groupName; 172 } 173 174 public CachePool setGroupName(String groupName) { 175 this.groupName = groupName; 176 return this; 177 } 178 179 public FsPermission getMode() { 180 return mode; 181 } 182 183 public CachePool setMode(FsPermission mode) { 184 this.mode = new FsPermission(mode); 185 return this; 186 } 187 188 public long getLimit() { 189 return limit; 190 } 191 192 public CachePool setLimit(long bytes) { 193 this.limit = bytes; 194 return this; 195 } 196 197 public long getMaxRelativeExpiryMs() { 198 return maxRelativeExpiryMs; 199 } 200 201 public CachePool setMaxRelativeExpiryMs(long expiry) { 202 this.maxRelativeExpiryMs = expiry; 203 return this; 204 } 205 206 /** 207 * Get either full or partial information about this CachePool. 208 * 209 * @param fullInfo 210 * If true, only the name will be returned (i.e., what you 211 * would get if you didn't have read permission for this pool.) 212 * @return 213 * Cache pool information. 214 */ 215 CachePoolInfo getInfo(boolean fullInfo) { 216 CachePoolInfo info = new CachePoolInfo(poolName); 217 if (!fullInfo) { 218 return info; 219 } 220 return info.setOwnerName(ownerName). 221 setGroupName(groupName). 222 setMode(new FsPermission(mode)). 223 setLimit(limit). 224 setMaxRelativeExpiryMs(maxRelativeExpiryMs); 225 } 226 227 /** 228 * Resets statistics related to this CachePool 229 */ 230 public void resetStatistics() { 231 bytesNeeded = 0; 232 bytesCached = 0; 233 filesNeeded = 0; 234 filesCached = 0; 235 } 236 237 public void addBytesNeeded(long bytes) { 238 bytesNeeded += bytes; 239 } 240 241 public void addBytesCached(long bytes) { 242 bytesCached += bytes; 243 } 244 245 public void addFilesNeeded(long files) { 246 filesNeeded += files; 247 } 248 249 public void addFilesCached(long files) { 250 filesCached += files; 251 } 252 253 public long getBytesNeeded() { 254 return bytesNeeded; 255 } 256 257 public long getBytesCached() { 258 return bytesCached; 259 } 260 261 public long getBytesOverlimit() { 262 return Math.max(bytesNeeded-limit, 0); 263 } 264 265 public long getFilesNeeded() { 266 return filesNeeded; 267 } 268 269 public long getFilesCached() { 270 return filesCached; 271 } 272 273 /** 274 * Get statistics about this CachePool. 275 * 276 * @return Cache pool statistics. 277 */ 278 private CachePoolStats getStats() { 279 return new CachePoolStats.Builder(). 280 setBytesNeeded(bytesNeeded). 281 setBytesCached(bytesCached). 282 setBytesOverlimit(getBytesOverlimit()). 283 setFilesNeeded(filesNeeded). 284 setFilesCached(filesCached). 285 build(); 286 } 287 288 /** 289 * Returns a CachePoolInfo describing this CachePool based on the permissions 290 * of the calling user. Unprivileged users will see only minimal descriptive 291 * information about the pool. 292 * 293 * @param pc Permission checker to be used to validate the user's permissions, 294 * or null 295 * @return CachePoolEntry describing this CachePool 296 */ 297 public CachePoolEntry getEntry(FSPermissionChecker pc) { 298 boolean hasPermission = true; 299 if (pc != null) { 300 try { 301 pc.checkPermission(this, FsAction.READ); 302 } catch (AccessControlException e) { 303 hasPermission = false; 304 } 305 } 306 return new CachePoolEntry(getInfo(hasPermission), 307 hasPermission ? getStats() : new CachePoolStats.Builder().build()); 308 } 309 310 public String toString() { 311 return new StringBuilder(). 312 append("{ ").append("poolName:").append(poolName). 313 append(", ownerName:").append(ownerName). 314 append(", groupName:").append(groupName). 315 append(", mode:").append(mode). 316 append(", limit:").append(limit). 317 append(", maxRelativeExpiryMs:").append(maxRelativeExpiryMs). 318 append(" }").toString(); 319 } 320 321 public DirectiveList getDirectiveList() { 322 return directiveList; 323 } 324}