You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by at...@apache.org on 2017/04/20 14:22:38 UTC

ambari git commit: AMBARI-19881. Ambari Web UI is unusably irresponsive on a 1000-node perf cluster after adding AMS (restart indicator loading is too heavy). (atkach)

Repository: ambari
Updated Branches:
  refs/heads/branch-2.4 c8b164a75 -> 3f4323ac0


AMBARI-19881. Ambari Web UI is unusably irresponsive on a 1000-node perf cluster after adding AMS (restart indicator loading is too heavy). (atkach)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/3f4323ac
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/3f4323ac
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/3f4323ac

Branch: refs/heads/branch-2.4
Commit: 3f4323ac0083385d4ebcde8ce1d7974b0728aabc
Parents: c8b164a
Author: Yusaku Sako <yu...@hortonworks.com>
Authored: Mon Feb 6 23:36:32 2017 +0200
Committer: Andrii Tkach <at...@apache.org>
Committed: Thu Apr 20 17:22:20 2017 +0300

----------------------------------------------------------------------
 ambari-web/app/controllers/main/service.js      |  2 +-
 .../app/mappers/component_config_mapper.js      | 58 ++++----------------
 .../app/mappers/components_state_mapper.js      |  5 +-
 ambari-web/app/mappers/server_data_mapper.js    |  1 +
 ambari-web/app/models/client_component.js       |  1 +
 ambari-web/app/models/host_component.js         | 17 +++++-
 ambari-web/app/models/service.js                | 21 ++++---
 ambari-web/app/views/main/service/menu.js       |  4 +-
 .../test/controllers/main/service_test.js       | 31 +++--------
 ambari-web/test/models/service_test.js          | 27 +++++----
 10 files changed, 72 insertions(+), 95 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/3f4323ac/ambari-web/app/controllers/main/service.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/service.js b/ambari-web/app/controllers/main/service.js
