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;
023
024import org.apache.hadoop.classification.InterfaceAudience;
025import org.apache.hadoop.classification.InterfaceStability;
026import org.apache.hadoop.io.Writable;
027import org.apache.hadoop.util.StringUtils;
028
029/** Store the summary of a content (a directory or a file). */
030@InterfaceAudience.Public
031@InterfaceStability.Evolving
032public class ContentSummary implements Writable{
033  private long length;
034  private long fileCount;
035  private long directoryCount;
036  private long quota;
037  private long spaceConsumed;
038  private long spaceQuota;
039  // These fields are to track the snapshot-related portion of the values.
040  private long snapshotLength;
041  private long snapshotFileCount;
042  private long snapshotDirectoryCount;
043  private long snapshotSpaceConsumed;
044
045  /** Constructor */
046  public ContentSummary() {}
047  
048  /** Constructor */
049  public ContentSummary(long length, long fileCount, long directoryCount) {
050    this(length, fileCount, directoryCount, -1L, length, -1L);
051  }
052
053  /** Constructor */
054  public ContentSummary(
055      long length, long fileCount, long directoryCount, long quota,
056      long spaceConsumed, long spaceQuota) {
057    this(length, fileCount, directoryCount, quota, spaceConsumed, spaceQuota,
058        0, 0, 0, 0);
059  }
060
061  /** Constructor */
062  public ContentSummary(
063      long length, long fileCount, long directoryCount, long quota,
064      long spaceConsumed, long spaceQuota, long snapshotLength,
065      long snapshotFileCount, long snapshotDirectoryCount,
066      long snapshotSpaceConsumed) {
067    this.length = length;
068    this.fileCount = fileCount;
069    this.directoryCount = directoryCount;
070    this.quota = quota;
071    this.spaceConsumed = spaceConsumed;
072    this.spaceQuota = spaceQuota;
073    this.snapshotLength = snapshotLength;
074    this.snapshotFileCount = snapshotFileCount;
075    this.snapshotDirectoryCount = snapshotDirectoryCount;
076    this.snapshotSpaceConsumed = snapshotSpaceConsumed;
077  }
078
079  /** @return the length */
080  public long getLength() {return length;}
081
082  public long getSnapshotLength() {
083    return snapshotLength;
084  }
085
086  /** @return the directory count */
087  public long getDirectoryCount() {return directoryCount;}
088
089  public long getSnapshotDirectoryCount() {
090    return snapshotDirectoryCount;
091  }
092
093  /** @return the file count */
094  public long getFileCount() {return fileCount;}
095
096  public long getSnapshotFileCount() {
097    return snapshotFileCount;
098  }
099
100  /** Return the directory quota */
101  public long getQuota() {return quota;}
102  
103  /** Retuns (disk) space consumed */ 
104  public long getSpaceConsumed() {return spaceConsumed;}
105
106  public long getSnapshotSpaceConsumed() {
107    return snapshotSpaceConsumed;
108  }
109
110  /** Returns (disk) space quota */
111  public long getSpaceQuota() {return spaceQuota;}
112  
113  @Override
114  @InterfaceAudience.Private
115  public void write(DataOutput out) throws IOException {
116    out.writeLong(length);
117    out.writeLong(fileCount);
118    out.writeLong(directoryCount);
119    out.writeLong(quota);
120    out.writeLong(spaceConsumed);
121    out.writeLong(spaceQuota);
122  }
123
124  @Override
125  @InterfaceAudience.Private
126  public void readFields(DataInput in) throws IOException {
127    this.length = in.readLong();
128    this.fileCount = in.readLong();
129    this.directoryCount = in.readLong();
130    this.quota = in.readLong();
131    this.spaceConsumed = in.readLong();
132    this.spaceQuota = in.readLong();
133  }
134
135  @Override
136  public boolean equals(Object to) {
137    if (this == to) {
138      return true;
139    } else if (to instanceof ContentSummary) {
140      ContentSummary right = (ContentSummary) to;
141      return getLength() == right.getLength() &&
142          getFileCount() == right.getFileCount() &&
143          getDirectoryCount() == right.getDirectoryCount() &&
144          getSnapshotLength() == right.getSnapshotLength() &&
145          getSnapshotFileCount() == right.getSnapshotFileCount() &&
146          getSnapshotDirectoryCount() == right.getSnapshotDirectoryCount() &&
147          getSnapshotSpaceConsumed() == right.getSnapshotSpaceConsumed() &&
148          super.equals(to);
149    } else {
150      return super.equals(to);
151    }
152  }
153
154  @Override
155  public int hashCode() {
156    long result = getLength() ^ getFileCount() ^ getDirectoryCount()
157        ^ getSnapshotLength() ^ getSnapshotFileCount()
158        ^ getSnapshotDirectoryCount() ^ getSnapshotSpaceConsumed();
159    return ((int) result) ^ super.hashCode();
160  }
161
162  /**
163   * Output format:
164   * <----12----> <----12----> <-------18------->
165   *    DIR_COUNT   FILE_COUNT       CONTENT_SIZE
166   */
167  private static final String SUMMARY_FORMAT = "%12s %12s %18s ";
168  /**
169   * Output format:
170   * <----12----> <------15-----> <------15-----> <------15----->
171   *        QUOTA       REM_QUOTA     SPACE_QUOTA REM_SPACE_QUOTA
172   * <----12----> <----12----> <-------18------->
173   *    DIR_COUNT   FILE_COUNT       CONTENT_SIZE
174   */
175  private static final String QUOTA_SUMMARY_FORMAT = "%12s %15s ";
176  private static final String SPACE_QUOTA_SUMMARY_FORMAT = "%15s %15s ";
177
178  private static final String[] HEADER_FIELDS = new String[] { "DIR_COUNT",
179      "FILE_COUNT", "CONTENT_SIZE"};
180  private static final String[] QUOTA_HEADER_FIELDS = new String[] { "QUOTA",
181      "REM_QUOTA", "SPACE_QUOTA", "REM_SPACE_QUOTA" };
182
183  /** The header string */
184  private static final String HEADER = String.format(
185      SUMMARY_FORMAT, (Object[]) HEADER_FIELDS);
186
187  private static final String QUOTA_HEADER = String.format(
188      QUOTA_SUMMARY_FORMAT + SPACE_QUOTA_SUMMARY_FORMAT,
189      (Object[]) QUOTA_HEADER_FIELDS) +
190      HEADER;
191  
192  /** Return the header of the output.
193   * if qOption is false, output directory count, file count, and content size;
194   * if qOption is true, output quota and remaining quota as well.
195   * 
196   * @param qOption a flag indicating if quota needs to be printed or not
197   * @return the header of the output
198   */
199  public static String getHeader(boolean qOption) {
200    return qOption ? QUOTA_HEADER : HEADER;
201  }
202
203  /**
204   * Returns the names of the fields from the summary header.
205   * 
206   * @return names of fields as displayed in the header
207   */
208  public static String[] getHeaderFields() {
209    return HEADER_FIELDS;
210  }
211
212  /**
213   * Returns the names of the fields used in the quota summary.
214   * 
215   * @return names of quota fields as displayed in the header
216   */
217  public static String[] getQuotaHeaderFields() {
218    return QUOTA_HEADER_FIELDS;
219  }
220
221  @Override
222  public String toString() {
223    return toString(true);
224  }
225
226  /** Return the string representation of the object in the output format.
227   * if qOption is false, output directory count, file count, and content size;
228   * if qOption is true, output quota and remaining quota as well.
229   *
230   * @param qOption a flag indicating if quota needs to be printed or not
231   * @return the string representation of the object
232  */
233  public String toString(boolean qOption) {
234    return toString(qOption, false);
235  }
236
237  /** Return the string representation of the object in the output format.
238   * For description of the options,
239   * @see #toString(boolean, boolean, boolean)
240   * 
241   * @param qOption a flag indicating if quota needs to be printed or not
242   * @param hOption a flag indicating if human readable output if to be used
243   * @return the string representation of the object
244   */
245  public String toString(boolean qOption, boolean hOption) {
246    return toString(qOption, hOption, false);
247  }
248
249  /** Return the string representation of the object in the output format.
250   * if qOption is false, output directory count, file count, and content size;
251   * if qOption is true, output quota and remaining quota as well.
252   * if hOption is false, file sizes are returned in bytes
253   * if hOption is true, file sizes are returned in human readable
254   * if xOption is false, output includes the calculation from snapshots
255   * if xOption is true, output excludes the calculation from snapshots
256   *
257   * @param qOption a flag indicating if quota needs to be printed or not
258   * @param hOption a flag indicating if human readable output is to be used
259   * @param xOption a flag indicating if calculation from snapshots is to be
260   *                included in the output
261   * @return the string representation of the object
262   */
263  public String toString(boolean qOption, boolean hOption, boolean xOption) {
264    String prefix = "";
265    if (qOption) {
266      String quotaStr = "none";
267      String quotaRem = "inf";
268      String spaceQuotaStr = "none";
269      String spaceQuotaRem = "inf";
270      
271      if (quota>0) {
272        quotaStr = formatSize(quota, hOption);
273        quotaRem = formatSize(quota-(directoryCount+fileCount), hOption);
274      }
275      if (spaceQuota>0) {
276        spaceQuotaStr = formatSize(spaceQuota, hOption);
277        spaceQuotaRem = formatSize(spaceQuota - spaceConsumed, hOption);
278      }
279      
280      prefix = String.format(QUOTA_SUMMARY_FORMAT + SPACE_QUOTA_SUMMARY_FORMAT,
281                             quotaStr, quotaRem, spaceQuotaStr, spaceQuotaRem);
282    }
283
284    if (xOption) {
285      return prefix + String.format(SUMMARY_FORMAT,
286          formatSize(directoryCount - snapshotDirectoryCount, hOption),
287          formatSize(fileCount - snapshotFileCount, hOption),
288          formatSize(length - snapshotLength, hOption));
289    } else {
290      return prefix + String.format(SUMMARY_FORMAT,
291          formatSize(directoryCount, hOption),
292          formatSize(fileCount, hOption),
293          formatSize(length, hOption));
294    }
295  }
296  /**
297   * Formats a size to be human readable or in bytes
298   * @param size value to be formatted
299   * @param humanReadable flag indicating human readable or not
300   * @return String representation of the size
301  */
302  private String formatSize(long size, boolean humanReadable) {
303    return humanReadable
304      ? StringUtils.TraditionalBinaryPrefix.long2String(size, "", 1)
305      : String.valueOf(size);
306  }
307}