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
(cherry picked from commit 9f77ccad73
)
Conflicts:
hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/TaskPage.java
hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/TestAHSWebApp.java
hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-common/src/main/java/org/apache/hadoop/yarn/server/webapp/WebPageUtils.java
This commit is contained in:
parent
1ae8a8342e
commit
6a30d93aa4
|
@ -43,7 +43,7 @@ public class TasksPage extends AppView {
|
||||||
.append(", bProcessing: true")
|
.append(", bProcessing: true")
|
||||||
|
|
||||||
.append("\n, aoColumnDefs: [\n")
|
.append("\n, aoColumnDefs: [\n")
|
||||||
.append("{'sType':'string', 'aTargets': [0]")
|
.append("{'sType':'natural', 'aTargets': [0]")
|
||||||
.append(", 'mRender': parseHadoopID }")
|
.append(", 'mRender': parseHadoopID }")
|
||||||
|
|
||||||
.append("\n, {'sType':'numeric', bSearchable:false, 'aTargets': [1]")
|
.append("\n, {'sType':'numeric', bSearchable:false, 'aTargets': [1]")
|
||||||
|
|
|
@ -39,6 +39,10 @@ Release 2.7.3 - UNRELEASED
|
||||||
|
|
||||||
YARN-4398. Remove unnecessary synchronization in RMStateStore. (Ning Ding via jianhe)
|
YARN-4398. Remove unnecessary synchronization in RMStateStore. (Ning Ding via jianhe)
|
||||||
|
|
||||||
|
YARN-3840. Resource Manager web ui issue when sorting application by id
|
||||||
|
(with application having id > 9999) (Mohammad Shahid Khan & Varun Saxena
|
||||||
|
via jianhe)
|
||||||
|
|
||||||
Release 2.7.2 - UNRELEASED
|
Release 2.7.2 - UNRELEASED
|
||||||
|
|
||||||
INCOMPATIBLE CHANGES
|
INCOMPATIBLE CHANGES
|
||||||
|
|
|
@ -65,14 +65,14 @@ public class JQueryUI extends HtmlBlock {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void render(Block html) {
|
protected void render(Block html) {
|
||||||
html.
|
html.link(root_url("static/jquery/themes-1.9.1/base/jquery-ui.css"))
|
||||||
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"))
|
||||||
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-1.8.2.min.js")).
|
.script(root_url("static/jquery/jquery-ui-1.9.1.custom.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/dt-1.9.4/js/jquery.dataTables.min.js")).
|
.script(root_url("static/yarn.dt.plugins.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; }",
|
.style("#jsnotice { padding: 0.2em; text-align: center; }",
|
||||||
".ui-progressbar { height: 1em; min-width: 5em }"); // required
|
".ui-progressbar { height: 1em; min-width: 5em }"); // required
|
||||||
|
|
||||||
List<String> list = Lists.newArrayList();
|
List<String> list = Lists.newArrayList();
|
||||||
|
@ -82,9 +82,8 @@ public class JQueryUI extends HtmlBlock {
|
||||||
initProgressBars(list);
|
initProgressBars(list);
|
||||||
|
|
||||||
if (!list.isEmpty()) {
|
if (!list.isEmpty()) {
|
||||||
html.
|
html.script().$type("text/javascript")._("$(function() {")
|
||||||
script().$type("text/javascript").
|
._(list.toArray())._("});")._();
|
||||||
_("$(function() {")._(list.toArray())._("});")._();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
|
||||||
|
}());
|
||||||
|
|
|
@ -53,7 +53,7 @@ public class AppAttemptPage extends AHSView {
|
||||||
|
|
||||||
protected String getContainersTableColumnDefs() {
|
protected String getContainersTableColumnDefs() {
|
||||||
StringBuilder sb = new StringBuilder();
|
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();
|
.append(", 'mRender': parseHadoopID }]").toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,7 @@ public class AppPage extends AHSView {
|
||||||
|
|
||||||
protected String getAttemptsTableColumnDefs() {
|
protected String getAttemptsTableColumnDefs() {
|
||||||
StringBuilder sb = new StringBuilder();
|
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(", 'mRender': parseHadoopID }")
|
||||||
|
|
||||||
.append("\n, {'sType':'numeric', 'aTargets': [1]")
|
.append("\n, {'sType':'numeric', 'aTargets': [1]")
|
||||||
|
|
|
@ -21,7 +21,7 @@ package org.apache.hadoop.yarn.server.applicationhistoryservice.webapp;
|
||||||
import static org.apache.hadoop.yarn.webapp.Params.TITLE;
|
import static org.apache.hadoop.yarn.webapp.Params.TITLE;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
import org.junit.Assert;
|
import java.util.Map;
|
||||||
import org.apache.hadoop.conf.Configuration;
|
import org.apache.hadoop.conf.Configuration;
|
||||||
import org.apache.hadoop.yarn.api.ApplicationBaseProtocol;
|
import org.apache.hadoop.yarn.api.ApplicationBaseProtocol;
|
||||||
import org.apache.hadoop.yarn.api.records.ApplicationAttemptId;
|
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.util.StringHelper;
|
||||||
import org.apache.hadoop.yarn.webapp.YarnWebParams;
|
import org.apache.hadoop.yarn.webapp.YarnWebParams;
|
||||||
import org.apache.hadoop.yarn.webapp.test.WebAppTests;
|
import org.apache.hadoop.yarn.webapp.test.WebAppTests;
|
||||||
|
import org.junit.Assert;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
@ -87,6 +88,21 @@ public class TestAHSWebApp extends ApplicationHistoryStoreTestUtils {
|
||||||
WebAppTests.flushOutput(injector);
|
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<String, String> moreParams =
|
||||||
|
ahsViewInstance.context().requestContext().moreParams();
|
||||||
|
String appTableColumnsMeta = moreParams.get("ui.dataTables.apps.init");
|
||||||
|
Assert.assertTrue(appTableColumnsMeta.indexOf("natural") != -1);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAppPage() throws Exception {
|
public void testAppPage() throws Exception {
|
||||||
Injector injector =
|
Injector injector =
|
||||||
|
@ -103,6 +119,22 @@ public class TestAHSWebApp extends ApplicationHistoryStoreTestUtils {
|
||||||
WebAppTests.flushOutput(injector);
|
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<String, String> moreParams =
|
||||||
|
appPageInstance.context().requestContext().moreParams();
|
||||||
|
String attemptsTableColumnsMeta =
|
||||||
|
moreParams.get("ui.dataTables.attempts.init");
|
||||||
|
Assert.assertTrue(attemptsTableColumnsMeta.indexOf("natural") != -1);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAppAttemptPage() throws Exception {
|
public void testAppAttemptPage() throws Exception {
|
||||||
Injector injector =
|
Injector injector =
|
||||||
|
@ -121,6 +153,21 @@ public class TestAHSWebApp extends ApplicationHistoryStoreTestUtils {
|
||||||
WebAppTests.flushOutput(injector);
|
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<String, String> moreParams =
|
||||||
|
appAttemptPageInstance.context().requestContext().moreParams();
|
||||||
|
String tableColumnsMeta = moreParams.get("ui.dataTables.containers.init");
|
||||||
|
Assert.assertTrue(tableColumnsMeta.indexOf("natural") != -1);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testContainerPage() throws Exception {
|
public void testContainerPage() throws Exception {
|
||||||
Injector injector =
|
Injector injector =
|
||||||
|
@ -181,5 +228,4 @@ public class TestAHSWebApp extends ApplicationHistoryStoreTestUtils {
|
||||||
return store;
|
return store;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,9 +42,8 @@ public class WebPageUtils {
|
||||||
|
|
||||||
private static String getAppsTableColumnDefs(boolean isFairSchedulerPage) {
|
private static String getAppsTableColumnDefs(boolean isFairSchedulerPage) {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
return sb
|
return sb.append("[\n")
|
||||||
.append("[\n")
|
.append("{'sType':'natural', 'aTargets': [0]")
|
||||||
.append("{'sType':'string', 'aTargets': [0]")
|
|
||||||
.append(", 'mRender': parseHadoopID }")
|
.append(", 'mRender': parseHadoopID }")
|
||||||
.append("\n, {'sType':'numeric', 'aTargets': " +
|
.append("\n, {'sType':'numeric', 'aTargets': " +
|
||||||
(isFairSchedulerPage ? "[6, 7]": "[5, 6]"))
|
(isFairSchedulerPage ? "[6, 7]": "[5, 6]"))
|
||||||
|
@ -63,7 +62,7 @@ public class WebPageUtils {
|
||||||
|
|
||||||
private static String getAttemptsTableColumnDefs() {
|
private static String getAttemptsTableColumnDefs() {
|
||||||
StringBuilder sb = new StringBuilder();
|
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(", 'mRender': parseHadoopID }")
|
||||||
.append("\n, {'sType':'numeric', 'aTargets': [1]")
|
.append("\n, {'sType':'numeric', 'aTargets': [1]")
|
||||||
.append(", 'mRender': renderHadoopDate }]").toString();
|
.append(", 'mRender': renderHadoopDate }]").toString();
|
||||||
|
@ -79,7 +78,7 @@ public class WebPageUtils {
|
||||||
|
|
||||||
private static String getContainersTableColumnDefs() {
|
private static String getContainersTableColumnDefs() {
|
||||||
StringBuilder sb = new StringBuilder();
|
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();
|
.append(", 'mRender': parseHadoopID }]").toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,14 @@ public class AllApplicationsPage extends NMView {
|
||||||
// Sort by id upon page load
|
// Sort by id upon page load
|
||||||
append(", aaSorting: [[0, 'asc']]").
|
append(", aaSorting: [[0, 'asc']]").
|
||||||
// applicationid, applicationstate
|
// 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
|
@Override
|
||||||
|
|
|
@ -52,9 +52,15 @@ public class AllContainersPage extends NMView {
|
||||||
private String containersTableInit() {
|
private String containersTableInit() {
|
||||||
return tableInit().
|
return tableInit().
|
||||||
// containerid, containerid, log-url
|
// 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
|
@Override
|
||||||
protected Class<? extends SubView> content() {
|
protected Class<? extends SubView> content() {
|
||||||
return AllContainersBlock.class;
|
return AllContainersBlock.class;
|
||||||
|
|
|
@ -28,6 +28,7 @@ import static org.mockito.Mockito.when;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
import org.apache.hadoop.conf.Configuration;
|
import org.apache.hadoop.conf.Configuration;
|
||||||
|
@ -119,6 +120,10 @@ public class TestRMWebApp {
|
||||||
YarnApplicationState.RUNNING.toString()));
|
YarnApplicationState.RUNNING.toString()));
|
||||||
rmViewInstance.render();
|
rmViewInstance.render();
|
||||||
WebAppTests.flushOutput(injector);
|
WebAppTests.flushOutput(injector);
|
||||||
|
Map<String, String> moreParams =
|
||||||
|
rmViewInstance.context().requestContext().moreParams();
|
||||||
|
String appsTableColumnsMeta = moreParams.get("ui.dataTables.apps.init");
|
||||||
|
Assert.assertTrue(appsTableColumnsMeta.indexOf("natural") != -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test public void testNodesPage() {
|
@Test public void testNodesPage() {
|
||||||
|
|
Loading…
Reference in New Issue