index 201bace..ff6b945 100644
--- a/ambari-web/app/controllers/main/service.js
+++ b/ambari-web/app/controllers/main/service.js
@@ -307,7 +307,7 @@ App.MainServiceController = Em.ArrayController.extend({
       return App.showConfirmationPopup(function () {
             self.restartHostComponents();
           }, Em.I18n.t('services.service.refreshAll.confirmMsg').format(
-              App.HostComponent.find().filterProperty('staleConfigs').mapProperty('service.displayName').uniq().join(', ')),
+              App.Service.find().filterProperty('isRestartRequired').mapProperty('displayName').uniq().join(', ')),
           null,
           null,
           Em.I18n.t('services.service.restartAll.confirmButton')

http://git-wip-us.apache.org/repos/asf/ambari/blob/3f4323ac/ambari-web/app/mappers/component_config_mapper.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mappers/component_config_mapper.js b/ambari-web/app/mappers/component_config_mapper.js
index 866f811..c1568e0 100644
--- a/ambari-web/app/mappers/component_config_mapper.js
+++ b/ambari-web/app/mappers/component_config_mapper.js
@@ -36,54 +36,20 @@ App.componentConfigMapper = App.QuickDataMapper.create({
   },
   map: function (json) {
     console.time('App.componentConfigMapper execution time');
-    var hostComponents = [];
-    var newHostComponentsMap = {};
-    var cacheServices = App.cache['services'];
-    var currentServiceComponentsMap = this.buildServiceComponentMap(cacheServices);
-    var mapConfig = this.get('config');
-    // We do not want to parse JSON if there is no need to
-    var hostComponentJsonMap = {};
-    var hostComponentJsonIds = [];
+    var staleConfigHostsMap = App.cache.staleConfigsComponentHosts;
 
-    if (json.items.length > 0 || this.get('model').find().someProperty('staleConfigs', true)) {
-      json.items.forEach(function (item) {
-        item.host_components.forEach(function (host_component) {
-          host_component.id = host_component.HostRoles.component_name + '_' + host_component.HostRoles.host_name;
-          hostComponentJsonIds.push(host_component.id);
-          hostComponentJsonMap[host_component.id] = host_component;
-        });
-      });
-      this.get('model').find().forEach(function (hostComponent) {
-        var id = hostComponent.get('id');
-        var hostComponentJson = hostComponentJsonMap[id];
-        var currentStaleConfigsState = Boolean(hostComponentJson);
-        var stateChanged = hostComponent.get('staleConfigs') !== currentStaleConfigsState;
-
-        if (stateChanged) {
-          hostComponent.set('staleConfigs', currentStaleConfigsState);
-        }
-        //delete loaded host-components, so only new ones left
-        delete hostComponentJsonMap[id];
-      });
-      hostComponentJsonIds.forEach(function (hcId) {
-        var newHostComponent = hostComponentJsonMap[hcId];
-        if (newHostComponent) {
-          var serviceName = newHostComponent.HostRoles.service_name;
-          hostComponents.push(this.parseIt(newHostComponent, mapConfig));
-          if (!newHostComponentsMap[serviceName]) {
-            newHostComponentsMap[serviceName] = [];
-          }
-          if (currentServiceComponentsMap[serviceName] && !currentServiceComponentsMap[serviceName][newHostComponent.id]) {
-            newHostComponentsMap[serviceName].push(newHostComponent.id);
-          }
-        }
-      }, this);
-      if (hostComponents.length > 0) {
-        App.store.commit();
-        App.store.loadMany(this.get('model'), hostComponents);
-        this.addNewHostComponents(newHostComponentsMap, cacheServices);
+    json.items.forEach(function(item) {
+      var componentName = item.ServiceComponentInfo.component_name;
+      var hosts = item.host_components.mapProperty('HostRoles.host_name') || [];
+      staleConfigHostsMap[componentName] = hosts;
+      if (App.HostComponent.isMaster(componentName)) {
+        App.MasterComponent.find(componentName).set('staleConfigHosts', hosts);
+      } else if (App.HostComponent.isSlave(componentName)) {
+        App.SlaveComponent.find(componentName).set('staleConfigHosts', hosts);
+      } else if (App.HostComponent.isClient(componentName)) {
+        App.ClientComponent.find(componentName).set('staleConfigHosts', hosts);
       }
-    }
+    });
     console.timeEnd('App.componentConfigMapper execution time');
   },
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/3f4323ac/ambari-web/app/mappers/components_state_mapper.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mappers/components_state_mapper.js b/ambari-web/app/mappers/components_state_mapper.js
index b86aee5..89d5af2 100644
--- a/ambari-web/app/mappers/components_state_mapper.js
+++ b/ambari-web/app/mappers/components_state_mapper.js
@@ -36,7 +36,8 @@ App.componentsStateMapper = App.QuickDataMapper.create({
     unknown_count: 'ServiceComponentInfo.unknown_count',
     started_count: 'ServiceComponentInfo.started_count',
     total_count: 'ServiceComponentInfo.total_count',
-    host_names: 'host_names'
+    host_names: 'host_names',
+    stale_config_hosts: 'stale_config_hosts'
   },
 
   slaveModel: App.SlaveComponent,
@@ -171,6 +172,7 @@ App.componentsStateMapper = App.QuickDataMapper.create({
     var slaves = [];
     var masters = [];
     var hasNewComponents = false;
+    var staleConfigHostsMap = App.cache.staleConfigsComponentHosts;
 
     if (json.items) {
       if (!App.isEmptyObject(Em.getWithDefault(App, 'cache.services', {}))) {
@@ -184,6 +186,7 @@ App.componentsStateMapper = App.QuickDataMapper.create({
         var extendedModel = this.getExtendedModel(item.ServiceComponentInfo.service_name);
         var cacheService = App.cache['services'].findProperty('ServiceInfo.service_name', item.ServiceComponentInfo.service_name);
 
+        item.stale_config_hosts = staleConfigHostsMap[item.ServiceComponentInfo.component_name] || [];
         if (item.ServiceComponentInfo.category === 'CLIENT') {
           item.host_names = item.host_components.mapProperty('HostRoles.host_name');
           clients.push(this.parseIt(item, this.clientMap));

http://git-wip-us.apache.org/repos/asf/ambari/blob/3f4323ac/ambari-web/app/mappers/server_data_mapper.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mappers/server_data_mapper.js b/ambari-web/app/mappers/server_data_mapper.js
index da25212..a99d8ae 100644
--- a/ambari-web/app/mappers/server_data_mapper.js
+++ b/ambari-web/app/mappers/server_data_mapper.js
@@ -26,6 +26,7 @@ App.cache = {
   'previousHostStatuses': {},
   'previousComponentStatuses': {},
   'previousComponentPassiveStates': {},
+  'staleConfigsComponentHosts': {},
   'services': [],
   'currentConfigVersions': {}
 };

http://git-wip-us.apache.org/repos/asf/ambari/blob/3f4323ac/ambari-web/app/models/client_component.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models/client_component.js b/ambari-web/app/models/client_component.js
index 19ef7ce..dc200b0 100644
--- a/ambari-web/app/models/client_component.js
+++ b/ambari-web/app/models/client_component.js
@@ -31,6 +31,7 @@ App.ClientComponent = DS.Model.extend({
   totalCount: DS.attr('number'),
   stackInfo: DS.belongsTo('App.StackServiceComponent'),
   hostNames: DS.attr('array'),
+  staleConfigHosts: DS.attr('array'),
 
   /**
    * Determines if component may be deleted

http://git-wip-us.apache.org/repos/asf/ambari/blob/3f4323ac/ambari-web/app/models/host_component.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models/host_component.js b/ambari-web/app/models/host_component.js
index c6b8264..94d09ea 100644
--- a/ambari-web/app/models/host_component.js
+++ b/ambari-web/app/models/host_component.js
@@ -51,7 +51,7 @@ App.HostComponent = DS.Model.extend({
    * @returns {bool}
    */
   isClient: function () {
-    return App.get('components.clients').contains(this.get('componentName'));
+    return App.HostComponent.isClient(this.get('componentName'));
   }.property('componentName'),
   /**
    * Determine if component is running now
@@ -73,7 +73,7 @@ App.HostComponent = DS.Model.extend({
    * @returns {bool}
    */
   isMaster: function () {
-    return App.get('components.masters').contains(this.get('componentName'));
+    return App.HostComponent.isMaster(this.get('componentName'));
   }.property('componentName', 'App.components.masters'),
 
   /**
@@ -81,7 +81,7 @@ App.HostComponent = DS.Model.extend({
    * @returns {bool}
    */
   isSlave: function () {
-    return App.get('components.slaves').contains(this.get('componentName'));
+    return App.HostComponent.isSlave(this.get('componentName'));
   }.property('componentName'),
   /**
    * Only certain components can be deleted.
@@ -164,6 +164,17 @@ App.HostComponent = DS.Model.extend({
 
 App.HostComponent.FIXTURES = [];
 
+App.HostComponent.isClient = function(componentName) {
+  return App.get('components.clients').contains(componentName);
+};
+
+App.HostComponent.isMaster = function(componentName) {
+  return App.get('components.masters').contains(componentName);
+};
+
+App.HostComponent.isSlave = function(componentName) {
+  return App.get('components.slaves').contains(componentName);
+};
 
 /**
  * get particular counter of host-component by name

http://git-wip-us.apache.org/repos/asf/ambari/blob/3f4323ac/ambari-web/app/models/service.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models/service.js b/ambari-web/app/models/service.js
index c648e93..76e4437 100644
--- a/ambari-web/app/models/service.js
+++ b/ambari-web/app/models/service.js
@@ -108,18 +108,23 @@ App.Service = DS.Model.extend({
    * actual_configs, then a restart is required.
    */
   isRestartRequired: function () {
-    var rhc = this.get('hostComponents').filterProperty('staleConfigs', true);
+    var serviceComponents = this.get('clientComponents').toArray()
+      .concat(this.get('slaveComponents').toArray())
+      .concat(this.get('masterComponents').toArray());
     var hc = {};
 
-    rhc.forEach(function(_rhc) {
-      var hostName = _rhc.get('hostName');
-      if (!hc[hostName]) {
-        hc[hostName] = [];
-      }
-      hc[hostName].push(_rhc.get('displayName'));
+    serviceComponents.forEach(function(component) {
+      var displayName = component.get('displayName');
+      component.get('staleConfigHosts').forEach(function(hostName) {
+        if (!hc[hostName]) {
+          hc[hostName] = [];
+        }
+        hc[hostName].push(displayName);
+      });
     });
+
     this.set('restartRequiredHostsAndComponents', hc);
-    return (rhc.length > 0);
+    return (serviceComponents.filterProperty('staleConfigHosts.length').length > 0);
   }.property('serviceName'),
   
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/3f4323ac/ambari-web/app/views/main/service/menu.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/service/menu.js b/ambari-web/app/views/main/service/menu.js
index 2c9ac5c..eeebc6e 100644
--- a/ambari-web/app/views/main/service/menu.js
+++ b/ambari-web/app/views/main/service/menu.js
@@ -63,7 +63,7 @@ App.MainServiceMenuView = Em.CollectionView.extend({
     templateName:require('templates/main/service/menu_item'),
     restartRequiredMessage: null,
 
-    shouldBeRestarted: Em.computed.someBy('content.hostComponents', 'staleConfigs', true),
+    shouldBeRestarted: Em.computed.equal('content.isRestartRequired'),
 
     active:function () {
       return this.get('content.id') == this.get('parentView.activeServiceId') ? 'active' : '';
@@ -164,7 +164,7 @@ App.TopNavServiceMenuView = Em.CollectionView.extend({
     templateName:require('templates/main/service/menu_item'),
     restartRequiredMessage: null,
 
-    shouldBeRestarted: Em.computed.someBy('content.hostComponents', 'staleConfigs', true),
+    shouldBeRestarted: Em.computed.equal('content.isRestartRequired'),
 
     active:function () {
       return this.get('content.id') == this.get('parentView.activeServiceId') ? 'active' : '';

http://git-wip-us.apache.org/repos/asf/ambari/blob/3f4323ac/ambari-web/test/controllers/main/service_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/controllers/main/service_test.js b/ambari-web/test/controllers/main/service_test.js
index 7b6981b..4a3f00c 100644
--- a/ambari-web/test/controllers/main/service_test.js
+++ b/ambari-web/test/controllers/main/service_test.js
@@ -373,41 +373,26 @@ describe('App.MainServiceController', function () {
     beforeEach(function () {
       sinon.spy(App, 'showConfirmationPopup');
       sinon.spy(mainServiceController, 'restartHostComponents');
-      sinon.stub(App.HostComponent, 'find', function() {
+      sinon.stub(App.Service, 'find', function() {
         return [
           Em.Object.create({
-            componentName: 'componentName1',
-            hostName: 'hostName1',
-            service: {
-              serviceName: 'serviceName1',
-              displayName: 'displayName1'
-            },
-            staleConfigs: true
+            displayName: 'displayName1',
+            isRestartRequired: true
           }),
           Em.Object.create({
-            componentName: 'componentName2',
-            hostName: 'hostName2',
-            service: {
-              serviceName: 'serviceName2',
-              displayName: 'displayName2'
-            },
-            staleConfigs: true
+            displayName: 'displayName2',
+            isRestartRequired: true
           }),
           Em.Object.create({
-            componentName: 'componentName3',
-            hostName: 'hostName3',
-            service: {
-              serviceName: 'serviceName3',
-              displayName: 'displayName3'
-            },
-            staleConfigs: false
+            displayName: 'displayName3',
+            isRestartRequired: false
           })
         ];
       });
     });
 
     afterEach(function () {
-      App.HostComponent.find.restore();
+      App.Service.find.restore();
       App.showConfirmationPopup.restore();
       mainServiceController.restartHostComponents.restore();
     });

http://git-wip-us.apache.org/repos/asf/ambari/blob/3f4323ac/ambari-web/test/models/service_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/models/service_test.js b/ambari-web/test/models/service_test.js
index e527e1e..5bd0cf8 100644
--- a/ambari-web/test/models/service_test.js
+++ b/ambari-web/test/models/service_test.js
@@ -133,20 +133,25 @@ describe('App.Service', function () {
     beforeEach(function () {
       service.reopen({
         serviceName: 'HDFS',
-        hostComponents: []
+        clientComponents: [],
+        slaveComponents: [],
+        masterComponents: []
       });
     });
-    hostComponentsDataFalse.forEach(function (item) {
-      it('should be false', function () {
-        service.set('hostComponents', item);
-        expect(service.get('isRestartRequired')).to.be.false;
-      });
+    it('should be false when no component has stale configs', function () {
+      expect(service.get('isRestartRequired')).to.be.false;
     });
-    hostComponentsDataTrue.forEach(function (item) {
-      it('should be true', function () {
-        service.set('hostComponents', item);
-        expect(service.get('isRestartRequired')).to.be.true;
-      });
+    it('should be true when clientComponents has stale configs', function () {
+      service.set('clientComponents', [Em.Object.create({staleConfigHosts: ['host1']})]);
+      expect(service.get('isRestartRequired')).to.be.true;
+    });
+    it('should be true when slaveComponents has stale configs', function () {
+      service.set('slaveComponents', [Em.Object.create({staleConfigHosts: ['host1']})]);
+      expect(service.get('isRestartRequired')).to.be.true;
+    });
+    it('should be true when masterComponents has stale configs', function () {
+      service.set('masterComponents', [Em.Object.create({staleConfigHosts: ['host1']})]);
+      expect(service.get('isRestartRequired')).to.be.true;
     });
   });