diff --git a/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt b/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt index 626584b685c..89ab217fce0 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt +++ b/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt @@ -258,6 +258,9 @@ Release 2.5.0 - UNRELEASED HDFS-6125. Cleanup unnecessary cast in HDFS code base. (suresh) + HDFS-5196. Provide more snapshot information in WebUI. + (Shinichi Yamashita via wheat9) + OPTIMIZATIONS BUG FIXES diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/protocol/SnapshotInfo.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/protocol/SnapshotInfo.java index db734a10730..d50c856074e 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/protocol/SnapshotInfo.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/protocol/SnapshotInfo.java @@ -20,6 +20,7 @@ package org.apache.hadoop.hdfs.protocol; import org.apache.hadoop.classification.InterfaceAudience; import org.apache.hadoop.classification.InterfaceStability; import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.FsPermissionProto; +import org.apache.hadoop.hdfs.server.namenode.snapshot.Snapshot; /** * SnapshotInfo maintains information for a snapshot @@ -79,4 +80,28 @@ public class SnapshotInfo { + "; group=" + group + "}"; } + + public static class Bean { + private final String snapshotID; + private final String snapshotDirectory; + private final long modificationTime; + + public Bean(Snapshot s) { + this.snapshotID = s.getRoot().getLocalName(); + this.snapshotDirectory = s.getRoot().getFullPathName(); + this.modificationTime = s.getRoot().getModificationTime(); + } + + public String getSnapshotID() { + return snapshotID; + } + + public String getSnapshotDirectory() { + return snapshotDirectory; + } + + public long getModificationTime() { + return modificationTime; + } + } } diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/protocol/SnapshottableDirectoryStatus.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/protocol/SnapshottableDirectoryStatus.java index 3deecbf42da..43bdedfe1ce 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/protocol/SnapshottableDirectoryStatus.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/protocol/SnapshottableDirectoryStatus.java @@ -166,4 +166,54 @@ public class SnapshottableDirectoryStatus { private static int maxLength(int n, Object value) { return Math.max(n, String.valueOf(value).length()); } + + public static class Bean { + private final String path; + private final int snapshotNumber; + private final int snapshotQuota; + private final long modificationTime; + private final short permission; + private final String owner; + private final String group; + + public Bean(SnapshottableDirectoryStatus s) { + this.path = s.getFullPath().toString(); + this.snapshotNumber = s.getSnapshotNumber(); + this.snapshotQuota = s.getSnapshotQuota(); + this.modificationTime = s.getDirStatus().getModificationTime(); + this.permission = + Short.valueOf(Integer.toOctalString( + s.getDirStatus().getPermission().toShort())); + this.owner = s.getDirStatus().getOwner(); + this.group = s.getDirStatus().getGroup(); + } + + public String getPath() { + return path; + } + + public int getSnapshotNumber() { + return snapshotNumber; + } + + public int getSnapshotQuota() { + return snapshotQuota; + } + + public long getModificationTime() { + return modificationTime; + } + + public short getPermission() { + return permission; + } + + public String getOwner() { + return owner; + } + + public String getGroup() { + return group; + } + } } diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java index 91433d34337..7c871275d2d 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java @@ -974,6 +974,7 @@ public class FSNamesystem implements Namesystem, FSClusterStats, registerMXBean(); DefaultMetricsSystem.instance().register(this); + snapshotManager.registerMXBean(); } /** @@ -5643,6 +5644,9 @@ public class FSNamesystem implements Namesystem, FSClusterStats, * shutdown FSNamesystem */ void shutdown() { + if (snapshotManager != null) { + snapshotManager.shutdown(); + } if (mbeanName != null) { MBeans.unregister(mbeanName); mbeanName = null; diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/snapshot/SnapshotManager.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/snapshot/SnapshotManager.java index ac1a982d219..48d57bd485d 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/snapshot/SnapshotManager.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/snapshot/SnapshotManager.java @@ -26,8 +26,11 @@ import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; +import javax.management.ObjectName; + import org.apache.hadoop.hdfs.DFSUtil; import org.apache.hadoop.hdfs.protocol.SnapshotException; +import org.apache.hadoop.hdfs.protocol.SnapshotInfo; import org.apache.hadoop.hdfs.protocol.SnapshottableDirectoryStatus; import org.apache.hadoop.hdfs.server.namenode.FSDirectory; import org.apache.hadoop.hdfs.server.namenode.FSImageFormat; @@ -37,6 +40,7 @@ import org.apache.hadoop.hdfs.server.namenode.INode.BlocksMapUpdateInfo; import org.apache.hadoop.hdfs.server.namenode.INodeDirectory; import org.apache.hadoop.hdfs.server.namenode.INodesInPath; import org.apache.hadoop.hdfs.server.namenode.snapshot.INodeDirectorySnapshottable.SnapshotDiffInfo; +import org.apache.hadoop.metrics2.util.MBeans; /** * Manage snapshottable directories and their snapshots. @@ -50,7 +54,7 @@ import org.apache.hadoop.hdfs.server.namenode.snapshot.INodeDirectorySnapshottab * 2. Lock the {@link FSDirectory} lock for the {@link SnapshotManager} methods * if necessary. */ -public class SnapshotManager implements SnapshotStats { +public class SnapshotManager implements SnapshotStatsMXBean { private boolean allowNestedSnapshots = false; private final FSDirectory fsdir; private static final int SNAPSHOT_ID_BIT_WIDTH = 24; @@ -259,12 +263,10 @@ public class SnapshotManager implements SnapshotStats { srcRoot.renameSnapshot(path, oldSnapshotName, newSnapshotName); } - @Override public int getNumSnapshottableDirs() { return snapshottables.size(); } - @Override public int getNumSnapshots() { return numSnapshots.get(); } @@ -372,4 +374,57 @@ public class SnapshotManager implements SnapshotStats { public int getMaxSnapshotID() { return ((1 << SNAPSHOT_ID_BIT_WIDTH) - 1); } + + private ObjectName mxBeanName; + + public void registerMXBean() { + mxBeanName = MBeans.register("NameNode", "SnapshotInfo", this); + } + + public void shutdown() { + MBeans.unregister(mxBeanName); + mxBeanName = null; + } + + @Override // SnapshotStatsMXBean + public SnapshotDirectoryMXBean getSnapshotStats() { + SnapshottableDirectoryStatus[] stats = getSnapshottableDirListing(null); + if (stats == null) { + return null; + } + return new SnapshotDirectoryMXBean(stats); + } + + public class SnapshotDirectoryMXBean { + private List directory = + new ArrayList(); + private List snapshots = + new ArrayList(); + + public SnapshotDirectoryMXBean(SnapshottableDirectoryStatus[] stats) { + set(stats); + } + + public void set(SnapshottableDirectoryStatus[] stats) { + for (SnapshottableDirectoryStatus s : stats) { + directory.add(new SnapshottableDirectoryStatus.Bean(s)); + try { + for (Snapshot shot : getSnapshottableRoot( + s.getFullPath().toString()).getSnapshotList()) { + snapshots.add(new SnapshotInfo.Bean(shot)); + } + } catch (IOException e) { + continue; + } + } + } + + public List getDirectory() { + return directory; + } + + public List getSnapshots() { + return snapshots; + } + } } diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/snapshot/SnapshotStats.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/snapshot/SnapshotStatsMXBean.java similarity index 76% rename from hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/snapshot/SnapshotStats.java rename to hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/snapshot/SnapshotStatsMXBean.java index 29b40e9ce65..fafa2f578a6 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/snapshot/SnapshotStats.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/snapshot/SnapshotStatsMXBean.java @@ -17,20 +17,18 @@ */ package org.apache.hadoop.hdfs.server.namenode.snapshot; +import org.apache.hadoop.hdfs.server.namenode.snapshot.SnapshotManager.SnapshotDirectoryMXBean; + /** * This is an interface used to retrieve statistic information related to * snapshots */ -public interface SnapshotStats { +public interface SnapshotStatsMXBean { /** - * @return The number of snapshottale directories in the system + * Return the list of snapshottable directories + * + * @return the list of snapshottable directories */ - public int getNumSnapshottableDirs(); - - /** - * @return The number of directories that have been snapshotted - */ - public int getNumSnapshots(); - + public SnapshotDirectoryMXBean getSnapshotStats(); } diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/webapps/hdfs/dfs-dust.js b/hadoop-hdfs-project/hadoop-hdfs/src/main/webapps/hdfs/dfs-dust.js index e2918362db4..c029407e6de 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/webapps/hdfs/dfs-dust.js +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/webapps/hdfs/dfs-dust.js @@ -55,6 +55,32 @@ } return res; + }, + + 'date_tostring' : function (v) { + return new Date(Number(v)).toLocaleString(); + }, + + 'helper_to_permission': function (v) { + var symbols = [ '---', '--x', '-w-', '-wx', 'r--', 'r-x', 'rw-', 'rwx' ]; + var sticky = v > 1000; + + var res = ""; + for (var i = 0; i < 3; ++i) { + res = symbols[(v % 10)] + res; + v = Math.floor(v / 10); + } + + if (sticky) { + var otherExec = ((v % 10) & 1) == 1; + res = res.substr(0, res.length - 1) + (otherExec ? 't' : 'T'); + } + + return res; + }, + + 'helper_to_directory' : function (v) { + return v === 'DIRECTORY' ? 'd' : '-'; } }; $.extend(dust.filters, filters); diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/webapps/hdfs/dfshealth.html b/hadoop-hdfs-project/hadoop-hdfs/src/main/webapps/hdfs/dfshealth.html index eb7d4389c12..bce156ee82c 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/webapps/hdfs/dfshealth.html +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/webapps/hdfs/dfshealth.html @@ -189,8 +189,54 @@