HDFS-5196. Provide more snapshot information in WebUI. Contributed by Shinichi Yamashita.
git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1581427 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
56205ca7d7
commit
867e0f8ea9
|
@ -258,6 +258,9 @@ Release 2.5.0 - UNRELEASED
|
||||||
|
|
||||||
HDFS-6125. Cleanup unnecessary cast in HDFS code base. (suresh)
|
HDFS-6125. Cleanup unnecessary cast in HDFS code base. (suresh)
|
||||||
|
|
||||||
|
HDFS-5196. Provide more snapshot information in WebUI.
|
||||||
|
(Shinichi Yamashita via wheat9)
|
||||||
|
|
||||||
OPTIMIZATIONS
|
OPTIMIZATIONS
|
||||||
|
|
||||||
BUG FIXES
|
BUG FIXES
|
||||||
|
|
|
@ -20,6 +20,7 @@ package org.apache.hadoop.hdfs.protocol;
|
||||||
import org.apache.hadoop.classification.InterfaceAudience;
|
import org.apache.hadoop.classification.InterfaceAudience;
|
||||||
import org.apache.hadoop.classification.InterfaceStability;
|
import org.apache.hadoop.classification.InterfaceStability;
|
||||||
import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.FsPermissionProto;
|
import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.FsPermissionProto;
|
||||||
|
import org.apache.hadoop.hdfs.server.namenode.snapshot.Snapshot;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SnapshotInfo maintains information for a snapshot
|
* SnapshotInfo maintains information for a snapshot
|
||||||
|
@ -79,4 +80,28 @@ public class SnapshotInfo {
|
||||||
+ "; group=" + group
|
+ "; 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -166,4 +166,54 @@ public class SnapshottableDirectoryStatus {
|
||||||
private static int maxLength(int n, Object value) {
|
private static int maxLength(int n, Object value) {
|
||||||
return Math.max(n, String.valueOf(value).length());
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -974,6 +974,7 @@ public class FSNamesystem implements Namesystem, FSClusterStats,
|
||||||
|
|
||||||
registerMXBean();
|
registerMXBean();
|
||||||
DefaultMetricsSystem.instance().register(this);
|
DefaultMetricsSystem.instance().register(this);
|
||||||
|
snapshotManager.registerMXBean();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -5643,6 +5644,9 @@ public class FSNamesystem implements Namesystem, FSClusterStats,
|
||||||
* shutdown FSNamesystem
|
* shutdown FSNamesystem
|
||||||
*/
|
*/
|
||||||
void shutdown() {
|
void shutdown() {
|
||||||
|
if (snapshotManager != null) {
|
||||||
|
snapshotManager.shutdown();
|
||||||
|
}
|
||||||
if (mbeanName != null) {
|
if (mbeanName != null) {
|
||||||
MBeans.unregister(mbeanName);
|
MBeans.unregister(mbeanName);
|
||||||
mbeanName = null;
|
mbeanName = null;
|
||||||
|
|
|
@ -26,8 +26,11 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
import javax.management.ObjectName;
|
||||||
|
|
||||||
import org.apache.hadoop.hdfs.DFSUtil;
|
import org.apache.hadoop.hdfs.DFSUtil;
|
||||||
import org.apache.hadoop.hdfs.protocol.SnapshotException;
|
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.protocol.SnapshottableDirectoryStatus;
|
||||||
import org.apache.hadoop.hdfs.server.namenode.FSDirectory;
|
import org.apache.hadoop.hdfs.server.namenode.FSDirectory;
|
||||||
import org.apache.hadoop.hdfs.server.namenode.FSImageFormat;
|
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.INodeDirectory;
|
||||||
import org.apache.hadoop.hdfs.server.namenode.INodesInPath;
|
import org.apache.hadoop.hdfs.server.namenode.INodesInPath;
|
||||||
import org.apache.hadoop.hdfs.server.namenode.snapshot.INodeDirectorySnapshottable.SnapshotDiffInfo;
|
import org.apache.hadoop.hdfs.server.namenode.snapshot.INodeDirectorySnapshottable.SnapshotDiffInfo;
|
||||||
|
import org.apache.hadoop.metrics2.util.MBeans;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manage snapshottable directories and their snapshots.
|
* 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
|
* 2. Lock the {@link FSDirectory} lock for the {@link SnapshotManager} methods
|
||||||
* if necessary.
|
* if necessary.
|
||||||
*/
|
*/
|
||||||
public class SnapshotManager implements SnapshotStats {
|
public class SnapshotManager implements SnapshotStatsMXBean {
|
||||||
private boolean allowNestedSnapshots = false;
|
private boolean allowNestedSnapshots = false;
|
||||||
private final FSDirectory fsdir;
|
private final FSDirectory fsdir;
|
||||||
private static final int SNAPSHOT_ID_BIT_WIDTH = 24;
|
private static final int SNAPSHOT_ID_BIT_WIDTH = 24;
|
||||||
|
@ -259,12 +263,10 @@ public class SnapshotManager implements SnapshotStats {
|
||||||
srcRoot.renameSnapshot(path, oldSnapshotName, newSnapshotName);
|
srcRoot.renameSnapshot(path, oldSnapshotName, newSnapshotName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getNumSnapshottableDirs() {
|
public int getNumSnapshottableDirs() {
|
||||||
return snapshottables.size();
|
return snapshottables.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getNumSnapshots() {
|
public int getNumSnapshots() {
|
||||||
return numSnapshots.get();
|
return numSnapshots.get();
|
||||||
}
|
}
|
||||||
|
@ -372,4 +374,57 @@ public class SnapshotManager implements SnapshotStats {
|
||||||
public int getMaxSnapshotID() {
|
public int getMaxSnapshotID() {
|
||||||
return ((1 << SNAPSHOT_ID_BIT_WIDTH) - 1);
|
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<SnapshottableDirectoryStatus.Bean> directory =
|
||||||
|
new ArrayList<SnapshottableDirectoryStatus.Bean>();
|
||||||
|
private List<SnapshotInfo.Bean> snapshots =
|
||||||
|
new ArrayList<SnapshotInfo.Bean>();
|
||||||
|
|
||||||
|
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<SnapshottableDirectoryStatus.Bean> getDirectory() {
|
||||||
|
return directory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<SnapshotInfo.Bean> getSnapshots() {
|
||||||
|
return snapshots;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,20 +17,18 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.hadoop.hdfs.server.namenode.snapshot;
|
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
|
* This is an interface used to retrieve statistic information related to
|
||||||
* snapshots
|
* 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();
|
public SnapshotDirectoryMXBean getSnapshotStats();
|
||||||
|
|
||||||
/**
|
|
||||||
* @return The number of directories that have been snapshotted
|
|
||||||
*/
|
|
||||||
public int getNumSnapshots();
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -55,6 +55,32 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
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);
|
$.extend(dust.filters, filters);
|
||||||
|
|
|
@ -189,8 +189,54 @@
|
||||||
|
|
||||||
<script type="text/x-dust-template" id="tmpl-snapshot">
|
<script type="text/x-dust-template" id="tmpl-snapshot">
|
||||||
<div class="page-header"><h1>Snapshot Summary</h1></div>
|
<div class="page-header"><h1>Snapshot Summary</h1></div>
|
||||||
<p><b>Snapshottable directories</b>: {SnapshottableDirectories}</p>
|
<div class="page-header"><h1><small>Snapshottable directories: {@size key=SnapshotStats.directory}{/size}</small></div>
|
||||||
<p><b>Snapshotted directories</b>: {Snapshots}</p>
|
<small>
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Path</th>
|
||||||
|
<th>Snapshot Number</th>
|
||||||
|
<th>Snapshot Quota</th>
|
||||||
|
<th>Modification Time</th>
|
||||||
|
<th>Permission</th>
|
||||||
|
<th>Owner</th>
|
||||||
|
<th>Group</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
{#SnapshotStats.directory}
|
||||||
|
<tr>
|
||||||
|
<td>{path}</td>
|
||||||
|
<td>{snapshotNumber}</td>
|
||||||
|
<td>{snapshotQuota}</td>
|
||||||
|
<td>{modificationTime|date_tostring}</td>
|
||||||
|
<td>{permission|helper_to_permission}</td>
|
||||||
|
<td>{owner}</td>
|
||||||
|
<td>{group}</td>
|
||||||
|
</tr>
|
||||||
|
{/SnapshotStats.directory}
|
||||||
|
</table>
|
||||||
|
</small>
|
||||||
|
|
||||||
|
<div class="page-header"><h1><small>Snapshotted directories: {@size key=SnapshotStats.snapshots}{/size}</small></div>
|
||||||
|
|
||||||
|
<small>
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Snapshot ID</th>
|
||||||
|
<th>Snapshot Directory</th>
|
||||||
|
<th>Modification Time</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
{#SnapshotStats.snapshots}
|
||||||
|
<tr>
|
||||||
|
<td>{snapshotID}</td>
|
||||||
|
<td>{snapshotDirectory}</td>
|
||||||
|
<td>{modificationTime|date_tostring}</td>
|
||||||
|
</tr>
|
||||||
|
{/SnapshotStats.snapshots}
|
||||||
|
</table>
|
||||||
|
</small>
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script type="text/x-dust-template" id="tmpl-datanode">
|
<script type="text/x-dust-template" id="tmpl-datanode">
|
||||||
|
|
|
@ -169,10 +169,9 @@
|
||||||
|
|
||||||
function load_snapshot_info() {
|
function load_snapshot_info() {
|
||||||
$.get(
|
$.get(
|
||||||
'/jmx?qry=Hadoop:service=NameNode,name=FSNamesystemState',
|
'/jmx?qry=Hadoop:service=NameNode,name=SnapshotInfo',
|
||||||
guard_with_startup_progress(function (resp) {
|
guard_with_startup_progress(function (resp) {
|
||||||
var data = JSON.parse(resp.beans[0].SnapshotStats);
|
dust.render('snapshot-info', resp.beans[0], function(err, out) {
|
||||||
dust.render('snapshot-info', data, function(err, out) {
|
|
||||||
$('#tab-snapshot').html(out);
|
$('#tab-snapshot').html(out);
|
||||||
$('#ui-tabs a[href="#tab-snapshot"]').tab('show');
|
$('#ui-tabs a[href="#tab-snapshot"]').tab('show');
|
||||||
});
|
});
|
||||||
|
|
|
@ -90,7 +90,7 @@
|
||||||
<tbody>
|
<tbody>
|
||||||
{#FileStatus}
|
{#FileStatus}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{#helper_to_permission/}</td>
|
<td>{type|helper_to_directory}{permission|helper_to_permission}</td>
|
||||||
<td>{owner}</td>
|
<td>{owner}</td>
|
||||||
<td>{group}</td>
|
<td>{group}</td>
|
||||||
<td>{length|fmt_bytes}</td>
|
<td>{length|fmt_bytes}</td>
|
||||||
|
|
|
@ -21,30 +21,7 @@
|
||||||
// The chunk size of tailing the files, i.e., how many bytes will be shown
|
// The chunk size of tailing the files, i.e., how many bytes will be shown
|
||||||
// in the preview.
|
// in the preview.
|
||||||
var TAIL_CHUNK_SIZE = 32768;
|
var TAIL_CHUNK_SIZE = 32768;
|
||||||
var helpers = {
|
|
||||||
'helper_to_permission': function(chunk, ctx, bodies, params) {
|
|
||||||
var p = ctx.current().permission;
|
|
||||||
var dir = ctx.current().type == 'DIRECTORY' ? 'd' : '-';
|
|
||||||
var symbols = [ '---', '--x', '-w-', '-wx', 'r--', 'r-x', 'rw-', 'rwx' ];
|
|
||||||
var sticky = p > 1000;
|
|
||||||
|
|
||||||
var res = "";
|
|
||||||
for (var i = 0; i < 3; ++i) {
|
|
||||||
res = symbols[(p % 10)] + res;
|
|
||||||
p = Math.floor(p / 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sticky) {
|
|
||||||
var otherExec = ((ctx.current().permission % 10) & 1) == 1;
|
|
||||||
res = res.substr(0, res.length - 1) + (otherExec ? 't' : 'T');
|
|
||||||
}
|
|
||||||
|
|
||||||
chunk.write(dir + res);
|
|
||||||
return chunk;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var base = dust.makeBase(helpers);
|
|
||||||
var current_directory = "";
|
var current_directory = "";
|
||||||
|
|
||||||
function show_err_msg(msg) {
|
function show_err_msg(msg) {
|
||||||
|
@ -171,7 +148,7 @@
|
||||||
current_directory = dir;
|
current_directory = dir;
|
||||||
$('#directory').val(dir);
|
$('#directory').val(dir);
|
||||||
window.location.hash = dir;
|
window.location.hash = dir;
|
||||||
dust.render('explorer', base.push(d), function(err, out) {
|
dust.render('explorer', d, function(err, out) {
|
||||||
$('#panel').html(out);
|
$('#panel').html(out);
|
||||||
|
|
||||||
$('.explorer-browse-links').click(function() {
|
$('.explorer-browse-links').click(function() {
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
/**
|
||||||
|
* 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.snapshot;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import java.lang.management.ManagementFactory;
|
||||||
|
import java.lang.reflect.Array;
|
||||||
|
|
||||||
|
import javax.management.MBeanServer;
|
||||||
|
import javax.management.ObjectName;
|
||||||
|
import javax.management.openmbean.CompositeData;
|
||||||
|
|
||||||
|
import org.apache.hadoop.conf.Configuration;
|
||||||
|
import org.apache.hadoop.fs.Path;
|
||||||
|
import org.apache.hadoop.hdfs.DistributedFileSystem;
|
||||||
|
import org.apache.hadoop.hdfs.MiniDFSCluster;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class TestSnapshotStatsMXBean {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test getting SnapshotStatsMXBean information
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testSnapshotStatsMXBeanInfo() throws Exception {
|
||||||
|
Configuration conf = new Configuration();
|
||||||
|
MiniDFSCluster cluster = null;
|
||||||
|
String pathName = "/snapshot";
|
||||||
|
Path path = new Path(pathName);
|
||||||
|
|
||||||
|
try {
|
||||||
|
cluster = new MiniDFSCluster.Builder(conf).build();
|
||||||
|
cluster.waitActive();
|
||||||
|
|
||||||
|
SnapshotManager sm = cluster.getNamesystem().getSnapshotManager();
|
||||||
|
DistributedFileSystem dfs = (DistributedFileSystem) cluster.getFileSystem();
|
||||||
|
dfs.mkdirs(path);
|
||||||
|
dfs.allowSnapshot(path);
|
||||||
|
dfs.createSnapshot(path);
|
||||||
|
|
||||||
|
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
|
||||||
|
ObjectName mxbeanName = new ObjectName(
|
||||||
|
"Hadoop:service=NameNode,name=SnapshotInfo");
|
||||||
|
|
||||||
|
CompositeData statsbean =
|
||||||
|
(CompositeData) mbs.getAttribute(mxbeanName, "SnapshotStats");
|
||||||
|
int numDirectories = Array.getLength(statsbean.get("directory"));
|
||||||
|
assertEquals(sm.getNumSnapshottableDirs(), numDirectories);
|
||||||
|
int numSnapshots = Array.getLength(statsbean.get("snapshots"));
|
||||||
|
assertEquals(sm.getNumSnapshots(), numSnapshots);
|
||||||
|
|
||||||
|
CompositeData directory = (CompositeData) Array.get(statsbean.get("directory"), 0);
|
||||||
|
CompositeData snapshots = (CompositeData) Array.get(statsbean.get("snapshots"), 0);
|
||||||
|
assertTrue(((String) directory.get("path")).contains(pathName));
|
||||||
|
assertTrue(((String) snapshots.get("snapshotDirectory")).contains(pathName));
|
||||||
|
} finally {
|
||||||
|
if (cluster != null) {
|
||||||
|
cluster.shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue