[prev in list] [next in list] [prev in thread] [next in thread]
List: hadoop-commits
Subject: [hadoop] branch trunk updated: HDFS-15531. Namenode UI: List snapshots in separate table for each sn
From: vivekratnavel () apache ! org
Date: 2020-08-27 18:36:59
Message-ID: 159855341915.19028.2955070039088127876 () gitbox ! apache ! org
[Download RAW message or body]
This is an automated email from the ASF dual-hosted git repository.
vivekratnavel pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/hadoop.git
The following commit(s) were added to refs/heads/trunk by this push:
new 06793da HDFS-15531. Namenode UI: List snapshots in separate table for each \
snapshottable directory (#2230) 06793da is described below
commit 06793da100123bda67afcda95d6f2221efd9c281
Author: Vivek Ratnavel Subramanian <vivekratnavel90@gmail.com>
AuthorDate: Thu Aug 27 11:36:30 2020 -0700
HDFS-15531. Namenode UI: List snapshots in separate table for each snapshottable \
directory (#2230)
---
.../src/main/webapps/hdfs/dfshealth.html | 53 ++++------
.../hadoop-hdfs/src/main/webapps/hdfs/dfshealth.js | 117 +++++++++++++++++++++
.../hadoop-hdfs/src/main/webapps/static/hadoop.css | 33 +++++-
3 files changed, 167 insertions(+), 36 deletions(-)
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 \
8b03185..27616fb 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
@@ -250,13 +250,15 @@
<script type="text/x-dust-template" id="tmpl-snapshot">
<div class="page-header"><h1>Snapshot Summary</h1></div>
-<div class="page-header"><h1><small>Snapshottable directories: {@size \
key=SnapshottableDirectories}{/size}</small></div> +<div \
class="snapshot-stats"><h2><small>Snapshottable Directories: {@size \
key=SnapshottableDirectories}{/size}</small></div> +<div \
class="snapshot-stats"><h2><small>Total Snapshots: {@size \
key=Snapshots}{/size}</small></div> <small>
-<table class="table">
+<table class="table" id="table-snapshots">
<thead>
<tr>
+ <th></th>
<th>Path</th>
- <th>Snapshot Number</th>
+ <th>Snapshots Count</th>
<th>Snapshot Quota</th>
<th>Modification Time</th>
<th>Permission</th>
@@ -264,42 +266,23 @@
<th>Group</th>
</tr>
</thead>
- {#SnapshottableDirectories}
- <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>
- {/SnapshottableDirectories}
-</table>
-</small>
-
-<div class="page-header"><h1><small>Snapshots: {@size \
key=Snapshots}{/size}</small></div>
-
-<small>
-<table class="table">
- <thead>
+ <tbody>
+ {#SnapshottableDirectories}
<tr>
- <th>Snapshot ID</th>
- <th>Snapshot Directory</th>
- <th>Modification Time</th>
- <th>Status</th>
+ <td class="details-control"></td>
+ <td ng-value="{path}">{path}</td>
+ <td ng-value="{snapshotNumber}">{snapshotNumber}</td>
+ <td ng-value="{snapshotQuota}">{snapshotQuota}</td>
+ <td ng-value="{modificationTime}">{modificationTime|date_tostring}</td>
+ <td>{permission|helper_to_permission}</td>
+ <td ng-value="{owner}">{owner}</td>
+ <td ng-value="{group}">{group}</td>
</tr>
- </thead>
- {#Snapshots}
- <tr>
- <td>{snapshotID}</td>
- <td>{snapshotDirectory}</td>
- <td>{modificationTime|date_tostring}</td>
- <td>{status}</td>
- </tr>
- {/Snapshots}
+ {/SnapshottableDirectories}
+ </tbody>
</table>
</small>
+
</script>
<script type="text/x-dust-template" id="tmpl-datanode">
diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/webapps/hdfs/dfshealth.js \
b/hadoop-hdfs-project/hadoop-hdfs/src/main/webapps/hdfs/dfshealth.js index \
9715c37..9be19fe 100644
--- a/hadoop-hdfs-project/hadoop-hdfs/src/main/webapps/hdfs/dfshealth.js
+++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/webapps/hdfs/dfshealth.js
@@ -429,10 +429,127 @@
dust.render('snapshot-info', resp.beans[0], function(err, out) {
$('#tab-snapshot').html(out);
$('#ui-tabs a[href="#tab-snapshot"]').tab('show');
+
+ // Build a map to store snapshottable directory -> snapshots
+ var snapshots = 'Snapshots' in resp.beans[0] ? resp.beans[0].Snapshots : \
[]; + var snapshotsMap = snapshots.reduce(function(result, snapshot) {
+ var rootPath = snapshot.snapshotDirectory.substr(0, \
snapshot.snapshotDirectory.indexOf(".snapshot") -1 ); + if (rootPath in \
result) { + var arr = result[rootPath];
+ arr.push(snapshot);
+ result[rootPath] = arr;
+ } else {
+ result[rootPath] = [snapshot];
+ }
+ return result;
+ }, {});
+
+ var table = $('#table-snapshots').DataTable( {
+ 'lengthMenu': [ [25, 50, 100, -1], [25, 50, 100, "All"] ],
+ 'columns': [
+ { 'orderable': false, 'searchable': false, 'data': null, \
'defaultContent': "" }, + { 'data': 'path', 'orderDataType': 'ng-value', \
'searchable': true , 'type': 'string', 'defaultContent': "" }, + { \
'data': 'snapshotNumber', 'orderDataType': 'ng-value', 'searchable': false , 'type': \
'num', 'defaultContent': 0 }, + { 'data': 'snapshotQuota', \
'orderDataType': 'ng-value', 'searchable': false , 'type': 'num', 'defaultContent': 0 \
}, + { 'data': 'modificationTime', 'orderDataType': 'ng-value', \
'searchable': false , 'type': 'string', 'defaultContent': "" }, + { \
'data': 'permission', 'orderable': false, 'searchable': false , 'type': 'string', \
'defaultContent': "" }, + { 'data': 'owner', 'orderDataType': \
'ng-value', 'searchable': true , 'type': 'string', 'defaultContent': "" }, + \
{ 'data': 'group', 'orderDataType': 'ng-value', 'searchable': true , 'type': \
'string', 'defaultContent': "" } + ],
+ 'order': [[ 1, 'asc' ]]
+ });
+ // Add event listener for opening and closing details
+ $('#table-snapshots tbody').on('click', 'td.details-control', function () \
{ + var tr = $(this).closest('tr');
+ var row = table.row( tr );
+
+ if ( row.child.isShown() ) {
+ // This row is already open - close it
+ row.child.hide();
+ tr.removeClass('shown');
+ }
+ else {
+ // Open this row
+ row.child( formatExpandedRow(row.data(), snapshotsMap) ).show();
+ var tableId = getSubTableId(row.data());
+ if (!$.fn.dataTable.isDataTable('#'+tableId)) {
+ $('#' + tableId).DataTable({
+ 'lengthMenu': [[25, 50, 100, -1], [25, 50, 100, "All"]],
+ 'columns': [
+ {
+ 'orderDataType': 'ng-value',
+ 'searchable': true,
+ 'type': 'num',
+ 'defaultContent': 0
+ },
+ {
+ 'orderDataType': 'ng-value',
+ 'searchable': true,
+ 'type': 'string',
+ 'defaultContent': ""
+ },
+ {
+ 'orderDataType': 'ng-value',
+ 'searchable': true,
+ 'type': 'string',
+ 'defaultContent': ""
+ },
+ {
+ 'orderDataType': 'ng-value',
+ 'searchable': true,
+ 'type': 'string',
+ 'defaultContent': ""
+ }
+ ],
+ 'order': [[0, 'asc']]
+ });
+ }
+ tr.addClass('shown');
+ }
+ });
});
})).fail(ajax_error_handler);
}
+ function getSubTableId(row) {
+ var path = row.path;
+ // replace all "/" with "-"
+ path = path.replace(/\//g, '-');
+ return "table-snapshots"+path;
+ }
+
+ function formatExpandedRow (row, snapshotsMap) {
+ // `row` is the original data object for the row
+ var tableId = getSubTableId(row);
+ var path = row.path;
+ var snapshots = snapshotsMap[path];
+ if (!snapshots || snapshots.length === 0) {
+ return 'No snapshots found for this path';
+ }
+ var tbody = snapshots.reduce(function(result, snapshot) {
+ var html = '<tr>'+
+ '<td ng-value="'+snapshot.snapshotID+'">'+ snapshot.snapshotID +'</td>'+
+ '<td ng-value="'+snapshot.snapshotDirectory+'">'+ \
snapshot.snapshotDirectory +'</td>'+ + '<td \
ng-value="'+snapshot.modificationTime+'">'+ \
moment(Number(snapshot.modificationTime)).format('ddd MMM DD HH:mm:ss ZZ YYYY') \
+'</td>'+ + '<td ng-value="'+snapshot.status+'">'+ snapshot.status +'</td>'+
+ '</tr>';
+ return result + html;
+ }, "");
+ return '<table class="table sub-table" id='+ tableId +'>'+
+ '<thead>'+
+ '<tr>'+
+ '<th>Snapshot ID</th>'+
+ '<th>Snapshot Directory</th>'+
+ '<th>Modification Time</th>' +
+ '<th>Status</th>' +
+ '</tr>'+
+ '</thead>'+
+ '<tbody>'+
+ tbody +
+ '</tbody>'+
+ '</table>';
+ }
+
function load_page() {
var hash = window.location.hash;
switch(hash) {
diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/webapps/static/hadoop.css \
b/hadoop-hdfs-project/hadoop-hdfs/src/main/webapps/static/hadoop.css index \
1f0d7a8..1245ebc 100644
--- a/hadoop-hdfs-project/hadoop-hdfs/src/main/webapps/static/hadoop.css
+++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/webapps/static/hadoop.css
@@ -369,4 +369,35 @@ header.bs-docs-nav, header.bs-docs-nav .navbar-brand {
.bar text {
fill: #fff;
font: 10px sans-serif;
-}
\ No newline at end of file
+}
+
+td.details-control:before {
+ color: #5fa341;
+ content: "\2b";
+ cursor: pointer;
+ font-size: 1.5em;
+ line-height: 1em;
+}
+
+tr.shown td.details-control:before {
+ color: #c7254e;
+ content: "\2212";
+ cursor: pointer;
+ font-size: 1.5em;
+ line-height: 1em;
+}
+
+#table-snapshots_wrapper {
+ margin-top: 20px;
+}
+
+table#table-snapshots>tbody>tr>td>.dataTables_wrapper {
+ padding-left: 50px;
+ padding-right: 10px;
+ padding-top: 10px;
+ background-color: #ddd;
+}
+
+.snapshot-stats>h2 {
+ margin: 0;
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: common-commits-unsubscribe@hadoop.apache.org
For additional commands, e-mail: common-commits-help@hadoop.apache.org
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic