Repository: ambari
Updated Branches:
  refs/heads/trunk e7726e447 -> 99cac719d


AMBARI-12469 Ambari Web Scalability: performance analysis. (atkach)


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

Branch: refs/heads/trunk
Commit: 99cac719dbcbb97f35b58be730cc3f856156f13a
Parents: e7726e4
Author: Andrii Tkach <atk...@hortonworks.com>
Authored: Tue Jul 21 19:39:11 2015 +0300
Committer: Andrii Tkach <atk...@hortonworks.com>
Committed: Tue Jul 21 19:39:11 2015 +0300

----------------------------------------------------------------------
 ambari-web/app/controllers/main/host.js         | 13 +--
 ambari-web/app/controllers/main/host/details.js |  1 +
 .../app/mappers/component_config_mapper.js      |  1 -
 ambari-web/app/mappers/hosts_mapper.js          | 42 +++++++---
 ambari-web/app/mappers/server_data_mapper.js    | 36 --------
 .../app/mappers/service_metrics_mapper.js       | 87 ++++++++++++--------
 .../mixins/common/table_server_view_mixin.js    |  8 +-
 ambari-web/app/models/host.js                   | 51 +++++-------
 ambari-web/app/models/service.js                |  8 +-
 ambari-web/app/models/service/hbase.js          |  4 +-
 ambari-web/app/models/service/hdfs.js           | 12 +--
 ambari-web/app/models/service/mapreduce2.js     |  4 +-
 ambari-web/app/models/service/yarn.js           | 12 +--
 .../main/dashboard/widgets/flume_agent_live.js  | 24 ++++--
 ambari-web/app/views/main/host.js               | 15 ++--
 .../test/mappers/server_data_mapper_test.js     |  6 +-
 ambari-web/test/mappers/service_mapper_test.js  | 12 +++
 ambari-web/test/models/host_test.js             |  4 +-
 ambari-web/test/models/service/hdfs_test.js     | 56 +++++--------
 ambari-web/test/models/service_test.js          | 16 ++--
 20 files changed, 185 insertions(+), 227 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/99cac719/ambari-web/app/controllers/main/host.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/host.js 
