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.tools.offlineImageViewer; 019 020import org.apache.hadoop.fs.Path; 021import org.apache.hadoop.fs.permission.PermissionStatus; 022import org.apache.hadoop.hdfs.server.namenode.FsImageProto.INodeSection.INode; 023import org.apache.hadoop.hdfs.server.namenode.FsImageProto.INodeSection.INodeDirectory; 024import org.apache.hadoop.hdfs.server.namenode.FsImageProto.INodeSection.INodeFile; 025import org.apache.hadoop.hdfs.server.namenode.FsImageProto.INodeSection.INodeSymlink; 026 027import java.io.IOException; 028import java.io.PrintStream; 029import java.text.SimpleDateFormat; 030import java.util.Date; 031 032/** 033 * A PBImageDelimitedTextWriter generates a text representation of the PB fsimage, 034 * with each element separated by a delimiter string. All of the elements 035 * common to both inodes and inodes-under-construction are included. When 036 * processing an fsimage with a layout version that did not include an 037 * element, such as AccessTime, the output file will include a column 038 * for the value, but no value will be included. 039 * 040 * Individual block information for each file is not currently included. 041 * 042 * The default delimiter is tab, as this is an unlikely value to be included in 043 * an inode path or other text metadata. The delimiter value can be via the 044 * constructor. 045 */ 046public class PBImageDelimitedTextWriter extends PBImageTextWriter { 047 static final String DEFAULT_DELIMITER = "\t"; 048 private static final String DATE_FORMAT="yyyy-MM-dd HH:mm"; 049 private final SimpleDateFormat dateFormatter = 050 new SimpleDateFormat(DATE_FORMAT); 051 052 private final String delimiter; 053 054 PBImageDelimitedTextWriter(PrintStream out, String delimiter, String tempPath) 055 throws IOException { 056 super(out, tempPath); 057 this.delimiter = delimiter; 058 } 059 060 private String formatDate(long date) { 061 return dateFormatter.format(new Date(date)); 062 } 063 064 private void append(StringBuffer buffer, int field) { 065 buffer.append(delimiter); 066 buffer.append(field); 067 } 068 069 private void append(StringBuffer buffer, long field) { 070 buffer.append(delimiter); 071 buffer.append(field); 072 } 073 074 private void append(StringBuffer buffer, String field) { 075 buffer.append(delimiter); 076 buffer.append(field); 077 } 078 079 @Override 080 public String getEntry(String parent, INode inode) { 081 StringBuffer buffer = new StringBuffer(); 082 String inodeName = inode.getName().toStringUtf8(); 083 Path path = new Path(parent.isEmpty() ? "/" : parent, 084 inodeName.isEmpty() ? "/" : inodeName); 085 buffer.append(path.toString()); 086 PermissionStatus p = null; 087 boolean isDir = false; 088 089 switch (inode.getType()) { 090 case FILE: 091 INodeFile file = inode.getFile(); 092 p = getPermission(file.getPermission()); 093 append(buffer, file.getReplication()); 094 append(buffer, formatDate(file.getModificationTime())); 095 append(buffer, formatDate(file.getAccessTime())); 096 append(buffer, file.getPreferredBlockSize()); 097 append(buffer, file.getBlocksCount()); 098 append(buffer, FSImageLoader.getFileSize(file)); 099 append(buffer, 0); // NS_QUOTA 100 append(buffer, 0); // DS_QUOTA 101 break; 102 case DIRECTORY: 103 INodeDirectory dir = inode.getDirectory(); 104 p = getPermission(dir.getPermission()); 105 append(buffer, 0); // Replication 106 append(buffer, formatDate(dir.getModificationTime())); 107 append(buffer, formatDate(0)); // Access time. 108 append(buffer, 0); // Block size. 109 append(buffer, 0); // Num blocks. 110 append(buffer, 0); // Num bytes. 111 append(buffer, dir.getNsQuota()); 112 append(buffer, dir.getDsQuota()); 113 isDir = true; 114 break; 115 case SYMLINK: 116 INodeSymlink s = inode.getSymlink(); 117 p = getPermission(s.getPermission()); 118 append(buffer, 0); // Replication 119 append(buffer, formatDate(s.getModificationTime())); 120 append(buffer, formatDate(s.getAccessTime())); 121 append(buffer, 0); // Block size. 122 append(buffer, 0); // Num blocks. 123 append(buffer, 0); // Num bytes. 124 append(buffer, 0); // NS_QUOTA 125 append(buffer, 0); // DS_QUOTA 126 break; 127 default: 128 break; 129 } 130 assert p != null; 131 String dirString = isDir ? "d" : "-"; 132 append(buffer, dirString + p.getPermission().toString()); 133 append(buffer, p.getUserName()); 134 append(buffer, p.getGroupName()); 135 return buffer.toString(); 136 } 137 138 @Override 139 public String getHeader() { 140 StringBuffer buffer = new StringBuffer(); 141 buffer.append("Path"); 142 append(buffer, "Replication"); 143 append(buffer, "ModificationTime"); 144 append(buffer, "AccessTime"); 145 append(buffer, "PreferredBlockSize"); 146 append(buffer, "BlocksCount"); 147 append(buffer, "FileSize"); 148 append(buffer, "NSQUOTA"); 149 append(buffer, "DSQUOTA"); 150 append(buffer, "Permission"); 151 append(buffer, "UserName"); 152 append(buffer, "GroupName"); 153 return buffer.toString(); 154 } 155}