Author: yusaku
Date: Wed Feb 27 20:10:01 2013
New Revision: 1450945
URL: http://svn.apache.org/r1450945
Log:
AMBARI-1519. Ambari Web goes back and forth between frozen and usable state
peridocially on a large cluster. (yusaku)
Modified:
incubator/ambari/trunk/CHANGES.txt
incubator/ambari/trunk/ambari-web/app/mappers/status_mapper.js
incubator/ambari/trunk/ambari-web/app/models/host.js
incubator/ambari/trunk/ambari-web/app/models/service.js
Modified: incubator/ambari/trunk/CHANGES.txt
URL:
http://svn.apache.org/viewvc/incubator/ambari/trunk/CHANGES.txt?rev=1450945&r1=1450944&r2=1450945&view=diff
==============================================================================
--- incubator/ambari/trunk/CHANGES.txt (original)
+++ incubator/ambari/trunk/CHANGES.txt Wed Feb 27 20:10:01 2013
@@ -387,6 +387,9 @@ Trunk (unreleased changes):
BUG FIXES
+ AMBARI-1519. Ambari Web goes back and forth between frozen and usable state
+ peridocially on a large cluster. (yusaku)
+
AMBARI-1499. Add hosts is broken. (yusaku)
AMBARI-1501. Nagios alerts do not update automatically. (yusaku)
Modified: incubator/ambari/trunk/ambari-web/app/mappers/status_mapper.js
URL:
http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-web/app/mappers/status_mapper.js?rev=1450945&r1=1450944&r2=1450945&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-web/app/mappers/status_mapper.js (original)
+++ incubator/ambari/trunk/ambari-web/app/mappers/status_mapper.js Wed Feb 27
20:10:01 2013
@@ -58,6 +58,8 @@ App.statusMapper = App.QuickDataMapper.c
}, this)
}, this);
+ // console.profile("App.statusMapper.map() profile");
+
var hostComponents = App.HostComponent.find();
hostComponents.forEach(function(hostComponent) {
@@ -67,6 +69,8 @@ App.statusMapper = App.QuickDataMapper.c
}
});
+ // console.profileEnd();
+
console.log('out status mapper. Took ' + (new Date().getTime() - start)
+ 'ms');
}
}
Modified: incubator/ambari/trunk/ambari-web/app/models/host.js
URL:
http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-web/app/models/host.js?rev=1450945&r1=1450944&r2=1450945&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-web/app/models/host.js (original)
+++ incubator/ambari/trunk/ambari-web/app/models/host.js Wed Feb 27 20:10:01
2013
@@ -122,7 +122,19 @@ App.Host = DS.Model.extend({
if (this.get('loadFifteen') != null) return
this.get('loadFifteen').toFixed(2);
}.property('loadOne', 'loadFive', 'loadFifteen'),
- healthClass: function(){
+ // Instead of making healthStatus a computed property that listens on
[email protected],
+ // we are creating a separate observer _updateHealthStatus. This is so that
healthStatus is updated
+ // only once after the run loop. This is because Ember invokes the computed
property every time
+ // a property that it depends on changes. For example, App.statusMapper's
map function would invoke
+ // the computed property too many times and freezes the UI without this hack.
+ // See
http://stackoverflow.com/questions/12467345/ember-js-collapsing-deferring-expensive-observers-or-computed-properties
+ healthClass: '',
+
+ _updateHealthClass: function(){
+ Ember.run.once(this, 'updateHealthClass');
+ }.observes('healthStatus', '[email protected]'),
+
+ updateHealthClass: function(){
var healthStatus = this.get('healthStatus');
/**
* Do nothing until load
@@ -147,8 +159,9 @@ App.Host = DS.Model.extend({
healthStatus = status;
}
}
- return 'health-status-' + healthStatus;
- }.property('healthStatus', '[email protected]'),
+ this.set('healthClass', 'health-status-' + healthStatus);
+ },
+
healthToolTip: function(){
var hostComponents = this.get('hostComponents').filter(function(item){
if(item.get('workStatus') !== App.HostComponentStatus.started){
Modified: incubator/ambari/trunk/ambari-web/app/models/service.js
URL:
http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-web/app/models/service.js?rev=1450945&r1=1450944&r2=1450945&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-web/app/models/service.js (original)
+++ incubator/ambari/trunk/ambari-web/app/models/service.js Wed Feb 27 20:10:01
2013
@@ -35,24 +35,45 @@ App.Service = DS.Model.extend({
return !(this.get('healthStatus') == 'green');
}.property('healthStatus'),
- healthStatus: function () {
+ // Instead of making healthStatus a computed property that listens on
[email protected],
+ // we are creating a separate observer _updateHealthStatus. This is so that
healthStatus is updated
+ // only once after the run loop. This is because Ember invokes the computed
property every time
+ // a property that it depends on changes. For example, App.statusMapper's
map function would invoke
+ // the computed property too many times and freezes the UI without this hack.
+ // See
http://stackoverflow.com/questions/12467345/ember-js-collapsing-deferring-expensive-observers-or-computed-properties
+ healthStatus: '',
+
+ updateHealthStatus: function () {
+ // console.log('model:service.healthStatus ' + this.get('serviceName'));
var components = this.get('hostComponents').filterProperty('isMaster',
true);
var isGreen = (this.get('serviceName') === 'HBASE' ?
components.someProperty('workStatus', App.HostComponentStatus.started) :
components.everyProperty('workStatus', App.HostComponentStatus.started))
;
if (isGreen) {
- return 'green';
+ this.set('healthStatus', 'green');
} else if (components.someProperty('workStatus',
App.HostComponentStatus.starting)) {
- return 'green-blinking';
+ this.set('healthStatus', 'green-blinking');
} else if (components.someProperty('workStatus',
App.HostComponentStatus.stopped)) {
- return 'red';
+ this.set('healthStatus', 'red');
} else {
- return 'red-blinking';
+ this.set('healthStatus', 'red-blinking');
}
- }.property('[email protected]'),
+ },
+
+ /**
+ * Every time when changes workStatus of any component we schedule
recalculating values related from them
+ */
+ _updateHealthStatus: (function() {
+ Ember.run.once(this, 'updateHealthStatus');
+ Ember.run.once(this, 'updateIsStopped');
+ Ember.run.once(this, 'updateIsStarted');
+ }).observes('[email protected]'),
- isStopped: function () {
+ isStopped: false,
+ isStarted: false,
+
+ updateIsStopped: function () {
var components = this.get('hostComponents');
var flag = true;
components.forEach(function (_component) {
@@ -60,13 +81,16 @@ App.Service = DS.Model.extend({
flag = false;
}
}, this);
- return flag;
- }.property('[email protected]'),
+ this.set('isStopped', flag);
+ },
- isStarted: function () {
+ updateIsStarted: function () {
var components = this.get('hostComponents').filterProperty('isMaster',
true);
- return components.everyProperty('workStatus',
App.HostComponentStatus.started);
- }.property('[email protected]'),
+ this.set('isStarted',
+ components.everyProperty('workStatus', App.HostComponentStatus.started)
+ );
+ },
+
isMaintained: function () {
var maintainedServices = [
"HDFS",
@@ -79,10 +103,9 @@ App.Service = DS.Model.extend({
"PIG",
"SQOOP"
];
- for (var i in maintainedServices) {
- if (this.get('serviceName') == maintainedServices[i]) return true;
- }
+ return maintainedServices.contains(this.get('serviceName'));
}.property('serviceName'),
+
isConfigurable: function () {
var configurableServices = [
"HDFS",
@@ -96,10 +119,9 @@ App.Service = DS.Model.extend({
"SQOOP",
"NAGIOS"
];
- for (var i in configurableServices) {
- if (this.get('serviceName') == configurableServices[i]) return true;
- }
+ return configurableServices.contains(this.get('serviceName'));
}.property('serviceName'),
+
displayName: function () {
switch (this.get('serviceName').toLowerCase()) {
case 'hdfs':
@@ -133,7 +155,7 @@ App.Service = DS.Model.extend({
App.Service.Health = {
live: "LIVE",
- dead: "DEAD",
+ dead: "DEAD-RED",
starting: "STARTING",
stopping: "STOPPING",