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.protocol; 019 020import java.io.PrintStream; 021import java.text.SimpleDateFormat; 022import java.util.Comparator; 023import java.util.Date; 024 025import org.apache.hadoop.fs.Path; 026import org.apache.hadoop.fs.permission.FsPermission; 027import org.apache.hadoop.hdfs.DFSUtilClient; 028 029/** 030 * Metadata about a snapshottable directory 031 */ 032public class SnapshottableDirectoryStatus { 033 /** Compare the statuses by full paths. */ 034 public static final Comparator<SnapshottableDirectoryStatus> COMPARATOR = 035 new Comparator<SnapshottableDirectoryStatus>() { 036 @Override 037 public int compare(SnapshottableDirectoryStatus left, 038 SnapshottableDirectoryStatus right) { 039 int d = DFSUtilClient.compareBytes(left.parentFullPath, 040 right.parentFullPath); 041 return d != 0? d 042 : DFSUtilClient.compareBytes(left.dirStatus.getLocalNameInBytes(), 043 right.dirStatus.getLocalNameInBytes()); 044 } 045 }; 046 047 /** Basic information of the snapshottable directory */ 048 private final HdfsFileStatus dirStatus; 049 050 /** Number of snapshots that have been taken*/ 051 private final int snapshotNumber; 052 053 /** Number of snapshots allowed. */ 054 private final int snapshotQuota; 055 056 /** Full path of the parent. */ 057 private final byte[] parentFullPath; 058 059 public SnapshottableDirectoryStatus(long modification_time, long access_time, 060 FsPermission permission, String owner, String group, byte[] localName, 061 long inodeId, int childrenNum, 062 int snapshotNumber, int snapshotQuota, byte[] parentFullPath) { 063 this.dirStatus = new HdfsFileStatus(0, true, 0, 0, modification_time, 064 access_time, permission, owner, group, null, localName, inodeId, 065 childrenNum, null, HdfsConstants.BLOCK_STORAGE_POLICY_ID_UNSPECIFIED); 066 this.snapshotNumber = snapshotNumber; 067 this.snapshotQuota = snapshotQuota; 068 this.parentFullPath = parentFullPath; 069 } 070 071 /** 072 * @return Number of snapshots that have been taken for the directory 073 */ 074 public int getSnapshotNumber() { 075 return snapshotNumber; 076 } 077 078 /** 079 * @return Number of snapshots allowed for the directory 080 */ 081 public int getSnapshotQuota() { 082 return snapshotQuota; 083 } 084 085 /** 086 * @return Full path of the parent 087 */ 088 public byte[] getParentFullPath() { 089 return parentFullPath; 090 } 091 092 /** 093 * @return The basic information of the directory 094 */ 095 public HdfsFileStatus getDirStatus() { 096 return dirStatus; 097 } 098 099 /** 100 * @return Full path of the file 101 */ 102 public Path getFullPath() { 103 String parentFullPathStr = 104 (parentFullPath == null || parentFullPath.length == 0) ? 105 null : DFSUtilClient.bytes2String(parentFullPath); 106 if (parentFullPathStr == null 107 && dirStatus.getLocalNameInBytes().length == 0) { 108 // root 109 return new Path("/"); 110 } else { 111 return parentFullPathStr == null ? new Path(dirStatus.getLocalName()) 112 : new Path(parentFullPathStr, dirStatus.getLocalName()); 113 } 114 } 115 116 /** 117 * Print a list of {@link SnapshottableDirectoryStatus} out to a given stream. 118 * @param stats The list of {@link SnapshottableDirectoryStatus} 119 * @param out The given stream for printing. 120 */ 121 public static void print(SnapshottableDirectoryStatus[] stats, 122 PrintStream out) { 123 if (stats == null || stats.length == 0) { 124 out.println(); 125 return; 126 } 127 int maxRepl = 0, maxLen = 0, maxOwner = 0, maxGroup = 0; 128 int maxSnapshotNum = 0, maxSnapshotQuota = 0; 129 for (SnapshottableDirectoryStatus status : stats) { 130 maxRepl = maxLength(maxRepl, status.dirStatus.getReplication()); 131 maxLen = maxLength(maxLen, status.dirStatus.getLen()); 132 maxOwner = maxLength(maxOwner, status.dirStatus.getOwner()); 133 maxGroup = maxLength(maxGroup, status.dirStatus.getGroup()); 134 maxSnapshotNum = maxLength(maxSnapshotNum, status.snapshotNumber); 135 maxSnapshotQuota = maxLength(maxSnapshotQuota, status.snapshotQuota); 136 } 137 138 String lineFormat = "%s%s " // permission string 139 + "%" + maxRepl + "s " 140 + (maxOwner > 0 ? "%-" + maxOwner + "s " : "%s") 141 + (maxGroup > 0 ? "%-" + maxGroup + "s " : "%s") 142 + "%" + maxLen + "s " 143 + "%s " // mod time 144 + "%" + maxSnapshotNum + "s " 145 + "%" + maxSnapshotQuota + "s " 146 + "%s"; // path 147 148 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm"); 149 150 for (SnapshottableDirectoryStatus status : stats) { 151 String line = String.format(lineFormat, "d", 152 status.dirStatus.getPermission(), 153 status.dirStatus.getReplication(), 154 status.dirStatus.getOwner(), 155 status.dirStatus.getGroup(), 156 String.valueOf(status.dirStatus.getLen()), 157 dateFormat.format(new Date(status.dirStatus.getModificationTime())), 158 status.snapshotNumber, status.snapshotQuota, 159 status.getFullPath().toString() 160 ); 161 out.println(line); 162 } 163 } 164 165 private static int maxLength(int n, Object value) { 166 return Math.max(n, String.valueOf(value).length()); 167 } 168 169 public static class Bean { 170 private final String path; 171 private final int snapshotNumber; 172 private final int snapshotQuota; 173 private final long modificationTime; 174 private final short permission; 175 private final String owner; 176 private final String group; 177 178 public Bean(String path, int snapshotNumber, int snapshotQuota, 179 long modificationTime, short permission, String owner, String group) { 180 this.path = path; 181 this.snapshotNumber = snapshotNumber; 182 this.snapshotQuota = snapshotQuota; 183 this.modificationTime = modificationTime; 184 this.permission = permission; 185 this.owner = owner; 186 this.group = group; 187 } 188 189 public String getPath() { 190 return path; 191 } 192 193 public int getSnapshotNumber() { 194 return snapshotNumber; 195 } 196 197 public int getSnapshotQuota() { 198 return snapshotQuota; 199 } 200 201 public long getModificationTime() { 202 return modificationTime; 203 } 204 205 public short getPermission() { 206 return permission; 207 } 208 209 public String getOwner() { 210 return owner; 211 } 212 213 public String getGroup() { 214 return group; 215 } 216 } 217}