blob: ad7a6d9b6b68d84dbcd595887d39a3bb6c41694d [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.hadoop.hdfs.server.namenode.visitor;
import org.apache.hadoop.thirdparty.com.google.common.base.Preconditions;
import org.apache.hadoop.hdfs.server.blockmanagement.BlockInfo;
import org.apache.hadoop.hdfs.server.namenode.DirectoryWithQuotaFeature;
import org.apache.hadoop.hdfs.server.namenode.FSNamesystem;
import org.apache.hadoop.hdfs.server.namenode.INode;
import org.apache.hadoop.hdfs.server.namenode.INodeDirectory;
import org.apache.hadoop.hdfs.server.namenode.INodeFile;
import org.apache.hadoop.hdfs.server.namenode.INodeReference;
import org.apache.hadoop.hdfs.server.namenode.INodeSymlink;
import org.apache.hadoop.hdfs.server.namenode.snapshot.DirectorySnapshottableFeature;
import org.apache.hadoop.hdfs.server.namenode.snapshot.DirectoryWithSnapshotFeature;
import org.apache.hadoop.hdfs.server.namenode.snapshot.DirectoryWithSnapshotFeature.DirectoryDiff;
import org.apache.hadoop.hdfs.server.namenode.snapshot.FileWithSnapshotFeature;
import org.apache.hadoop.hdfs.server.namenode.snapshot.Snapshot;
import java.io.PrintWriter;
import java.io.StringWriter;
/**
* To print the namespace tree recursively for testing.
*
* \- foo (INodeDirectory@33dd2717)
* \- sub1 (INodeDirectory@442172)
* +- file1 (INodeFile@78392d4)
* +- file2 (INodeFile@78392d5)
* +- sub11 (INodeDirectory@8400cff)
* \- file3 (INodeFile@78392d6)
* \- z_file4 (INodeFile@45848712)
*/
public final class NamespacePrintVisitor implements NamespaceVisitor {
static final String NON_LAST_ITEM = "+-";
static final String LAST_ITEM = "\\-";
/** @return string of the tree in the given {@link FSNamesystem}. */
public static String print2Sting(FSNamesystem ns) {
return print2Sting(ns.getFSDirectory().getRoot());
}
/** @return string of the tree from the given root. */
public static String print2Sting(INode root) {
final StringWriter out = new StringWriter();
new NamespacePrintVisitor(new PrintWriter(out)).print(root);
return out.getBuffer().toString();
}
private final PrintWriter out;
private final StringBuffer prefix = new StringBuffer();
private NamespacePrintVisitor(PrintWriter out) {
this.out = out;
}
private void print(INode root) {
root.accept(this, Snapshot.CURRENT_STATE_ID);
}
private void printINode(INode iNode, int snapshot) {
out.print(prefix);
out.print(" ");
final String name = iNode.getLocalName();
out.print(name != null && name.isEmpty()? "/": name);
out.print(" (");
out.print(iNode.getObjectString());
out.print("), ");
out.print(iNode.getParentString());
out.print(", " + iNode.getPermissionStatus(snapshot));
}
@Override
public void visitFile(INodeFile file, int snapshot) {
printINode(file, snapshot);
out.print(", fileSize=" + file.computeFileSize(snapshot));
// print only the first block, if it exists
out.print(", blocks=");
final BlockInfo[] blocks = file.getBlocks();
out.print(blocks.length == 0 ? null: blocks[0]);
out.println();
final FileWithSnapshotFeature snapshotFeature
= file.getFileWithSnapshotFeature();
if (snapshotFeature != null) {
if (prefix.length() >= 2) {
prefix.setLength(prefix.length() - 2);
prefix.append(" ");
}
out.print(prefix);
out.print(snapshotFeature);
}
out.println();
}
@Override
public void visitSymlink(INodeSymlink symlink, int snapshot) {
printINode(symlink, snapshot);
out.print(" ~> ");
out.println(symlink.getSymlinkString());
}
@Override
public void visitReference(INodeReference ref, int snapshot) {
printINode(ref, snapshot);
if (ref instanceof INodeReference.DstReference) {
out.print(", dstSnapshotId=" + ref.getDstSnapshotId());
} else if (ref instanceof INodeReference.WithCount) {
out.print(", " + ((INodeReference.WithCount)ref).getCountDetails());
}
out.println();
}
@Override
public void preVisitReferred(INode referred) {
prefix.setLength(prefix.length() - 2);
prefix.append(" ->");
}
@Override
public void postVisitReferred(INode referred) {
prefix.setLength(prefix.length() - 2);
}
@Override
public void visitDirectory(INodeDirectory dir, int snapshot) {
printINode(dir, snapshot);
out.print(", childrenSize=" + dir.getChildrenList(snapshot).size());
final DirectoryWithQuotaFeature q = dir.getDirectoryWithQuotaFeature();
if (q != null) {
out.print(", " + q);
}
if (dir instanceof Snapshot.Root) {
out.print(", snapshotId=" + snapshot);
}
out.println();
if (prefix.length() >= 2) {
prefix.setLength(prefix.length() - 2);
prefix.append(" ");
}
final DirectoryWithSnapshotFeature snapshotFeature
= dir.getDirectoryWithSnapshotFeature();
if (snapshotFeature != null) {
out.print(prefix);
out.print(snapshotFeature);
}
out.println();
}
@Override
public void visitSnapshottable(INodeDirectory dir,
DirectorySnapshottableFeature snapshottable) {
out.println();
out.print(prefix);
out.print("Snapshot of ");
final String name = dir.getLocalName();
out.print(name != null && name.isEmpty()? "/": name);
out.print(": quota=");
out.print(snapshottable.getSnapshotQuota());
int n = 0;
for(DirectoryDiff diff : snapshottable.getDiffs()) {
if (diff.isSnapshotRoot()) {
n++;
}
}
final int numSnapshots = snapshottable.getNumSnapshots();
Preconditions.checkState(n == numSnapshots,
"numSnapshots = " + numSnapshots + " != " + n);
out.print(", #snapshot=");
out.println(n);
}
@Override
public void preVisitSub(Element sub, int index, boolean isLast) {
prefix.append(isLast? LAST_ITEM : NON_LAST_ITEM);
}
@Override
public void postVisitSub(Element sub, int index, boolean isLast) {
prefix.setLength(prefix.length() - 2);
}
}