From 726c1f14b826ffa69b002ba22e969e314d565acd Mon Sep 17 00:00:00 2001 From: Rohith Sharma K S Date: Thu, 12 May 2016 15:17:49 +0530 Subject: [PATCH] YARN-3840. Resource Manager web ui issue when sorting application by id (with application having id > 9999). Contributed by Mohammad Shahid Khan and Varun Saxena --- .../mapreduce/v2/app/webapp/TaskPage.java | 2 +- .../mapreduce/v2/app/webapp/TasksPage.java | 2 +- .../hadoop/yarn/webapp/view/JQueryUI.java | 21 ++++---- .../webapps/static/dt-sorting/natural.js | 54 +++++++++++++++++++ .../webapp/AppAttemptPage.java | 2 +- .../webapp/AppPage.java | 2 +- .../webapp/TestAHSWebApp.java | 50 ++++++++++++++++- .../yarn/server/webapp/WebPageUtils.java | 6 +-- .../webapp/AllApplicationsPage.java | 9 +++- .../nodemanager/webapp/AllContainersPage.java | 8 ++- .../resourcemanager/webapp/TestRMWebApp.java | 5 ++ 11 files changed, 139 insertions(+), 22 deletions(-) create mode 100644 hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/resources/webapps/static/dt-sorting/natural.js diff --git a/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/TaskPage.java b/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/TaskPage.java index 19b0d7cfdfe..f8637e7043b 100644 --- a/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/TaskPage.java +++ b/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/TaskPage.java @@ -221,7 +221,7 @@ public class TaskPage extends AppView { .append("\n{'aTargets': [ 5 ]") .append(", 'bSearchable': false }") - .append("\n, {'sType':'string', 'aTargets': [ 0 ]") + .append("\n, {'sType':'natural', 'aTargets': [ 0 ]") .append(", 'mRender': parseHadoopID }") .append("\n, {'sType':'numeric', 'aTargets': [ 6, 7") diff --git a/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/TasksPage.java b/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/TasksPage.java index 96485279db2..e2f12dc4d16 100644 --- a/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/TasksPage.java +++ b/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/TasksPage.java @@ -43,7 +43,7 @@ public class TasksPage extends AppView { .append(", bProcessing: true") .append("\n, aoColumnDefs: [\n") - .append("{'sType':'string', 'aTargets': [0]") + .append("{'sType':'natural', 'aTargets': [0]") .append(", 'mRender': parseHadoopID }") .append("\n, {'sType':'numeric', bSearchable:false, 'aTargets': [1]") diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/webapp/view/JQueryUI.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/webapp/view/JQueryUI.java index 9abfdac7e0f..06372e38574 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/webapp/view/JQueryUI.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/webapp/view/JQueryUI.java @@ -65,14 +65,14 @@ public class JQueryUI extends HtmlBlock { @Override protected void render(Block html) { - html. - link(root_url("static/jquery/themes-1.9.1/base/jquery-ui.css")). - link(root_url("static/dt-1.9.4/css/jui-dt.css")). - script(root_url("static/jquery/jquery-1.8.2.min.js")). - script(root_url("static/jquery/jquery-ui-1.9.1.custom.min.js")). - script(root_url("static/dt-1.9.4/js/jquery.dataTables.min.js")). - script(root_url("static/yarn.dt.plugins.js")). - style("#jsnotice { padding: 0.2em; text-align: center; }", + html.link(root_url("static/jquery/themes-1.9.1/base/jquery-ui.css")) + .link(root_url("static/dt-1.9.4/css/jui-dt.css")) + .script(root_url("static/jquery/jquery-1.8.2.min.js")) + .script(root_url("static/jquery/jquery-ui-1.9.1.custom.min.js")) + .script(root_url("static/dt-1.9.4/js/jquery.dataTables.min.js")) + .script(root_url("static/yarn.dt.plugins.js")) + .script(root_url("static/dt-sorting/natural.js")) + .style("#jsnotice { padding: 0.2em; text-align: center; }", ".ui-progressbar { height: 1em; min-width: 5em }"); // required List list = Lists.newArrayList(); @@ -82,9 +82,8 @@ public class JQueryUI extends HtmlBlock { initProgressBars(list); if (!list.isEmpty()) { - html. - script().$type("text/javascript"). - _("$(function() {")._(list.toArray())._("});")._(); + html.script().$type("text/javascript")._("$(function() {") + ._(list.toArray())._("});")._(); } } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/resources/webapps/static/dt-sorting/natural.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/resources/webapps/static/dt-sorting/natural.js new file mode 100644 index 00000000000..3475eddfd6a --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/resources/webapps/static/dt-sorting/natural.js @@ -0,0 +1,54 @@ +/** + * 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. + */ + +(function() { + function naturalSort (a, b) { + var diff = a.length - b.length; + if (diff != 0) { + var splitA = a.split("_"); + var splitB = b.split("_"); + if (splitA.length != splitB.length) { + return a.localeCompare(b); + } + for (var i=1; i < splitA.length; i++) { + var splitdiff = splitA[i].length - splitB[i].length; + if (splitdiff != 0) { + return splitdiff; + } + var splitCompare = splitA[i].localeCompare(splitB[i]); + if (splitCompare != 0) { + return splitCompare; + } + } + return diff; + } + return a.localeCompare(b); + } + +jQuery.extend( jQuery.fn.dataTableExt.oSort, { + "natural-asc": function ( a, b ) { + return naturalSort(a,b); + }, + + "natural-desc": function ( a, b ) { + return naturalSort(a,b) * -1; + } +} ); + +}()); + diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/AppAttemptPage.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/AppAttemptPage.java index c7fe3189558..a08297db9a6 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/AppAttemptPage.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/AppAttemptPage.java @@ -53,7 +53,7 @@ public class AppAttemptPage extends AHSView { protected String getContainersTableColumnDefs() { StringBuilder sb = new StringBuilder(); - return sb.append("[\n").append("{'sType':'string', 'aTargets': [0]") + return sb.append("[\n").append("{'sType':'natural', 'aTargets': [0]") .append(", 'mRender': parseHadoopID }]").toString(); } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/AppPage.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/AppPage.java index 50dcd9665ee..c0e1394ae62 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/AppPage.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/AppPage.java @@ -55,7 +55,7 @@ public class AppPage extends AHSView { protected String getAttemptsTableColumnDefs() { StringBuilder sb = new StringBuilder(); - return sb.append("[\n").append("{'sType':'string', 'aTargets': [0]") + return sb.append("[\n").append("{'sType':'natural', 'aTargets': [0]") .append(", 'mRender': parseHadoopID }") .append("\n, {'sType':'numeric', 'aTargets': [1]") diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/TestAHSWebApp.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/TestAHSWebApp.java index 1e0886f36c2..49fcc58b2ae 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/TestAHSWebApp.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/TestAHSWebApp.java @@ -21,7 +21,7 @@ package org.apache.hadoop.yarn.server.applicationhistoryservice.webapp; import static org.apache.hadoop.yarn.webapp.Params.TITLE; import static org.mockito.Mockito.mock; -import org.junit.Assert; +import java.util.Map; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.yarn.api.ApplicationBaseProtocol; import org.apache.hadoop.yarn.api.records.ApplicationAttemptId; @@ -38,6 +38,7 @@ import org.apache.hadoop.yarn.server.applicationhistoryservice.MemoryApplication import org.apache.hadoop.yarn.util.StringHelper; import org.apache.hadoop.yarn.webapp.YarnWebParams; import org.apache.hadoop.yarn.webapp.test.WebAppTests; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -87,6 +88,21 @@ public class TestAHSWebApp extends ApplicationHistoryStoreTestUtils { WebAppTests.flushOutput(injector); } + @Test + public void testAPPViewNaturalSortType() throws Exception { + Injector injector = + WebAppTests.createMockInjector(ApplicationBaseProtocol.class, + mockApplicationHistoryClientService(5, 1, 1)); + AHSView ahsViewInstance = injector.getInstance(AHSView.class); + + ahsViewInstance.render(); + WebAppTests.flushOutput(injector); + Map moreParams = + ahsViewInstance.context().requestContext().moreParams(); + String appTableColumnsMeta = moreParams.get("ui.dataTables.apps.init"); + Assert.assertTrue(appTableColumnsMeta.indexOf("natural") != -1); + } + @Test public void testAboutPage() throws Exception { Injector injector = @@ -117,6 +133,22 @@ public class TestAHSWebApp extends ApplicationHistoryStoreTestUtils { WebAppTests.flushOutput(injector); } + @Test + public void testAppPageNaturalSortType() throws Exception { + Injector injector = + WebAppTests.createMockInjector(ApplicationBaseProtocol.class, + mockApplicationHistoryClientService(1, 5, 1)); + AppPage appPageInstance = injector.getInstance(AppPage.class); + + appPageInstance.render(); + WebAppTests.flushOutput(injector); + Map moreParams = + appPageInstance.context().requestContext().moreParams(); + String attemptsTableColumnsMeta = + moreParams.get("ui.dataTables.attempts.init"); + Assert.assertTrue(attemptsTableColumnsMeta.indexOf("natural") != -1); + } + @Test public void testAppAttemptPage() throws Exception { Injector injector = @@ -135,6 +167,21 @@ public class TestAHSWebApp extends ApplicationHistoryStoreTestUtils { WebAppTests.flushOutput(injector); } + @Test + public void testAppAttemptPageNaturalSortType() throws Exception { + Injector injector = + WebAppTests.createMockInjector(ApplicationBaseProtocol.class, + mockApplicationHistoryClientService(1, 1, 5)); + AppAttemptPage appAttemptPageInstance = + injector.getInstance(AppAttemptPage.class); + appAttemptPageInstance.render(); + WebAppTests.flushOutput(injector); + Map moreParams = + appAttemptPageInstance.context().requestContext().moreParams(); + String tableColumnsMeta = moreParams.get("ui.dataTables.containers.init"); + Assert.assertTrue(tableColumnsMeta.indexOf("natural") != -1); + } + @Test public void testContainerPage() throws Exception { Injector injector = @@ -195,5 +242,4 @@ public class TestAHSWebApp extends ApplicationHistoryStoreTestUtils { return store; } }; - } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-common/src/main/java/org/apache/hadoop/yarn/server/webapp/WebPageUtils.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-common/src/main/java/org/apache/hadoop/yarn/server/webapp/WebPageUtils.java index d51c632c4da..a07baa2366f 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-common/src/main/java/org/apache/hadoop/yarn/server/webapp/WebPageUtils.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-common/src/main/java/org/apache/hadoop/yarn/server/webapp/WebPageUtils.java @@ -49,7 +49,7 @@ public class WebPageUtils { boolean isFairSchedulerPage, boolean isResourceManager) { StringBuilder sb = new StringBuilder(); sb.append("[\n") - .append("{'sType':'string', 'aTargets': [0]") + .append("{'sType':'natural', 'aTargets': [0]") .append(", 'mRender': parseHadoopID }") .append("\n, {'sType':'numeric', 'aTargets': [6, 7]") .append(", 'mRender': renderHadoopDate }") @@ -75,7 +75,7 @@ public class WebPageUtils { private static String getAttemptsTableColumnDefs() { StringBuilder sb = new StringBuilder(); - return sb.append("[\n").append("{'sType':'string', 'aTargets': [0]") + return sb.append("[\n").append("{'sType':'natural', 'aTargets': [0]") .append(", 'mRender': parseHadoopID }") .append("\n, {'sType':'numeric', 'aTargets': [1]") .append(", 'mRender': renderHadoopDate }]").toString(); @@ -91,7 +91,7 @@ public class WebPageUtils { private static String getContainersTableColumnDefs() { StringBuilder sb = new StringBuilder(); - return sb.append("[\n").append("{'sType':'string', 'aTargets': [0]") + return sb.append("[\n").append("{'sType':'natural', 'aTargets': [0]") .append(", 'mRender': parseHadoopID }]").toString(); } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/AllApplicationsPage.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/AllApplicationsPage.java index 9a227430a99..d32b271e46a 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/AllApplicationsPage.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/AllApplicationsPage.java @@ -54,7 +54,14 @@ public class AllApplicationsPage extends NMView { // Sort by id upon page load append(", aaSorting: [[0, 'asc']]"). // applicationid, applicationstate - append(", aoColumns:[null, null]} ").toString(); + append(", aoColumns:[").append(getApplicationsIdColumnDefs()) + .append(", null]} ").toString(); + } + + private String getApplicationsIdColumnDefs() { + StringBuilder sb = new StringBuilder(); + return sb.append("{'sType':'natural', 'aTargets': [0]") + .append(", 'mRender': parseHadoopID }").toString(); } @Override diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/AllContainersPage.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/AllContainersPage.java index 1bbb945d87a..24b85753b18 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/AllContainersPage.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/AllContainersPage.java @@ -52,9 +52,15 @@ public class AllContainersPage extends NMView { private String containersTableInit() { return tableInit(). // containerid, containerid, log-url - append(", aoColumns:[null, null, {bSearchable:false}]} ").toString(); + append(", aoColumns:[").append(getContainersIdColumnDefs()) + .append(", null, {bSearchable:false}]} ").toString(); } + private String getContainersIdColumnDefs() { + StringBuilder sb = new StringBuilder(); + return sb.append("{'sType':'natural', 'aTargets': [0]") + .append(", 'mRender': parseHadoopID }").toString(); + } @Override protected Class content() { return AllContainersBlock.class; diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebApp.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebApp.java index 02904217060..edf3b3ff6ec 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebApp.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebApp.java @@ -28,6 +28,7 @@ import static org.mockito.Mockito.when; import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.concurrent.ConcurrentMap; import org.apache.hadoop.conf.Configuration; @@ -119,6 +120,10 @@ public class TestRMWebApp { YarnApplicationState.RUNNING.toString())); rmViewInstance.render(); WebAppTests.flushOutput(injector); + Map moreParams = + rmViewInstance.context().requestContext().moreParams(); + String appsTableColumnsMeta = moreParams.get("ui.dataTables.apps.init"); + Assert.assertTrue(appsTableColumnsMeta.indexOf("natural") != -1); } @Test public void testNodesPage() {