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.io.DataInput; 021import java.io.DataOutput; 022import java.io.IOException; 023import java.util.List; 024 025import org.apache.hadoop.classification.InterfaceAudience; 026import org.apache.hadoop.classification.InterfaceStability; 027import org.apache.hadoop.io.Writable; 028import org.apache.hadoop.util.StringUtils; 029 030/** Store the summary of a content (a directory or a file). */ 031@InterfaceAudience.Public 032@InterfaceStability.Evolving 033public class ContentSummary extends QuotaUsage implements Writable{ 034 private long length; 035 private long fileCount; 036 private long directoryCount; 037 038 /** We don't use generics. Instead override spaceConsumed and other methods 039 in order to keep backward compatibility. */ 040 public static class Builder extends QuotaUsage.Builder { 041 public Builder() { 042 } 043 044 public Builder length(long length) { 045 this.length = length; 046 return this; 047 } 048 049 public Builder fileCount(long fileCount) { 050 this.fileCount = fileCount; 051 return this; 052 } 053 054 public Builder directoryCount(long directoryCount) { 055 this.directoryCount = directoryCount; 056 return this; 057 } 058 059 @Override 060 public Builder quota(long quota){ 061 super.quota(quota); 062 return this; 063 } 064 065 @Override 066 public Builder spaceConsumed(long spaceConsumed) { 067 super.spaceConsumed(spaceConsumed); 068 return this; 069 } 070 071 @Override 072 public Builder spaceQuota(long spaceQuota) { 073 super.spaceQuota(spaceQuota); 074 return this; 075 } 076 077 @Override 078 public Builder typeConsumed(long typeConsumed[]) { 079 super.typeConsumed(typeConsumed); 080 return this; 081 } 082 083 @Override 084 public Builder typeQuota(StorageType type, long quota) { 085 super.typeQuota(type, quota); 086 return this; 087 } 088 089 @Override 090 public Builder typeConsumed(StorageType type, long consumed) { 091 super.typeConsumed(type, consumed); 092 return this; 093 } 094 095 @Override 096 public Builder typeQuota(long typeQuota[]) { 097 super.typeQuota(typeQuota); 098 return this; 099 } 100 101 public ContentSummary build() { 102 // Set it in case applications call QuotaUsage#getFileAndDirectoryCount. 103 super.fileAndDirectoryCount(this.fileCount + this.directoryCount); 104 return new ContentSummary(this); 105 } 106 107 private long length; 108 private long fileCount; 109 private long directoryCount; 110 } 111 112 /** Constructor deprecated by ContentSummary.Builder*/ 113 @Deprecated 114 public ContentSummary() {} 115 116 /** Constructor, deprecated by ContentSummary.Builder 117 * This constructor implicitly set spaceConsumed the same as length. 118 * spaceConsumed and length must be set explicitly with 119 * ContentSummary.Builder 120 * */ 121 @Deprecated 122 public ContentSummary(long length, long fileCount, long directoryCount) { 123 this(length, fileCount, directoryCount, -1L, length, -1L); 124 } 125 126 /** Constructor, deprecated by ContentSummary.Builder */ 127 @Deprecated 128 public ContentSummary( 129 long length, long fileCount, long directoryCount, long quota, 130 long spaceConsumed, long spaceQuota) { 131 this.length = length; 132 this.fileCount = fileCount; 133 this.directoryCount = directoryCount; 134 setQuota(quota); 135 setSpaceConsumed(spaceConsumed); 136 setSpaceQuota(spaceQuota); 137 } 138 139 /** Constructor for ContentSummary.Builder*/ 140 private ContentSummary(Builder builder) { 141 super(builder); 142 this.length = builder.length; 143 this.fileCount = builder.fileCount; 144 this.directoryCount = builder.directoryCount; 145 } 146 147 /** @return the length */ 148 public long getLength() {return length;} 149 150 /** @return the directory count */ 151 public long getDirectoryCount() {return directoryCount;} 152 153 /** @return the file count */ 154 public long getFileCount() {return fileCount;} 155 156 @Override 157 @InterfaceAudience.Private 158 public void write(DataOutput out) throws IOException { 159 out.writeLong(length); 160 out.writeLong(fileCount); 161 out.writeLong(directoryCount); 162 out.writeLong(getQuota()); 163 out.writeLong(getSpaceConsumed()); 164 out.writeLong(getSpaceQuota()); 165 } 166 167 @Override 168 @InterfaceAudience.Private 169 public void readFields(DataInput in) throws IOException { 170 this.length = in.readLong(); 171 this.fileCount = in.readLong(); 172 this.directoryCount = in.readLong(); 173 setQuota(in.readLong()); 174 setSpaceConsumed(in.readLong()); 175 setSpaceQuota(in.readLong()); 176 } 177 178 @Override 179 public boolean equals(Object to) { 180 if (this == to) { 181 return true; 182 } else if (to instanceof ContentSummary) { 183 return getLength() == ((ContentSummary) to).getLength() && 184 getFileCount() == ((ContentSummary) to).getFileCount() && 185 getDirectoryCount() == ((ContentSummary) to).getDirectoryCount() && 186 super.equals(to); 187 } else { 188 return super.equals(to); 189 } 190 } 191 192 @Override 193 public int hashCode() { 194 long result = getLength() ^ getFileCount() ^ getDirectoryCount(); 195 return ((int) result) ^ super.hashCode(); 196 } 197 198 /** 199 * Output format: 200 * <----12----> <----12----> <-------18-------> 201 * DIR_COUNT FILE_COUNT CONTENT_SIZE 202 */ 203 private static final String SUMMARY_FORMAT = "%12s %12s %18s "; 204 205 private static final String[] SUMMARY_HEADER_FIELDS = 206 new String[] {"DIR_COUNT", "FILE_COUNT", "CONTENT_SIZE"}; 207 208 /** The header string */ 209 private static final String SUMMARY_HEADER = String.format( 210 SUMMARY_FORMAT, (Object[]) SUMMARY_HEADER_FIELDS); 211 212 private static final String ALL_HEADER = QUOTA_HEADER + SUMMARY_HEADER; 213 214 215 /** Return the header of the output. 216 * if qOption is false, output directory count, file count, and content size; 217 * if qOption is true, output quota and remaining quota as well. 218 * 219 * @param qOption a flag indicating if quota needs to be printed or not 220 * @return the header of the output 221 */ 222 public static String getHeader(boolean qOption) { 223 return qOption ? ALL_HEADER : SUMMARY_HEADER; 224 } 225 226 227 228 /** 229 * Returns the names of the fields from the summary header. 230 * 231 * @return names of fields as displayed in the header 232 */ 233 public static String[] getHeaderFields() { 234 return SUMMARY_HEADER_FIELDS; 235 } 236 237 /** 238 * Returns the names of the fields used in the quota summary. 239 * 240 * @return names of quota fields as displayed in the header 241 */ 242 public static String[] getQuotaHeaderFields() { 243 return QUOTA_HEADER_FIELDS; 244 } 245 246 @Override 247 public String toString() { 248 return toString(true); 249 } 250 251 /** Return the string representation of the object in the output format. 252 * if qOption is false, output directory count, file count, and content size; 253 * if qOption is true, output quota and remaining quota as well. 254 * 255 * @param qOption a flag indicating if quota needs to be printed or not 256 * @return the string representation of the object 257 */ 258 public String toString(boolean qOption) { 259 return toString(qOption, false); 260 } 261 262 /** Return the string representation of the object in the output format. 263 * if qOption is false, output directory count, file count, and content size; 264 * if qOption is true, output quota and remaining quota as well. 265 * if hOption is false file sizes are returned in bytes 266 * if hOption is true file sizes are returned in human readable 267 * 268 * @param qOption a flag indicating if quota needs to be printed or not 269 * @param hOption a flag indicating if human readable output if to be used 270 * @return the string representation of the object 271 */ 272 public String toString(boolean qOption, boolean hOption) { 273 return toString(qOption, hOption, false, null); 274 } 275 276 /** 277 * Return the string representation of the object in the output format. 278 * if tOption is true, display the quota by storage types, 279 * Otherwise, same logic with #toString(boolean,boolean) 280 * 281 * @param qOption a flag indicating if quota needs to be printed or not 282 * @param hOption a flag indicating if human readable output if to be used 283 * @param tOption a flag indicating if display quota by storage types 284 * @param types Storage types to display 285 * @return the string representation of the object 286 */ 287 public String toString(boolean qOption, boolean hOption, 288 boolean tOption, List<StorageType> types) { 289 String prefix = ""; 290 291 if (tOption) { 292 return getTypesQuotaUsage(hOption, types); 293 } 294 295 if (qOption) { 296 prefix = getQuotaUsage(hOption); 297 } 298 299 return prefix + String.format(SUMMARY_FORMAT, 300 formatSize(directoryCount, hOption), 301 formatSize(fileCount, hOption), 302 formatSize(length, hOption)); 303 } 304 305 /** 306 * Formats a size to be human readable or in bytes 307 * @param size value to be formatted 308 * @param humanReadable flag indicating human readable or not 309 * @return String representation of the size 310 */ 311 private String formatSize(long size, boolean humanReadable) { 312 return humanReadable 313 ? StringUtils.TraditionalBinaryPrefix.long2String(size, "", 1) 314 : String.valueOf(size); 315 } 316}