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 */ 018 package org.apache.hadoop.hdfs.protocol; 019 020 import java.io.PrintStream; 021 import java.text.SimpleDateFormat; 022 import java.util.Comparator; 023 import java.util.Date; 024 025 import org.apache.hadoop.fs.Path; 026 import org.apache.hadoop.fs.permission.FsPermission; 027 import org.apache.hadoop.hdfs.DFSUtil; 028 import org.apache.hadoop.hdfs.server.blockmanagement.BlockStoragePolicySuite; 029 030 /** 031 * Metadata about a snapshottable directory 032 */ 033 public class SnapshottableDirectoryStatus { 034 /** Compare the statuses by full paths. */ 035 public static final Comparator<SnapshottableDirectoryStatus> COMPARATOR 036 = new Comparator<SnapshottableDirectoryStatus>() { 037 @Override 038 public int compare(SnapshottableDirectoryStatus left, 039 SnapshottableDirectoryStatus right) { 040 int d = DFSUtil.compareBytes(left.parentFullPath, right.parentFullPath); 041 return d != 0? d 042 : DFSUtil.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, BlockStoragePolicySuite.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 : DFSUtil.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 StringBuilder fmt = new StringBuilder(); 139 fmt.append("%s%s "); // permission string 140 fmt.append("%" + maxRepl + "s "); 141 fmt.append((maxOwner > 0) ? "%-" + maxOwner + "s " : "%s"); 142 fmt.append((maxGroup > 0) ? "%-" + maxGroup + "s " : "%s"); 143 fmt.append("%" + maxLen + "s "); 144 fmt.append("%s "); // mod time 145 fmt.append("%" + maxSnapshotNum + "s "); 146 fmt.append("%" + maxSnapshotQuota + "s "); 147 fmt.append("%s"); // path 148 149 String lineFormat = fmt.toString(); 150 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm"); 151 152 for (SnapshottableDirectoryStatus status : stats) { 153 String line = String.format(lineFormat, "d", 154 status.dirStatus.getPermission(), 155 status.dirStatus.getReplication(), 156 status.dirStatus.getOwner(), 157 status.dirStatus.getGroup(), 158 String.valueOf(status.dirStatus.getLen()), 159 dateFormat.format(new Date(status.dirStatus.getModificationTime())), 160 status.snapshotNumber, status.snapshotQuota, 161 status.getFullPath().toString() 162 ); 163 out.println(line); 164 } 165 } 166 167 private static int maxLength(int n, Object value) { 168 return Math.max(n, String.valueOf(value).length()); 169 } 170 171 public static class Bean { 172 private final String path; 173 private final int snapshotNumber; 174 private final int snapshotQuota; 175 private final long modificationTime; 176 private final short permission; 177 private final String owner; 178 private final String group; 179 180 public Bean(String path, int snapshotNumber, int snapshotQuota, 181 long modificationTime, short permission, String owner, String group) { 182 this.path = path; 183 this.snapshotNumber = snapshotNumber; 184 this.snapshotQuota = snapshotQuota; 185 this.modificationTime = modificationTime; 186 this.permission = permission; 187 this.owner = owner; 188 this.group = group; 189 } 190 191 public String getPath() { 192 return path; 193 } 194 195 public int getSnapshotNumber() { 196 return snapshotNumber; 197 } 198 199 public int getSnapshotQuota() { 200 return snapshotQuota; 201 } 202 203 public long getModificationTime() { 204 return modificationTime; 205 } 206 207 public short getPermission() { 208 return permission; 209 } 210 211 public String getOwner() { 212 return owner; 213 } 214 215 public String getGroup() { 216 return group; 217 } 218 } 219 }