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.fs; 019 020import java.util.Arrays; 021import java.util.List; 022 023import org.apache.hadoop.classification.InterfaceAudience; 024import org.apache.hadoop.classification.InterfaceStability; 025import org.apache.hadoop.util.StringUtils; 026 027/** Store the quota usage of a directory. */ 028@InterfaceAudience.Public 029@InterfaceStability.Evolving 030public class QuotaUsage { 031 private long fileAndDirectoryCount; 032 // Make the followings protected so that 033 // deprecated ContentSummary constructor can use them. 034 private long quota; 035 private long spaceConsumed; 036 private long spaceQuota; 037 private long[] typeConsumed; 038 private long[] typeQuota; 039 040 /** Builder class for QuotaUsage. */ 041 public static class Builder { 042 public Builder() { 043 this.quota = -1; 044 this.spaceQuota = -1; 045 046 typeConsumed = new long[StorageType.values().length]; 047 typeQuota = new long[StorageType.values().length]; 048 for (int i = 0; i < typeQuota.length; i++) { 049 typeQuota[i] = -1; 050 } 051 } 052 053 public Builder fileAndDirectoryCount(long count) { 054 this.fileAndDirectoryCount = count; 055 return this; 056 } 057 058 public Builder quota(long quota){ 059 this.quota = quota; 060 return this; 061 } 062 063 public Builder spaceConsumed(long spaceConsumed) { 064 this.spaceConsumed = spaceConsumed; 065 return this; 066 } 067 068 public Builder spaceQuota(long spaceQuota) { 069 this.spaceQuota = spaceQuota; 070 return this; 071 } 072 073 public Builder typeConsumed(long[] typeConsumed) { 074 for (int i = 0; i < typeConsumed.length; i++) { 075 this.typeConsumed[i] = typeConsumed[i]; 076 } 077 return this; 078 } 079 080 public Builder typeQuota(StorageType type, long quota) { 081 this.typeQuota[type.ordinal()] = quota; 082 return this; 083 } 084 085 public Builder typeConsumed(StorageType type, long consumed) { 086 this.typeConsumed[type.ordinal()] = consumed; 087 return this; 088 } 089 090 public Builder typeQuota(long[] typeQuota) { 091 for (int i = 0; i < typeQuota.length; i++) { 092 this.typeQuota[i] = typeQuota[i]; 093 } 094 return this; 095 } 096 097 public QuotaUsage build() { 098 return new QuotaUsage(this); 099 } 100 101 private long fileAndDirectoryCount; 102 private long quota; 103 private long spaceConsumed; 104 private long spaceQuota; 105 private long[] typeConsumed; 106 private long[] typeQuota; 107 } 108 109 // Make it protected for the deprecated ContentSummary constructor. 110 protected QuotaUsage() { } 111 112 /** Build the instance based on the builder. */ 113 protected QuotaUsage(Builder builder) { 114 this.fileAndDirectoryCount = builder.fileAndDirectoryCount; 115 this.quota = builder.quota; 116 this.spaceConsumed = builder.spaceConsumed; 117 this.spaceQuota = builder.spaceQuota; 118 this.typeConsumed = builder.typeConsumed; 119 this.typeQuota = builder.typeQuota; 120 } 121 122 protected void setQuota(long quota) { 123 this.quota = quota; 124 } 125 126 protected void setSpaceConsumed(long spaceConsumed) { 127 this.spaceConsumed = spaceConsumed; 128 } 129 130 protected void setSpaceQuota(long spaceQuota) { 131 this.spaceQuota = spaceQuota; 132 } 133 134 /** Return the directory count. */ 135 public long getFileAndDirectoryCount() { 136 return fileAndDirectoryCount; 137 } 138 139 /** Return the directory quota. */ 140 public long getQuota() { 141 return quota; 142 } 143 144 /** Return (disk) space consumed. */ 145 public long getSpaceConsumed() { 146 return spaceConsumed; 147 } 148 149 /** Return (disk) space quota. */ 150 public long getSpaceQuota() { 151 return spaceQuota; 152 } 153 154 /** Return storage type quota. */ 155 public long getTypeQuota(StorageType type) { 156 return (typeQuota != null) ? typeQuota[type.ordinal()] : -1; 157 } 158 159 /** Return storage type consumed. */ 160 public long getTypeConsumed(StorageType type) { 161 return (typeConsumed != null) ? typeConsumed[type.ordinal()] : 0; 162 } 163 164 /** Return storage type quota. */ 165 private long[] getTypesQuota() { 166 return typeQuota; 167 } 168 169 /** Return storage type quota. */ 170 private long[] getTypesConsumed() { 171 return typeConsumed; 172 } 173 174 /** Return true if any storage type quota has been set. */ 175 public boolean isTypeQuotaSet() { 176 if (typeQuota == null) { 177 return false; 178 } 179 for (StorageType t : StorageType.getTypesSupportingQuota()) { 180 if (typeQuota[t.ordinal()] > 0) { 181 return true; 182 } 183 } 184 return false; 185 } 186 187 /** Return true if any storage type consumption information is available. */ 188 public boolean isTypeConsumedAvailable() { 189 if (typeConsumed == null) { 190 return false; 191 } 192 for (StorageType t : StorageType.getTypesSupportingQuota()) { 193 if (typeConsumed[t.ordinal()] > 0) { 194 return true; 195 } 196 } 197 return false; 198 } 199 200 @Override 201 public boolean equals(Object to) { 202 return (this == to || (to instanceof QuotaUsage && 203 getFileAndDirectoryCount() == 204 ((QuotaUsage) to).getFileAndDirectoryCount() && 205 getQuota() == ((QuotaUsage) to).getQuota() && 206 getSpaceConsumed() == ((QuotaUsage) to).getSpaceConsumed() && 207 getSpaceQuota() == ((QuotaUsage) to).getSpaceQuota() && 208 Arrays.equals(getTypesQuota(), ((QuotaUsage) to).getTypesQuota()) && 209 Arrays.equals(getTypesConsumed(), 210 ((QuotaUsage) to).getTypesConsumed()))); 211 } 212 213 @Override 214 public int hashCode() { 215 long result = (getFileAndDirectoryCount() ^ getQuota() ^ 216 getSpaceConsumed() ^ getSpaceQuota()); 217 if (getTypesQuota() != null) { 218 for (long quota : getTypesQuota()) { 219 result ^= quota; 220 } 221 } 222 if (getTypesConsumed() != null) { 223 for (long consumed : getTypesConsumed()) { 224 result ^= consumed; 225 } 226 } 227 return (int)result; 228 } 229 230 /** 231 * Output format: 232 * <----12----> <----15----> <----15----> <----15----> <-------18-------> 233 * QUOTA REMAINING_QUATA SPACE_QUOTA SPACE_QUOTA_REM FILE_NAME 234 */ 235 protected static final String QUOTA_STRING_FORMAT = "%12s %15s "; 236 protected static final String SPACE_QUOTA_STRING_FORMAT = "%15s %15s "; 237 238 protected static final String[] QUOTA_HEADER_FIELDS = new String[] {"QUOTA", 239 "REM_QUOTA", "SPACE_QUOTA", "REM_SPACE_QUOTA"}; 240 241 protected static final String QUOTA_HEADER = String.format( 242 QUOTA_STRING_FORMAT + SPACE_QUOTA_STRING_FORMAT, 243 (Object[]) QUOTA_HEADER_FIELDS); 244 245 /** 246 * Output format: 247 * <----12----> <------15-----> <------15-----> <------15-----> 248 * QUOTA REM_QUOTA SPACE_QUOTA REM_SPACE_QUOTA 249 * <----12----> <----12----> <-------18-------> 250 * DIR_COUNT FILE_COUNT CONTENT_SIZE 251 */ 252 private static final String STORAGE_TYPE_SUMMARY_FORMAT = "%13s %17s "; 253 254 /** Return the header of the output. 255 * @return the header of the output 256 */ 257 public static String getHeader() { 258 return QUOTA_HEADER; 259 } 260 261 /** default quota display string */ 262 private static final String QUOTA_NONE = "none"; 263 private static final String QUOTA_INF = "inf"; 264 265 @Override 266 public String toString() { 267 return toString(false); 268 } 269 270 public String toString(boolean hOption) { 271 return toString(hOption, false, null); 272 } 273 274 /** Return the string representation of the object in the output format. 275 * if hOption is false file sizes are returned in bytes 276 * if hOption is true file sizes are returned in human readable 277 * 278 * @param hOption a flag indicating if human readable output if to be used 279 * @return the string representation of the object 280 */ 281 public String toString(boolean hOption, 282 boolean tOption, List<StorageType> types) { 283 if (tOption) { 284 return getTypesQuotaUsage(hOption, types); 285 } 286 return getQuotaUsage(hOption); 287 } 288 289 protected String getQuotaUsage(boolean hOption) { 290 String quotaStr = QUOTA_NONE; 291 String quotaRem = QUOTA_INF; 292 String spaceQuotaStr = QUOTA_NONE; 293 String spaceQuotaRem = QUOTA_INF; 294 295 if (quota > 0) { 296 quotaStr = formatSize(quota, hOption); 297 quotaRem = formatSize(quota-fileAndDirectoryCount, hOption); 298 } 299 if (spaceQuota >= 0) { 300 spaceQuotaStr = formatSize(spaceQuota, hOption); 301 spaceQuotaRem = formatSize(spaceQuota - spaceConsumed, hOption); 302 } 303 304 return String.format(QUOTA_STRING_FORMAT + SPACE_QUOTA_STRING_FORMAT, 305 quotaStr, quotaRem, spaceQuotaStr, spaceQuotaRem); 306 } 307 308 protected String getTypesQuotaUsage(boolean hOption, 309 List<StorageType> types) { 310 StringBuffer content = new StringBuffer(); 311 for (StorageType st : types) { 312 long typeQuota = getTypeQuota(st); 313 long typeConsumed = getTypeConsumed(st); 314 String quotaStr = QUOTA_NONE; 315 String quotaRem = QUOTA_INF; 316 317 if (typeQuota >= 0) { 318 quotaStr = formatSize(typeQuota, hOption); 319 quotaRem = formatSize(typeQuota - typeConsumed, hOption); 320 } 321 322 content.append(String.format(STORAGE_TYPE_SUMMARY_FORMAT, 323 quotaStr, quotaRem)); 324 } 325 return content.toString(); 326 } 327 328 /** 329 * return the header of with the StorageTypes. 330 * 331 * @param storageTypes 332 * @return storage header string 333 */ 334 public static String getStorageTypeHeader(List<StorageType> storageTypes) { 335 StringBuffer header = new StringBuffer(); 336 337 for (StorageType st : storageTypes) { 338 /* the field length is 13/17 for quota and remain quota 339 * as the max length for quota name is ARCHIVE_QUOTA 340 * and remain quota name REM_ARCHIVE_QUOTA */ 341 String storageName = st.toString(); 342 header.append(String.format(STORAGE_TYPE_SUMMARY_FORMAT, 343 storageName + "_QUOTA", "REM_" + storageName + "_QUOTA")); 344 } 345 return header.toString(); 346 } 347 348 /** 349 * Formats a size to be human readable or in bytes. 350 * @param size value to be formatted 351 * @param humanReadable flag indicating human readable or not 352 * @return String representation of the size 353 */ 354 private String formatSize(long size, boolean humanReadable) { 355 return humanReadable 356 ? StringUtils.TraditionalBinaryPrefix.long2String(size, "", 1) 357 : String.valueOf(size); 358 } 359}