1 /**
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 package org.apache.hadoop.hdfs.protocol;
19 
20 import java.io.PrintStream;
21 import java.text.SimpleDateFormat;
22 import java.util.Comparator;
23 import java.util.Date;
24 
25 import org.apache.hadoop.fs.Path;
26 import org.apache.hadoop.fs.permission.FsPermission;
27 import org.apache.hadoop.hdfs.DFSUtil;
28 import org.apache.hadoop.hdfs.server.blockmanagement.BlockStoragePolicySuite;
29 
30 /**
31  * Metadata about a snapshottable directory
32  */
33 public class SnapshottableDirectoryStatus {
34   /** Compare the statuses by full paths. */
35   public static final Comparator<SnapshottableDirectoryStatus> COMPARATOR
36       = new Comparator<SnapshottableDirectoryStatus>() {
37     @Override
38     public int compare(SnapshottableDirectoryStatus left,
39                        SnapshottableDirectoryStatus right) {
40       int d = DFSUtil.compareBytes(left.parentFullPath, right.parentFullPath);
41       return d != 0? d
42           : DFSUtil.compareBytes(left.dirStatus.getLocalNameInBytes(),
43               right.dirStatus.getLocalNameInBytes());
44     }
45   };
46 
47   /** Basic information of the snapshottable directory */
48   private final HdfsFileStatus dirStatus;
49 
50   /** Number of snapshots that have been taken*/
51   private final int snapshotNumber;
52 
53   /** Number of snapshots allowed. */
54   private final int snapshotQuota;
55 
56   /** Full path of the parent. */
57   private final byte[] parentFullPath;
58 
SnapshottableDirectoryStatus(long modification_time, long access_time, FsPermission permission, String owner, String group, byte[] localName, long inodeId, int childrenNum, int snapshotNumber, int snapshotQuota, byte[] parentFullPath)59   public SnapshottableDirectoryStatus(long modification_time, long access_time,
60       FsPermission permission, String owner, String group, byte[] localName,
61       long inodeId, int childrenNum,
62       int snapshotNumber, int snapshotQuota, byte[] parentFullPath) {
63     this.dirStatus = new HdfsFileStatus(0, true, 0, 0, modification_time,
64         access_time, permission, owner, group, null, localName, inodeId,
65         childrenNum, null, BlockStoragePolicySuite.ID_UNSPECIFIED);
66     this.snapshotNumber = snapshotNumber;
67     this.snapshotQuota = snapshotQuota;
68     this.parentFullPath = parentFullPath;
69   }
70 
71   /**
72    * @return Number of snapshots that have been taken for the directory
73    */
getSnapshotNumber()74   public int getSnapshotNumber() {
75     return snapshotNumber;
76   }
77 
78   /**
79    * @return Number of snapshots allowed for the directory
80    */
getSnapshotQuota()81   public int getSnapshotQuota() {
82     return snapshotQuota;
83   }
84 
85   /**
86    * @return Full path of the parent
87    */
getParentFullPath()88   public byte[] getParentFullPath() {
89     return parentFullPath;
90   }
91 
92   /**
93    * @return The basic information of the directory
94    */
getDirStatus()95   public HdfsFileStatus getDirStatus() {
96     return dirStatus;
97   }
98 
99   /**
100    * @return Full path of the file
101    */
getFullPath()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    */
print(SnapshottableDirectoryStatus[] stats, PrintStream out)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 
maxLength(int n, Object value)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 
Bean(String path, int snapshotNumber, int snapshotQuota, long modificationTime, short permission, String owner, String group)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 
getPath()191     public String getPath() {
192       return path;
193     }
194 
getSnapshotNumber()195     public int getSnapshotNumber() {
196       return snapshotNumber;
197     }
198 
getSnapshotQuota()199     public int getSnapshotQuota() {
200       return snapshotQuota;
201     }
202 
getModificationTime()203     public long getModificationTime() {
204       return modificationTime;
205     }
206 
getPermission()207     public short getPermission() {
208       return permission;
209     }
210 
getOwner()211     public String getOwner() {
212       return owner;
213     }
214 
getGroup()215     public String getGroup() {
216       return group;
217     }
218   }
219 }
220