From 1260d598d352a00e51b27d44e6c77e73fa18b1a4 Mon Sep 17 00:00:00 2001 From: Jing Zhao Date: Fri, 13 Sep 2013 20:41:11 +0000 Subject: [PATCH] HDFS-4096. Add snapshot information to namenode WebUI. Contributed by Haohui Mai. git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1523091 13f79535-47bb-0310-9956-ffa450edef68 --- hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt | 3 + .../hdfs/server/namenode/FSNamesystem.java | 9 +++ .../server/namenode/NamenodeJspHelper.java | 11 +++ .../namenode/metrics/FSNamesystemMBean.java | 5 ++ .../src/main/webapps/hdfs/dfshealth.jsp | 5 +- .../namenode/TestFSNamesystemMBean.java | 72 +++++++++++++++++++ 6 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestFSNamesystemMBean.java diff --git a/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt b/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt index f8ac7928388..7dd9a126d75 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt +++ b/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt @@ -272,6 +272,9 @@ Release 2.3.0 - UNRELEASED HDFS-4879. Add "blocked ArrayList" collection to avoid CMS full GCs (Todd Lipcon via Colin Patrick McCabe) + HDFS-4096. Add snapshot information to namenode WebUI. (Haohui Mai via + jing9) + OPTIMIZATIONS BUG FIXES 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 dc733122c68..f4f8ccedec0 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 @@ -4199,6 +4199,15 @@ public class FSNamesystem implements Namesystem, FSClusterStats, return this.snapshotManager.getNumSnapshots(); } + @Override + public String getSnapshotStats() { + Map info = new HashMap(); + info.put("SnapshottableDirectories", this.getNumSnapshottableDirs()); + info.put("Snapshots", this.getNumSnapshots()); + return JSON.toString(info); + } + + int getNumberOfDatanodes(DatanodeReportType type) { readLock(); try { diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/NamenodeJspHelper.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/NamenodeJspHelper.java index 36163c7d0bf..e2aa4fcf7c5 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/NamenodeJspHelper.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/NamenodeJspHelper.java @@ -203,6 +203,17 @@ class NamenodeJspHelper { return ""; } + static void generateSnapshotReport(JspWriter out, FSNamesystem fsn) + throws IOException { + out.println("
" + + "\n" + + "" + + ""); + + out.println(String.format("", fsn.getNumSnapshottableDirs(), fsn.getNumSnapshots())); + out.println("
Snapshottable directoriesSnapshotted directories
%d%d
"); + } + static class HealthJsp { private int rowNum = 0; private int colNum = 0; diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/metrics/FSNamesystemMBean.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/metrics/FSNamesystemMBean.java index abc65ab51e9..4835fd86be3 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/metrics/FSNamesystemMBean.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/metrics/FSNamesystemMBean.java @@ -130,4 +130,9 @@ public interface FSNamesystemMBean { * @return number of decommissioned dead data nodes */ public int getNumDecomDeadDataNodes(); + + /** + * The statistics of snapshots + */ + public String getSnapshotStats(); } diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/webapps/hdfs/dfshealth.jsp b/hadoop-hdfs-project/hadoop-hdfs/src/main/webapps/hdfs/dfshealth.jsp index 0b0091e10d6..36f6199d978 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/webapps/hdfs/dfshealth.jsp +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/webapps/hdfs/dfshealth.jsp @@ -73,7 +73,10 @@ <% healthjsp.generateJournalReport(out, nn, request); %>
<% healthjsp.generateConfReport(out, nn, request); %> -
+
+

Snapshot Summary

+<% NamenodeJspHelper.generateSnapshotReport(out, fsn); %> +

Startup Progress

<% healthjsp.generateStartupProgress(out, nn.getStartupProgress()); %> <% diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestFSNamesystemMBean.java b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestFSNamesystemMBean.java new file mode 100644 index 00000000000..dcfd83ded68 --- /dev/null +++ b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestFSNamesystemMBean.java @@ -0,0 +1,72 @@ +/** + * 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; + +import static org.junit.Assert.assertTrue; + +import java.lang.management.ManagementFactory; +import java.util.Map; + +import javax.management.MBeanServer; +import javax.management.ObjectName; + +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.hdfs.MiniDFSCluster; +import org.junit.Test; +import org.mortbay.util.ajax.JSON; + +/** + * Class for testing {@link NameNodeMXBean} implementation + */ +public class TestFSNamesystemMBean { + + @Test + public void test() throws Exception { + Configuration conf = new Configuration(); + MiniDFSCluster cluster = null; + + try { + cluster = new MiniDFSCluster.Builder(conf).build(); + cluster.waitActive(); + + FSNamesystem fsn = cluster.getNameNode().namesystem; + + MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); + ObjectName mxbeanName = new ObjectName( + "Hadoop:service=NameNode,name=FSNamesystemState"); + + String snapshotStats = (String) (mbs.getAttribute(mxbeanName, + "SnapshotStats")); + + @SuppressWarnings("unchecked") + Map stat = (Map) JSON + .parse(snapshotStats); + + assertTrue(stat.containsKey("SnapshottableDirectories") + && (Long) stat.get("SnapshottableDirectories") == fsn + .getNumSnapshottableDirs()); + assertTrue(stat.containsKey("Snapshots") + && (Long) stat.get("Snapshots") == fsn.getNumSnapshots()); + + } finally { + if (cluster != null) { + cluster.shutdown(); + } + } + } +}