b/ambari-web/app/controllers/main/host.js
index a798f0b..9d8347c 100644
--- a/ambari-web/app/controllers/main/host.js
+++ b/ambari-web/app/controllers/main/host.js
@@ -54,18 +54,7 @@ App.MainHostController = 
Em.ArrayController.extend(App.TableServerMixin, {
     return installedComponents;
   }.property('App.router.clusterController.isLoaded'),
 
-  content: [],
-
-  requestedObserver: function() {
-    Em.run.once(this, 'setContentOnce');
-  }.observes('dataSource.@each.isRequested'),
-
-  setContentOnce: function() {
-    var self = this;
-    Em.run.next(function() {
-      self.set('content', 
self.get('dataSource').filterProperty('isRequested'));
-    });
-  },
+  content: App.Host.find(),
 
   allHostStackVersions: App.HostStackVersion.find(),
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/99cac719/ambari-web/app/controllers/main/host/details.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/host/details.js 
b/ambari-web/app/controllers/main/host/details.js
index c3a17ca..aaca4f0 100644
--- a/ambari-web/app/controllers/main/host/details.js
+++ b/ambari-web/app/controllers/main/host/details.js
@@ -382,6 +382,7 @@ App.MainHostDetailsController = Em.Controller.extend({
    */
   removeHostComponentModel: function(componentName, hostName) {
     var component = App.HostComponent.find().filterProperty('componentName', 
componentName).findProperty('hostName', hostName);
+    App.cache['services'].findProperty('ServiceInfo.service_name', 
component.get('serviceName')).host_components.without(component.get('id'));
     App.serviceMapper.deleteRecord(component);
   },
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/99cac719/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 dddb79a..334fd57 100644
--- a/ambari-web/app/mappers/component_config_mapper.js
+++ b/ambari-web/app/mappers/component_config_mapper.js
@@ -42,7 +42,6 @@ App.componentConfigMapper = App.QuickDataMapper.create({
     // We do not want to parse JSON if there is no need to
     var hostComponentJsonMap = {};
     var hostComponentJsonIds = [];
-    var hostComponentLoaded = {};
 
     if (json.items.length > 0 || 
this.get('model').find().someProperty('staleConfigs', true)) {
       json.items.forEach(function (item) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/99cac719/ambari-web/app/mappers/hosts_mapper.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mappers/hosts_mapper.js 
b/ambari-web/app/mappers/hosts_mapper.js
index 5ab249e..cd05499 100644
--- a/ambari-web/app/mappers/hosts_mapper.js
+++ b/ambari-web/app/mappers/hosts_mapper.js
@@ -92,27 +92,45 @@ App.hostsMapper = App.QuickDataMapper.create({
       var selectedHosts = App.db.getSelectedHosts('mainHostController');
       var stackUpgradeSupport = App.get('supports.stackUpgrade');
       var clusterName = App.get('clusterName');
+      var advancedHostComponents = [];
 
       json.items.forEach(function (item, index) {
+        var notStartedComponents = [];
+        var componentsInPassiveState = [];
+        var componentsWithStaleConfigs = [];
+
         item.host_components = item.host_components || [];
         item.host_components.forEach(function (host_component) {
-          host_component.id = host_component.HostRoles.component_name + "_" + 
item.Hosts.host_name;
+          var id = host_component.HostRoles.component_name + "_" + 
item.Hosts.host_name;
           var component = this.parseIt(host_component, 
this.hostComponentConfig);
           var serviceName = host_component.HostRoles.service_name;
 
-          component.id = host_component.HostRoles.component_name + "_" + 
item.Hosts.host_name;
+          host_component.id = id;
+          component.id = id;
           component.host_id = item.Hosts.host_name;
           component.host_name = item.Hosts.host_name;
           components.push(component);
-          componentsIdMap[component.id] = component;
+          componentsIdMap[id] = component;
           if (!newHostComponentsMap[serviceName]) {
             newHostComponentsMap[serviceName] = [];
           }
           if (!currentServiceComponentsMap[serviceName]) {
             currentServiceComponentsMap[serviceName] = [];
           }
-          if (!currentServiceComponentsMap[serviceName][component.id]) {
-            newHostComponentsMap[serviceName].push(component.id);
+          if (!currentServiceComponentsMap[serviceName][id]) {
+            newHostComponentsMap[serviceName].push(id);
+          }
+          if 
(App.serviceMetricsMapper.get('ADVANCED_COMPONENTS').contains(host_component.HostRoles.component_name))
 {
+            advancedHostComponents.push(id);
+          }
+          if (component.work_status !== App.HostComponentStatus.started) {
+            notStartedComponents.push(id);
+          }
+          if (component.stale_configs) {
+            componentsWithStaleConfigs.push(id);
+          }
+          if (component.passive_state !== 'OFF') {
+            componentsInPassiveState.push(id);
           }
         }, this);
 
@@ -145,6 +163,9 @@ App.hostsMapper = App.QuickDataMapper.create({
         var parsedItem = this.parseIt(item, this.config);
         parsedItem.is_requested = true;
         parsedItem.selected = selectedHosts.contains(parsedItem.host_name);
+        parsedItem.not_started_components = notStartedComponents;
+        parsedItem.components_in_passive_state = componentsInPassiveState;
+        parsedItem.components_with_stale_configs = componentsWithStaleConfigs;
 
         hostIds[item.Hosts.host_name] = parsedItem;
 
@@ -156,20 +177,15 @@ App.hostsMapper = App.QuickDataMapper.create({
       }
 
 
-      App.Host.find().filterProperty('isRequested', true)
-        .filter(function(item) {
-          return !hostIds[item.get('hostName')];
-        })
-        .setEach('isRequested', false);
-
-      
App.HostComponent.find().filterProperty('isMaster').forEach(function(component) 
{
-        if (componentsIdMap[component.get('id')]) 
componentsIdMap[component.get('id')].display_name_advanced = 
component.get('displayNameAdvanced');
+      advancedHostComponents.forEach(function(id) {
+        if (componentsIdMap[id]) componentsIdMap[id].display_name_advanced = 
App.HostComponent.find(id).get('displayNameAdvanced');
       });
       App.store.commit();
       if (stackUpgradeSupport) {
         App.store.loadMany(App.HostStackVersion, stackVersions);
       }
       App.store.loadMany(App.HostComponent, components);
+      App.Host.find().clear();
       App.store.loadMany(App.Host, hostsWithFullInfo);
       var itemTotal = parseInt(json.itemTotal);
       if (!isNaN(itemTotal)) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/99cac719/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 239ba0f..a87cf78 100644
--- a/ambari-web/app/mappers/server_data_mapper.js
+++ b/ambari-web/app/mappers/server_data_mapper.js
@@ -110,7 +110,6 @@ App.QuickDataMapper = App.ServerDataMapper.extend({
   getJsonProperty: function (json, path) {
     var pathArr = path.split('.');
     var current = json;
-    pathArr = this.filterDotted(pathArr);
     while (pathArr.length && current) {
       if (pathArr[0].substr(-1) == ']') {
         var index = parseInt(pathArr[0].substr(-2, 1));
@@ -126,29 +125,6 @@ App.QuickDataMapper = App.ServerDataMapper.extend({
     return current;
   },
 
-  filterDotted: function(arr) {
-    var buffer = [];
-    var dottedBuffer = [];
-    var dotted = false;
-    arr.forEach(function(item) {
-      if(/\['|\["/.test(item)) {
-        dottedBuffer.push(item.substr(2, item.length));
-        dotted = true;
-      } else if (dotted && !/\]'|"\]/.test(item)) {
-        dottedBuffer.push(item);
-      } else if (/']|"]/.test(item)) {
-        dottedBuffer.push(item.substr(0, item.length - 2));
-        buffer.push(dottedBuffer.join('.'));
-        dotted = false;
-        dottedBuffer = [];
-      } else {
-        buffer.push(item);
-      }
-    });
-
-    return buffer;
-  },
-
   /**
    * properly delete record from model
    * @param item
@@ -183,17 +159,5 @@ App.QuickDataMapper = App.ServerDataMapper.extend({
       return result;
     }
     return current;
-  },
-
-  calculateState: function (json) {
-//    var stateEqual = (json.desired_status != json.work_status);
-//    if (stateEqual) {
-//      if (json.desired_status == 'STARTED' && json.work_status == 
'INSTALLED') {
-//        json.work_status = 'STARTING';
-//      } else if (json.desired_status == 'INSTALLED' && json.work_status == 
'STARTED') {
-//        json.work_status = 'STOPPING';
-//      }
-//    }
-    return json;
   }
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/99cac719/ambari-web/app/mappers/service_metrics_mapper.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mappers/service_metrics_mapper.js 
b/ambari-web/app/mappers/service_metrics_mapper.js
index b97ec42..78d37eb 100644
--- a/ambari-web/app/mappers/service_metrics_mapper.js
+++ b/ambari-web/app/mappers/service_metrics_mapper.js
@@ -19,7 +19,7 @@ var App = require('app');
 var misc = require('utils/misc');
 var stringUtils = require('utils/string_utils');
 var dateUtils = require('utils/date');
-var previousResponse = [];
+var previousMasterComponentIds = [];
 
 App.serviceMetricsMapper = App.QuickDataMapper.create({
 
@@ -44,6 +44,8 @@ App.serviceMetricsMapper = App.QuickDataMapper.create({
     standby_name_node_id: 'standby_name_node_id',
     standby_name_node2_id: 'standby_name_node2_id',
     journal_nodes: 'journal_nodes',
+    name_node_id: 'name_node_id',
+    sname_node_id: 'sname_node_id',
     metrics_not_available: 'metrics_not_available',
     name_node_start_time: 
'nameNodeComponent.host_components[0].metrics.runtime.StartTime',
     jvm_memory_heap_used: 
'nameNodeComponent.host_components[0].metrics.jvm.HeapMemoryUsed',
@@ -95,14 +97,19 @@ App.serviceMetricsMapper = App.QuickDataMapper.create({
     queue: 'resourceManagerComponent.queue',
     node_managers_started: 'node_managers_started',
     node_managers_installed: 'node_managers_installed',
-    node_managers_total: 'node_managers_total'
+    node_managers_total: 'node_managers_total',
+    app_timeline_server_id: 'app_timeline_server_id',
+    resource_manager_id: 'resource_manager_id',
+    active_resource_manager_id: 'active_resource_manager_id'
   },
   mapReduce2Config: {
-    map_reduce2_clients: 'map_reduce2_clients'
+    map_reduce2_clients: 'map_reduce2_clients',
+    job_history_server_id: 'job_history_server_id'
   },
   hbaseConfig: {
     master_start_time: 
'masterComponent.host_components[0].metrics.hbase.master.MasterStartTime',
     master_active_time: 
'masterComponent.host_components[0].metrics.hbase.master.MasterActiveTime',
+    master_id: 'master_id',
     average_load: 
'masterComponent.host_components[0].metrics.hbase.master.AverageLoad',
     heap_memory_used: 
'masterComponent.host_components[0].metrics.jvm.HeapMemoryUsed',
     heap_memory_max: 
'masterComponent.host_components[0].metrics.jvm.HeapMemoryMax',
@@ -141,20 +148,24 @@ App.serviceMetricsMapper = App.QuickDataMapper.create({
 
   model3: App.HostComponent,
   config3: {
-    id: 'id',
     work_status: 'HostRoles.state',
     passive_state: 'HostRoles.maintenance_state',
-    desired_status: 'HostRoles.desired_state',
     component_name: 'HostRoles.component_name',
     host_id: 'HostRoles.host_name',
     host_name: 'HostRoles.host_name',
     stale_configs: 'HostRoles.stale_configs',
     ha_status: 'HostRoles.ha_state',
     display_name_advanced: 'display_name_advanced',
-    $service_id: 'none', /* will be set outside of parse function */
     admin_state: 'HostRoles.desired_admin_state'
   },
 
+  /**
+   * components which have additional relations and filtered for 
<code>computeAdditionalRelations</code>
+   * @type {Array}
+   * @const
+   */
+  ADVANCED_COMPONENTS: ['SECONDARY_NAMENODE', 'RESOURCEMANAGER', 'NAMENODE', 
'HBASE_MASTER', 'RESOURCEMANAGER'],
+
   map: function (json) {
     console.time('App.serviceMetricsMapper execution time');
     if (json.items) {
@@ -165,14 +176,13 @@ App.serviceMetricsMapper = App.QuickDataMapper.create({
       var previousComponentStatuses = App.cache['previousComponentStatuses'];
       var previousComponentPassiveStates = 
App.cache['previousComponentPassiveStates'];
       var result = [];
+      var advancedHostComponents = [];
+      var hostComponentIdsMap = {};
+
       /**
        * services contains constructed service-components structure from 
components array
        */
-
-      services.forEach(function (service) {
-        service.host_components = [];
-        service.components = [];
-      });
+      services.setEach('components', []);
 
       json.items.forEach(function (component) {
         var serviceName = component.ServiceComponentInfo.service_name;
@@ -181,28 +191,38 @@ App.serviceMetricsMapper = App.QuickDataMapper.create({
           service.components.push(component);
         }
         component.host_components.forEach(function (host_component) {
-          host_component.id = host_component.HostRoles.component_name + "_" + 
host_component.HostRoles.host_name;
+          var id = host_component.HostRoles.component_name + "_" + 
host_component.HostRoles.host_name;
+          hostComponentIdsMap[id] = true;
           previousComponentStatuses[host_component.id] = 
host_component.HostRoles.state;
           previousComponentPassiveStates[host_component.id] = 
host_component.HostRoles.maintenance_state;
           this.config3.ha_status = host_component.HostRoles.component_name == 
"HBASE_MASTER" ?
             'metrics.hbase.master.IsActiveMaster' : 'HostRoles.ha_state';
           var comp = this.parseIt(host_component, this.config3);
+          comp.id = id;
           comp.service_id = serviceName;
           hostComponents.push(comp);
+          if (this.get('ADVANCED_COMPONENTS').contains(comp.component_name)) {
+            advancedHostComponents.push(comp);
+          }
         }, this);
       }, this);
 
-      this.computeAdditionalRelations(hostComponents, services);
+      this.computeAdditionalRelations(advancedHostComponents, services);
       //load master components to model
-      App.HostComponent.find().filterProperty('isMaster').forEach(function 
(hostComponent) {
-        if (hostComponent && !hostComponents.someProperty('id', 
hostComponent.get('id'))) {
-          this.deleteRecord(hostComponent);
+      previousMasterComponentIds.forEach(function (id) {
+        if (!hostComponentIdsMap[id]) {
+          var hostComponent = App.HostComponent.find(id);
+          if (hostComponent.get('isLoaded')) {
+            this.deleteRecord(hostComponent);
+          }
           var serviceCache = services.findProperty('ServiceInfo.service_name', 
hostComponent.get('service.serviceName'));
           if (serviceCache) {
             serviceCache.host_components = 
serviceCache.host_components.without(hostComponent.get('id'));
           }
         }
       }, this);
+      previousMasterComponentIds = hostComponents.mapProperty('id');
+
       App.store.loadMany(this.get('model3'), hostComponents);
 
       //parse service metrics from components
@@ -261,24 +281,6 @@ App.serviceMetricsMapper = App.QuickDataMapper.create({
 
       //load services to model
       App.store.loadMany(this.get('model'), result);
-      /*if (previousResponse.length !== result.length) {
-       App.store.loadMany(this.get('model'), result);
-       } else {
-       result.forEach(function (serviceJson) {
-       var fields = ['passive_state','work_status', 'rand', 'alerts', 
'quick_links', 'host_components', 'tool_tip_content', 'critical_alerts_count'];
-       var service = this.get('model').find(serviceJson.id);
-       var modifiedData = this.getDiscrepancies(serviceJson, 
previousResponse.findProperty('id', serviceJson.id), fields);
-       if (modifiedData.isLoadNeeded) {
-       App.store.load(this.get('model'), serviceJson);
-       } else {
-       for (var property in modifiedData) {
-       service.set(stringUtils.underScoreToCamelCase(property), 
modifiedData[property]);
-       }
-       }
-       }, this)
-       }
-
-       previousResponse = result;*/
     }
     console.timeEnd('App.serviceMetricsMapper execution time');
   },
@@ -447,6 +449,7 @@ App.serviceMetricsMapper = App.QuickDataMapper.create({
         for (var host in liveNodesJson) {
           item.live_data_nodes.push('DATANODE' + '_' + host);
         }
+        item.name_node_id = "NAMENODE" + "_" + 
component.host_components[0].HostRoles.host_name;
       }
       if (component.ServiceComponentInfo && 
component.ServiceComponentInfo.component_name == "JOURNALNODE") {
         if (!item.journal_nodes) {
@@ -454,10 +457,15 @@ App.serviceMetricsMapper = App.QuickDataMapper.create({
         }
         if (component.host_components) {
           component.host_components.forEach(function (hc) {
-            item.journal_nodes.push(hc.HostRoles.host_name);
+            item.journal_nodes.push("JOURNALNODE" + "_" + 
hc.HostRoles.host_name);
           });
         }
       }
+      if (component.ServiceComponentInfo &&
+          component.ServiceComponentInfo.component_name == 
"SECONDARY_NAMENODE" &&
+          component.host_components.length > 0) {
+        item.sname_node_id = "SECONDARY_NAMENODE" + "_" + 
component.host_components[0].HostRoles.host_name;
+      }
     });
     // Map
     var finalJson = this.parseIt(item, finalConfig);
@@ -481,6 +489,9 @@ App.serviceMetricsMapper = App.QuickDataMapper.create({
           var activeRM = 
component.host_components.findProperty('HostRoles.ha_state', 'ACTIVE');
           var activeHostComponentIndex = 
component.host_components.indexOf(activeRM);
           self.setActiveAsFirstHostComponent(component, 
activeHostComponentIndex);
+          if (activeRM) {
+            item.active_resource_manager_id = "RESOURCEMANAGER" + "_" + 
activeRM.HostRoles.host_name;
+          }
         }
 
         if (component.host_components[0].metrics && 
component.host_components[0].metrics.yarn) {
@@ -491,6 +502,10 @@ App.serviceMetricsMapper = App.QuickDataMapper.create({
         }
         // extend config
         finalConfig = jQuery.extend(finalConfig, yarnConfig);
+        item.resource_manager_id = "RESOURCEMANAGER" + "_" + 
component.host_components[0].HostRoles.host_name;
+      }
+      if (component.ServiceComponentInfo && 
component.ServiceComponentInfo.component_name == "APP_TIMELINE_SERVER") {
+        item.app_timeline_server_id = "APP_TIMELINE_SERVER" + "_" + 
component.host_components[0].HostRoles.host_name;
       }
     });
     // Map
@@ -520,6 +535,7 @@ App.serviceMetricsMapper = App.QuickDataMapper.create({
       if (component.ServiceComponentInfo && 
component.ServiceComponentInfo.component_name == "HISTORYSERVER") {
         item.jobHistoryServerComponent = component;
         finalConfig = jQuery.extend(finalConfig, mapReduce2Config);
+        item.job_history_server_id = "HISTORYSERVER" + "_" + 
component.host_components[0].HostRoles.host_name;
       }
     });
     // Map
@@ -552,6 +568,7 @@ App.serviceMetricsMapper = App.QuickDataMapper.create({
             item.regions_in_transition = regionsArray == null ? 0 : 
regionsArray;
           }
         }
+        item.master_id = "HBASE_MASTER" + "_" + 
component.host_components[0].HostRoles.host_name;
       }
     });
     // Map

http://git-wip-us.apache.org/repos/asf/ambari/blob/99cac719/ambari-web/app/mixins/common/table_server_view_mixin.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mixins/common/table_server_view_mixin.js 
b/ambari-web/app/mixins/common/table_server_view_mixin.js
index e46bd2e..75fb545 100644
--- a/ambari-web/app/mixins/common/table_server_view_mixin.js
+++ b/ambari-web/app/mixins/common/table_server_view_mixin.js
@@ -41,12 +41,12 @@ App.TableServerViewMixin = Em.Mixin.create({
   totalCount: function () {
     return this.get('controller.totalCount');
   }.property('controller.totalCount'),
+
   /**
    * data requested from server
    */
-  content: function () {
-    return this.get('controller.content');
-  }.property('controller.content'),
+  contentBinding: 'controller.content',
+
   /**
    * content already filtered on server-side
    */
@@ -57,7 +57,7 @@ App.TableServerViewMixin = Em.Mixin.create({
    * sort and slice recieved content by pagination parameters
    */
   pageContent: function () {
-    var content = this.get('filteredContent');
+    var content = this.get('filteredContent').toArray();
     if (content.length > ((this.get('endIndex') - this.get('startIndex')) + 
1)) {
       content = content.slice(0, (this.get('endIndex') - 
this.get('startIndex')) + 1);
     }

http://git-wip-us.apache.org/repos/asf/ambari/blob/99cac719/ambari-web/app/models/host.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models/host.js b/ambari-web/app/models/host.js
index 1f3f6d4..53e3472 100644
--- a/ambari-web/app/models/host.js
+++ b/ambari-web/app/models/host.js
@@ -25,6 +25,9 @@ App.Host = DS.Model.extend({
   publicHostName: DS.attr('string'),
   cluster: DS.belongsTo('App.Cluster'),
   hostComponents: DS.hasMany('App.HostComponent'),
+  notStartedComponents: DS.hasMany('App.HostComponent'),
+  componentsWithStaleConfigs: DS.hasMany('App.HostComponent'),
+  componentsInPassiveState: DS.hasMany('App.HostComponent'),
   cpu: DS.attr('string'),
   cpuPhysical: DS.attr('string'),
   memory: DS.attr('string'),
@@ -54,10 +57,6 @@ App.Host = DS.Model.extend({
    * Is host checked at the main Hosts page
    */
   selected:DS.attr('boolean'),
-  /**
-   * determine whether host is requested from server
-   */
-  isRequested: DS.attr('boolean'),
 
   currentVersion: function () {
     var current = this.get('stackVersions').findProperty('isCurrent');
@@ -87,27 +86,21 @@ App.Host = DS.Model.extend({
     return 0;
   }.property('memTotal', 'memFree'),
 
-  componentsWithStaleConfigs: function () {
-    return this.get('hostComponents').filterProperty('staleConfigs', true);
-  }.property('hostComponents.@each.staleConfigs'),
 
   /**
-   * Get count of host components with stale configs
-   * @returns {Number}
+   * @type {number}
    */
-  componentsWithStaleConfigsCount: function() {
-    return this.get('componentsWithStaleConfigs').length;
-  }.property('componentsWithStaleConfigs.length'),
+  componentsInPassiveStateCount: function() {
+    return this.get('componentsInPassiveState').length;
+  }.property('componentsInPassiveState.length'),
 
   /**
-   * Get count of host components in passive state
+   * Get count of host components with stale configs
    * @returns {Number}
    */
-  componentsInPassiveStateCount: function() {
-    return this.get('hostComponents').filter(function(component) {
-      return component.get('passiveState') !== 'OFF';
-    }).length;
-  }.property('hostComponents.@each.passiveState'),
+  componentsWithStaleConfigsCount: function() {
+    return this.get('componentsWithStaleConfigs.length');
+  }.property('componentsWithStaleConfigs.length'),
 
   /**
    * Count of mounted on host disks
@@ -250,30 +243,28 @@ App.Host = DS.Model.extend({
    * Contains affected host components names (based on 
<code>healthClass</code>)
    * @returns {String}
    */
-  healthToolTip: function(){
-    var hostComponents = this.get('hostComponents').filter(function(item){
-      return item.get('workStatus') !== App.HostComponentStatus.started;
-    });
+  healthToolTip: function () {
+    var hostComponents = this.get('notStartedComponents');
     var output = '';
     if (this.get('passiveState') != 'OFF') {
       return Em.I18n.t('hosts.host.passive.mode');
     }
-    switch (this.get('healthClass')){
+    switch (this.get('healthClass')) {
       case 'health-status-DEAD-RED':
-        hostComponents = hostComponents.filterProperty('isMaster', true);
+        hostComponents = hostComponents.filterProperty('isMaster');
         output = Em.I18n.t('hosts.host.healthStatus.mastersDown');
-        hostComponents.forEach(function(hc, index){
-          output += (index == (hostComponents.length-1)) ? 
hc.get('displayName') : (hc.get('displayName')+", ");
+        hostComponents.forEach(function (hc, index) {
+          output += (index == (hostComponents.length - 1)) ? 
hc.get('displayName') : (hc.get('displayName') + ", ");
         }, this);
         break;
       case 'health-status-DEAD-YELLOW':
         output = Em.I18n.t('hosts.host.healthStatus.heartBeatNotReceived');
         break;
       case 'health-status-DEAD-ORANGE':
-        hostComponents = hostComponents.filterProperty('isSlave', true);
+        hostComponents = hostComponents.filterProperty('isSlave');
         output = Em.I18n.t('hosts.host.healthStatus.slavesDown');
-        hostComponents.forEach(function(hc, index){
-          output += (index == (hostComponents.length-1)) ? 
hc.get('displayName') : (hc.get('displayName')+", ");
+        hostComponents.forEach(function (hc, index) {
+          output += (index == (hostComponents.length - 1)) ? 
hc.get('displayName') : (hc.get('displayName') + ", ");
         }, this);
         break;
       case 'health-status-LIVE':
@@ -281,7 +272,7 @@ App.Host = DS.Model.extend({
         break;
     }
     return output;
-  
}.property('hostComponents.@each.workStatus','hostComponents.@each.passiveState')
+  }.property('notStartedComponents')
 });
 
 App.Host.FIXTURES = [];

http://git-wip-us.apache.org/repos/asf/ambari/blob/99cac719/ambari-web/app/models/service.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models/service.js b/ambari-web/app/models/service.js
index 08e1662..a255157 100644
--- a/ambari-web/app/models/service.js
+++ b/ambari-web/app/models/service.js
@@ -95,8 +95,9 @@ App.Service = DS.Model.extend({
    * actual_configs, then a restart is required.
    */
   isRestartRequired: function () {
-    var rhc = App.HostComponent.find().filterProperty('service.serviceName', 
this.get('serviceName')).filterProperty('staleConfigs', true);
+    var rhc = this.get('hostComponents').filterProperty('staleConfigs', true);
     var hc = {};
+
     rhc.forEach(function(_rhc) {
       var hostName = _rhc.get('hostName');
       if (!hc[hostName]) {
@@ -105,9 +106,8 @@ App.Service = DS.Model.extend({
       hc[hostName].push(_rhc.get('displayName'));
     });
     this.set('restartRequiredHostsAndComponents', hc);
-    return (rhc.length>0);
-
-  }.property('serviceName', 'hostComponents.@each.staleConfigs'),
+    return (rhc.length > 0);
+  }.property('serviceName'),
   
   /**
    * Contains a map of which hosts and host_components

http://git-wip-us.apache.org/repos/asf/ambari/blob/99cac719/ambari-web/app/models/service/hbase.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models/service/hbase.js 
b/ambari-web/app/models/service/hbase.js
index 5b39771..09378fc 100644
--- a/ambari-web/app/models/service/hbase.js
+++ b/ambari-web/app/models/service/hbase.js
@@ -18,9 +18,7 @@
 var App = require('app');
 
 App.HBaseService = App.Service.extend({
-  master: function () {
-    return this.get('hostComponents').findProperty('componentName', 
'HBASE_MASTER');
-  }.property('hostComponents'),
+  master: DS.belongsTo('App.HostComponent'),
   regionServersStarted: DS.attr('number'),
   regionServersInstalled: DS.attr('number'),
   regionServersTotal: DS.attr('number'),

http://git-wip-us.apache.org/repos/asf/ambari/blob/99cac719/ambari-web/app/models/service/hdfs.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models/service/hdfs.js 
b/ambari-web/app/models/service/hdfs.js
index 3cb1cef..fef47d8 100644
--- a/ambari-web/app/models/service/hdfs.js
+++ b/ambari-web/app/models/service/hdfs.js
@@ -19,12 +19,8 @@ var App = require('app');
 
 App.HDFSService = App.Service.extend({
   version: DS.attr('string'),
-  nameNode: function () {
-    return this.get('hostComponents').findProperty('componentName', 
'NAMENODE');
-  }.property('hostComponents'),
-  snameNode: function () {
-    return this.get('hostComponents').findProperty('componentName', 
'SECONDARY_NAMENODE');
-  }.property('hostComponents'),
+  nameNode: DS.belongsTo('App.HostComponent'),
+  snameNode: DS.belongsTo('App.HostComponent'),
   activeNameNode: DS.belongsTo('App.HostComponent'),
   standbyNameNode: DS.belongsTo('App.HostComponent'),
   standbyNameNode2: DS.belongsTo('App.HostComponent'),
@@ -37,9 +33,7 @@ App.HDFSService = App.Service.extend({
   nfsGatewaysStarted: DS.attr('number'),
   nfsGatewaysInstalled: DS.attr('number'),
   nfsGatewaysTotal: DS.attr('number'),
-  journalNodes: function () {
-    return this.get('hostComponents').filterProperty('componentName', 
'JOURNALNODE');
-  }.property('hostComponents.@each'),
+  journalNodes: DS.hasMany('App.HostComponent'),
   nameNodeStartTime: DS.attr('number'),
   jvmMemoryHeapUsed: DS.attr('number'),
   jvmMemoryHeapMax: DS.attr('number'),

http://git-wip-us.apache.org/repos/asf/ambari/blob/99cac719/ambari-web/app/models/service/mapreduce2.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models/service/mapreduce2.js 
b/ambari-web/app/models/service/mapreduce2.js
index ad343e1..e02b866 100644
--- a/ambari-web/app/models/service/mapreduce2.js
+++ b/ambari-web/app/models/service/mapreduce2.js
@@ -18,9 +18,7 @@
 var App = require('app');
 
 App.MapReduce2Service = App.Service.extend({
-  jobHistoryServer: function () {
-    return this.get('hostComponents').findProperty('componentName', 
'HISTORYSERVER');
-  }.property('hostComponents'),
+  jobHistoryServer: DS.belongsTo('App.HostComponent'),
   mapReduce2Clients: DS.attr('number')
 });
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/99cac719/ambari-web/app/models/service/yarn.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models/service/yarn.js 
b/ambari-web/app/models/service/yarn.js
index 3534b4e..c8967e6 100644
--- a/ambari-web/app/models/service/yarn.js
+++ b/ambari-web/app/models/service/yarn.js
@@ -19,18 +19,12 @@ var App = require('app');
 var objectUtils = require('utils/object_utils');
 
 App.YARNService = App.Service.extend({
-  resourceManager: function() {
-    return this.get('hostComponents').findProperty('componentName', 
'RESOURCEMANAGER');
-  }.property('hostComponents'),
+  resourceManager: DS.belongsTo('App.HostComponent'),
   isRMHaEnabled: function() {
     return this.get('hostComponents').filterProperty('componentName', 
'RESOURCEMANAGER').length > 1;
   }.property('hostComponents'),
-  activeResourceManager: function() {
-    return this.get('hostComponents').filterProperty('componentName', 
'RESOURCEMANAGER').findProperty('haStatus', 'ACTIVE');
-  }.property('hostComponents'),
-  appTimelineServer: function() {
-    return this.get('hostComponents').findProperty('componentName', 
'APP_TIMELINE_SERVER');
-  }.property('hostComponents'),
+  activeResourceManager: DS.belongsTo('App.HostComponent'),
+  appTimelineServer: DS.belongsTo('App.HostComponent'),
   nodeManagersStarted: DS.attr('number'),
   nodeManagersInstalled: DS.attr('number'),
   nodeManagersTotal: DS.attr('number'),

http://git-wip-us.apache.org/repos/asf/ambari/blob/99cac719/ambari-web/app/views/main/dashboard/widgets/flume_agent_live.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/dashboard/widgets/flume_agent_live.js 
b/ambari-web/app/views/main/dashboard/widgets/flume_agent_live.js
index e8945db..c775a7b 100644
--- a/ambari-web/app/views/main/dashboard/widgets/flume_agent_live.js
+++ b/ambari-web/app/views/main/dashboard/widgets/flume_agent_live.js
@@ -44,14 +44,15 @@ App.FlumeAgentUpView = App.TextDashboardWidgetView.extend({
     return this.get('model.hostComponents').filterProperty('componentName', 
'FLUME_HANDLER');
   }.property('model.hostComponents.length'),
 
-  flumeAgentsLive: function () {
-    return this.get('flumeAgentComponents').filterProperty("workStatus", 
"STARTED");
-  }.property('flumeAgentComponents.@each.workStatus'),
-
-  flumeAgentsDead: function () {
-    return this.get('flumeAgentComponents').filterProperty("workStatus", 
"INSTALLED");
-  }.property('flumeAgentComponents.@each.workStatus'),
+  /**
+   * @type {Array}
+   */
+  flumeAgentsLive: [],
 
+  /**
+   * @type {Array}
+   */
+  flumeAgentsDead: [],
 
   data: function () {
     if ( !this.get('flumeAgentComponents.length')) {
@@ -65,6 +66,15 @@ App.FlumeAgentUpView = App.TextDashboardWidgetView.extend({
     return this.get('flumeAgentsLive').length + "/" + 
this.get('flumeAgentComponents').length;
   }.property('flumeAgentComponents.length', 'flumeAgentsLive'),
 
+  statusObserver: function() {
+    Em.run.once(this, 'filterStatusOnce');
+  }.observes('flumeAgentComponents.@each.workStatus'),
+
+  filterStatusOnce: function() {
+    this.set('flumeAgentsLive', 
this.get('flumeAgentComponents').filterProperty("workStatus", "STARTED"));
+    this.set('flumeAgentsDead', 
this.get('flumeAgentComponents').filterProperty("workStatus", "INSTALLED"));
+  },
+
   editWidget: function (event) {
     var parent = this;
     var max_tmp =  parseFloat(parent.get('maxValue'));

http://git-wip-us.apache.org/repos/asf/ambari/blob/99cac719/ambari-web/app/views/main/host.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/host.js 
b/ambari-web/app/views/main/host.js
index df2f65f..b204985 100644
--- a/ambari-web/app/views/main/host.js
+++ b/ambari-web/app/views/main/host.js
@@ -388,7 +388,6 @@ App.MainHostView = 
App.TableView.extend(App.TableServerViewMixin, {
         id:host.id,
         clusterId: host.cluster_id,
         passiveState: host.passive_state,
-        isRequested: host.is_requested,
         hostName: host.host_name,
         hostComponents: host.host_components
       })
@@ -569,29 +568,27 @@ App.MainHostView = 
App.TableView.extend(App.TableServerViewMixin, {
      * @returns {String}
      */
     restartRequiredComponentsMessage: function() {
-      var restartRequiredComponents = 
this.get('content.hostComponents').filterProperty('staleConfigs', true);
-      var count = restartRequiredComponents.length;
+      var restartRequiredComponents = 
this.get('content.componentsWithStaleConfigs');
+      var count = this.get('content.componentsWithStaleConfigsCount');
       if (count <= 5) {
         var word = (count == 1) ? Em.I18n.t('common.component') : 
Em.I18n.t('common.components');
         return 
Em.I18n.t('hosts.table.restartComponents.withNames').format(restartRequiredComponents.getEach('displayName').join(',
 ')) + ' ' + word.toLowerCase();
       }
       return 
Em.I18n.t('hosts.table.restartComponents.withoutNames').format(count);
-    }.property('content.hostComponents.@each.staleConfigs'),
+    }.property('content.componentsWithStaleConfigs'),
 
     /**
      * Tooltip message for "Maintenance" icon
      * @returns {String}
      */
     componentsInPassiveStateMessage: function() {
-      var componentsInPassiveState = 
this.get('content.hostComponents').filter(function(component) {
-        return component.get('passiveState') !== 'OFF';
-      });
-      var count = componentsInPassiveState.length;
+      var componentsInPassiveState = 
this.get('content.componentsInPassiveState');
+      var count = this.get('content.componentsInPassiveStateCount');
       if (count <= 5) {
         return 
Em.I18n.t('hosts.table.componentsInPassiveState.withNames').format(componentsInPassiveState.getEach('displayName').join(',
 '));
       }
       return 
Em.I18n.t('hosts.table.componentsInPassiveState.withoutNames').format(count);
-    }.property('content.hostComponents.@each.passiveState'),
+    }.property('content.componentsInPassiveState'),
 
     /**
      * true if host has only one repoversion

http://git-wip-us.apache.org/repos/asf/ambari/blob/99cac719/ambari-web/test/mappers/server_data_mapper_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/mappers/server_data_mapper_test.js 
b/ambari-web/test/mappers/server_data_mapper_test.js
index a1868cb..da873d5 100644
--- a/ambari-web/test/mappers/server_data_mapper_test.js
+++ b/ambari-web/test/mappers/server_data_mapper_test.js
@@ -73,8 +73,7 @@ describe('App.QuickDataMapper', function () {
       f4_type: 'array',
       f4: {
         item: 'c2'
-      },
-      f5: 'item.["key.dotted"]'
+      }
     };
     var mapper = App.QuickDataMapper.create();
     var result = mapper.parseIt(test_json, config);
@@ -93,9 +92,6 @@ describe('App.QuickDataMapper', function () {
     it('Generate array of json fields', function() {
       expect(result.f4).to.eql(['val1','val4','val5']);
     });
-    it('Check value with dotted key', function() {
-      expect(result.f5).to.eql('val6');
-    });
   });
 
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/99cac719/ambari-web/test/mappers/service_mapper_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/mappers/service_mapper_test.js 
b/ambari-web/test/mappers/service_mapper_test.js
index 3545c03..5091c0f 100644
--- a/ambari-web/test/mappers/service_mapper_test.js
+++ b/ambari-web/test/mappers/service_mapper_test.js
@@ -50,6 +50,9 @@ describe('App.serviceMetricsMapper', function () {
                         ritCount: 0
                       }
                     }
+                  },
+                  HostRoles: {
+                    host_name: 'host1'
                   }
                 }
               ]
@@ -78,6 +81,9 @@ describe('App.serviceMetricsMapper', function () {
                         ritCount: 0
                       }
                     }
+                  },
+                  HostRoles: {
+                    host_name: 'host1'
                   }
                 }
               ]
@@ -106,6 +112,9 @@ describe('App.serviceMetricsMapper', function () {
                         ritCount: 0
                       }
                     }
+                  },
+                  HostRoles: {
+                    host_name: 'host1'
                   }
                 }
               ]
@@ -134,6 +143,9 @@ describe('App.serviceMetricsMapper', function () {
                         ritCount: 0
                       }
                     }
+                  },
+                  HostRoles: {
+                    host_name: 'host1'
                   }
                 }
               ]

http://git-wip-us.apache.org/repos/asf/ambari/blob/99cac719/ambari-web/test/models/host_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/models/host_test.js 
b/ambari-web/test/models/host_test.js
index 674496d..30bc5e2 100644
--- a/ambari-web/test/models/host_test.js
+++ b/ambari-web/test/models/host_test.js
@@ -216,7 +216,7 @@ describe('App.Host', function () {
     });
   });
 
-  describe('#componentsWithStaleConfigs', function () {
+  describe.skip('#componentsWithStaleConfigs', function () {
     it('One component with stale configs', function () {
       host1.set('hostComponents', [Em.Object.create({
         staleConfigs: true
@@ -235,7 +235,7 @@ describe('App.Host', function () {
     });
   });
 
-  describe('#componentsInPassiveStateCount', function () {
+  describe.skip('#componentsInPassiveStateCount', function () {
     it('No component in passive state', function () {
       host1.set('hostComponents', [Em.Object.create({
         passiveState: 'OFF'

http://git-wip-us.apache.org/repos/asf/ambari/blob/99cac719/ambari-web/test/models/service/hdfs_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/models/service/hdfs_test.js 
b/ambari-web/test/models/service/hdfs_test.js
index d923967..2eb1130 100644
--- a/ambari-web/test/models/service/hdfs_test.js
+++ b/ambari-web/test/models/service/hdfs_test.js
@@ -21,44 +21,32 @@ var App = require('app');
 var modelSetup = require('test/init_model_test');
 require('models/service/hdfs');
 
-var hdfsService,
-  hdfsServiceData = {
-    id: 'hdfs'
-  },
-  hostComponentsData = [
-    {
-      id: 'journalnode',
-      componentName: 'JOURNALNODE'
-    }
-  ],
-  cases = [
-    {
-      propertyName: 'journalNodes',
-      componentId: 'journalnode'
-    }
-  ];
-
 describe('App.HDFSService', function () {
 
-  beforeEach(function () {
-    hdfsService = App.HDFSService.createRecord(hdfsServiceData);
-  });
-
-  afterEach(function () {
-    modelSetup.deleteRecord(hdfsService);
-  });
-
-  cases.forEach(function (item) {
-    var propertyName = item.propertyName;
-    describe('#' + propertyName, function () {
-      it('should take one component from hostComponents', function () {
-        hdfsService.reopen({
-          hostComponents: hostComponentsData
+    describe('#isNnHaEnabled', function () {
+      var record = App.HDFSService.createRecord({
+        id: 'hdfs'
+      });
+      it('ha disabled', function () {
+        record.reopen({
+          hostComponents: [Em.Object.create({componentName: 'NAMENODE'})],
+          snameNode: true
         });
-        expect(hdfsService.get(propertyName)).to.have.length(1);
-        expect(hdfsService.get(propertyName)[0].id).to.equal(item.componentId);
+        record.propertyDidChange('isNnHaEnabled');
+        expect(record.get('isNnHaEnabled')).to.be.false;
+      });
+      it('ha enabled', function () {
+        record.setProperties({
+          hostComponents: [
+            Em.Object.create({componentName: 'NAMENODE'}),
+            Em.Object.create({componentName: 'NAMENODE'})
+          ],
+          snameNode: null
+        });
+        record.propertyDidChange('isNnHaEnabled');
+        expect(record.get('isNnHaEnabled')).to.be.true;
       });
     });
-  });
+
 
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/99cac719/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 4753f95..eeb0de0 100644
--- a/ambari-web/test/models/service_test.js
+++ b/ambari-web/test/models/service_test.js
@@ -218,28 +218,22 @@ describe('App.Service', function () {
   });
 
   describe('#isRestartRequired', function () {
-    var mockHostComponentModel = function (mock) {
-      sinon.stub(App.HostComponent, 'find', function () {
-        return mock;
-      });
-    }
+
     beforeEach(function () {
       service.reopen({
-        serviceName: 'HDFS'
+        serviceName: 'HDFS',
+        hostComponents: []
       });
     });
-    afterEach(function () {
-      App.HostComponent.find.restore();
-    });
     hostComponentsDataFalse.forEach(function (item) {
       it('should be false', function () {
-        mockHostComponentModel(item);
+        service.set('hostComponents', item);
         expect(service.get('isRestartRequired')).to.be.false;
       });
     });
     hostComponentsDataTrue.forEach(function (item) {
       it('should be true', function () {
-        mockHostComponentModel(item);
+        service.set('hostComponents', item);
         expect(service.get('isRestartRequired')).to.be.true;
       });
     });

Reply via email to