You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tez.apache.org by sr...@apache.org on 2015/11/05 03:35:21 UTC

tez git commit: TEZ-2895. Tez UI: Add option to enable and disable in-progress (sree)

Repository: tez
Updated Branches:
  refs/heads/master e9344fb6e -> 0e7f54c9b


TEZ-2895. Tez UI: Add option to enable and disable in-progress (sree)


Project: http://git-wip-us.apache.org/repos/asf/tez/repo
Commit: http://git-wip-us.apache.org/repos/asf/tez/commit/0e7f54c9
Tree: http://git-wip-us.apache.org/repos/asf/tez/tree/0e7f54c9
Diff: http://git-wip-us.apache.org/repos/asf/tez/diff/0e7f54c9

Branch: refs/heads/master
Commit: 0e7f54c9b65f6db6abfee2292f601a6924890c69
Parents: e9344fb
Author: Sreenath Somarajapuram <sr...@apache.org>
Authored: Thu Nov 5 08:04:56 2015 +0530
Committer: Sreenath Somarajapuram <sr...@apache.org>
Committed: Thu Nov 5 08:04:56 2015 +0530

----------------------------------------------------------------------
 CHANGES.txt                                     |   1 +
 tez-ui/src/main/webapp/app/scripts/app.js       |   1 +
 .../app/scripts/controllers/base-controller.js  |  49 ++++++++
 .../controllers/dag-task-attempts-controller.js |   3 +-
 .../app/scripts/controllers/dag_controller.js   |  20 ++--
 .../scripts/controllers/dag_index_controller.js |   7 +-
 .../webapp/app/scripts/controllers/dag_tasks.js |   3 +-
 .../app/scripts/controllers/dag_vertices.js     |   5 +-
 .../scripts/controllers/polling-controller.js   |  26 ++++-
 .../controllers/table-page-controller.js        |  20 ++--
 .../controllers/task_attempt_controller.js      |  14 +--
 .../app/scripts/controllers/task_controller.js  |  12 +-
 .../controllers/task_index_controller.js        |   2 +-
 .../task_task_attempts_controller.js            |   3 +-
 .../scripts/controllers/tez-app-controller.js   |  12 +-
 .../controllers/tez-app-dags-controller.js      |   2 +
 .../controllers/tez-app-index-controller.js     |   2 +-
 .../scripts/controllers/vertex_controller.js    |  11 +-
 .../controllers/vertex_index_controller.js      |   2 +-
 .../vertex_task_attempts_controller.js          |   5 +-
 .../controllers/vertex_tasks_controller.js      |   5 +-
 .../scripts/helpers/entity-array-pollster.js    |  10 +-
 tez-ui/src/main/webapp/app/scripts/router.js    | 112 +++++++------------
 tez-ui/src/main/webapp/app/styles/main.less     |   7 ++
 tez-ui/src/main/webapp/app/styles/shared.less   |  15 ++-
 .../app/templates/components/load-time.hbs      |  10 ++
 26 files changed, 200 insertions(+), 159 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tez/blob/0e7f54c9/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index c4113f2..29a8151 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -7,6 +7,7 @@ INCOMPATIBLE CHANGES
   TEZ-2679. Admin forms of launch env settings
 
 ALL CHANGES:
+  TEZ-2895. Tez UI: Add option to enable and disable in-progress
   TEZ-2894. Tez UI: Disable sorting for few columns while in progress. Display an alert on trying to sort them
   TEZ-2893. Tez UI: Retain vertex info displayed in DAG details page even after completion
   TEZ-2878. Tez UI: AM error handling - Make the UI handle cases in which AM returns unexpected/no data

http://git-wip-us.apache.org/repos/asf/tez/blob/0e7f54c9/tez-ui/src/main/webapp/app/scripts/app.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/app.js b/tez-ui/src/main/webapp/app/scripts/app.js
index c1c2c45..f2c3dd0 100644
--- a/tez-ui/src/main/webapp/app/scripts/app.js
+++ b/tez-ui/src/main/webapp/app/scripts/app.js
@@ -298,6 +298,7 @@ require('scripts/router');
 require('scripts/views/**/*');
 require('scripts/models/**/*');
 
+require('scripts/controllers/base-controller');
 require('scripts/controllers/polling-controller');
 require('scripts/controllers/table-page-controller');
 require('scripts/controllers/**/*');

http://git-wip-us.apache.org/repos/asf/tez/blob/0e7f54c9/tez-ui/src/main/webapp/app/scripts/controllers/base-controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/controllers/base-controller.js b/tez-ui/src/main/webapp/app/scripts/controllers/base-controller.js
new file mode 100644
index 0000000..e0461dc
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/scripts/controllers/base-controller.js
@@ -0,0 +1,49 @@
+/**
+ * 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.
+ */
+
+App.BaseController = Em.ObjectController.extend({
+  controllerName: null, // Must be set by the respective controllers
+
+  isActive: false,
+
+  setup: function () {
+    this.set('isActive', true);
+  },
+  reset: function () {
+    this.set('isActive', false);
+  },
+
+  getStoreKey: function (subKey) {
+    return "%@:%@".fmt(this.get('controllerName'), subKey);
+  },
+  storeConfig: function (key, value) {
+    try {
+      localStorage.setItem(this.getStoreKey(key) , JSON.stringify(value));
+    }catch(e){
+      return e;
+    }
+    return value;
+  },
+  fetchConfig: function (key) {
+    try {
+      return JSON.parse(localStorage.getItem(this.getStoreKey(key)));
+    }catch(e){}
+    return undefined;
+  },
+
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/0e7f54c9/tez-ui/src/main/webapp/app/scripts/controllers/dag-task-attempts-controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/controllers/dag-task-attempts-controller.js b/tez-ui/src/main/webapp/app/scripts/controllers/dag-task-attempts-controller.js
index a5e5200..db5b1fd 100644
--- a/tez-ui/src/main/webapp/app/scripts/controllers/dag-task-attempts-controller.js
+++ b/tez-ui/src/main/webapp/app/scripts/controllers/dag-task-attempts-controller.js
@@ -34,13 +34,14 @@ App.DagTaskAttemptsController = App.TablePageController.extend({
         this.get('amWebServiceVersion') != '1' &&
         !this.get('loading') &&
         this.get('isActive') &&
+        this.get('pollingEnabled') &&
         this. get('rowsDisplayed.length') > 0) {
       this.get('pollster').start();
     }
     else {
       this.get('pollster').stop();
     }
-  }.observes('status', 'amWebServiceVersion', 'rowsDisplayed', 'loading', 'isActive'),
+  }.observes('status', 'amWebServiceVersion', 'rowsDisplayed', 'loading', 'isActive', 'pollingEnabled'),
 
   pollsterOptionsObserver: function () {
     this.set('pollster.options', {

http://git-wip-us.apache.org/repos/asf/tez/blob/0e7f54c9/tez-ui/src/main/webapp/app/scripts/controllers/dag_controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/controllers/dag_controller.js b/tez-ui/src/main/webapp/app/scripts/controllers/dag_controller.js
index 95c6a8f..634bd84 100644
--- a/tez-ui/src/main/webapp/app/scripts/controllers/dag_controller.js
+++ b/tez-ui/src/main/webapp/app/scripts/controllers/dag_controller.js
@@ -21,27 +21,20 @@ App.DagController = App.PollingController.extend(App.Helpers.DisplayHelper, {
   pageTitle: 'Dag',
 
   loading: true,
-  isActive: false,
 
   pollingType: 'dagInfo',
 
-  setup: function () {
-    this.set('isActive', true);
-  },
-  reset: function () {
-    this.set('isActive', false);
-  },
-
   pollsterControl: function () {
     if(this.get('status') == 'RUNNING' &&
         this.get('amWebServiceVersion') != '1' &&
+        this.get('pollingEnabled') &&
         this.get('isActive')) {
       this.get('pollster').start();
     }
     else {
       this.get('pollster').stop();
     }
-  }.observes('status', 'amWebServiceVersion', 'isActive'),
+  }.observes('status', 'amWebServiceVersion', 'isActive', 'pollingEnabled'),
 
   pollsterOptionsObserver: function () {
     var model = this.get('model');
@@ -107,10 +100,13 @@ App.DagController = App.PollingController.extend(App.Helpers.DisplayHelper, {
     allLoaders.then(function(){
       if (dag.get('status') === 'RUNNING') {
         // update the progress info if available. this need not block the UI
-        if (dag.get('amWebServiceVersion') == '1') {
+        if (dag.get('amWebServiceVersion') == '1' || !that.get('pollingEnabled')) {
           that.updateInfoFromAM(dag);
         }
       }
+      else if(dag.get('status') == 'SUCCEEDED') {
+        dag.set('progress', 1);
+      }
     });
 
     return allLoaders;
@@ -124,9 +120,9 @@ App.DagController = App.PollingController.extend(App.Helpers.DisplayHelper, {
       appId: dag.get('applicationId'),
       dagIdx: dag.get('idx')
     }).then(function(dagProgressInfo) {
-      that.set('dag.progress', dagProgressInfo.get('progress'));
+      that.set('progress', dagProgressInfo.get('progress'));
     }).catch(function (error) {
-      Em.Logger.error("Failed to fetch dagProgress" + e);
+      Em.Logger.error("Failed to fetch dagProgress" + error);
     });
   },
 

http://git-wip-us.apache.org/repos/asf/tez/blob/0e7f54c9/tez-ui/src/main/webapp/app/scripts/controllers/dag_index_controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/controllers/dag_index_controller.js b/tez-ui/src/main/webapp/app/scripts/controllers/dag_index_controller.js
index ad3c454..61b4912 100644
--- a/tez-ui/src/main/webapp/app/scripts/controllers/dag_index_controller.js
+++ b/tez-ui/src/main/webapp/app/scripts/controllers/dag_index_controller.js
@@ -44,17 +44,20 @@ App.DagIndexController = App.TablePageController.extend({
         this.get('amWebServiceVersion') != '1' &&
         !this.get('loading') &&
         this.get('isActive') &&
+        this.get('pollingEnabled') &&
         this.get('rowsDisplayed.length') > 0) {
       this.get('pollster').start();
     }
     else {
       this.get('pollster').stop();
     }
-  }.observes('status', 'amWebServiceVersion', 'loading', 'isActive'),
+  }.observes('status', 'amWebServiceVersion', 'loading', 'isActive', 'pollingEnabled'),
 
   applicationComplete: function () {
     this._super();
-    this.set('controllers.dag.progress', 1);
+    if(this.get('controllers.dag.status') == 'SUCCEEDED') {
+      this.set('controllers.dag.progress', 1);
+    }
   },
 
   pollsterOptionsObserver: function () {

http://git-wip-us.apache.org/repos/asf/tez/blob/0e7f54c9/tez-ui/src/main/webapp/app/scripts/controllers/dag_tasks.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/controllers/dag_tasks.js b/tez-ui/src/main/webapp/app/scripts/controllers/dag_tasks.js
index d8cae6a..8ab20e3 100644
--- a/tez-ui/src/main/webapp/app/scripts/controllers/dag_tasks.js
+++ b/tez-ui/src/main/webapp/app/scripts/controllers/dag_tasks.js
@@ -33,13 +33,14 @@ App.DagTasksController = App.TablePageController.extend({
         this.get('amWebServiceVersion') != '1' &&
         !this.get('loading') &&
         this.get('isActive') &&
+        this.get('pollingEnabled') &&
         this. get('rowsDisplayed.length') > 0) {
       this.get('pollster').start();
     }
     else {
       this.get('pollster').stop();
     }
-  }.observes('status', 'amWebServiceVersion', 'rowsDisplayed', 'loading', 'isActive'),
+  }.observes('status', 'amWebServiceVersion', 'rowsDisplayed', 'loading', 'isActive', 'pollingEnabled'),
 
   pollsterOptionsObserver: function () {
     this.set('pollster.options', {

http://git-wip-us.apache.org/repos/asf/tez/blob/0e7f54c9/tez-ui/src/main/webapp/app/scripts/controllers/dag_vertices.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/controllers/dag_vertices.js b/tez-ui/src/main/webapp/app/scripts/controllers/dag_vertices.js
index 44d29da..d0740a9 100644
--- a/tez-ui/src/main/webapp/app/scripts/controllers/dag_vertices.js
+++ b/tez-ui/src/main/webapp/app/scripts/controllers/dag_vertices.js
@@ -34,13 +34,14 @@ App.DagVerticesController = App.TablePageController.extend({
         this.get('amWebServiceVersion') != '1' &&
         !this.get('loading') &&
         this.get('isActive') &&
+        this.get('pollingEnabled') &&
         this. get('rowsDisplayed.length') > 0) {
       this.get('pollster').start();
     }
     else {
       this.get('pollster').stop();
     }
-  }.observes('status', 'amWebServiceVersion', 'rowsDisplayed', 'loading', 'isActive'),
+  }.observes('status', 'amWebServiceVersion', 'rowsDisplayed', 'loading', 'isActive', 'pollingEnabled'),
 
   pollsterOptionsObserver: function () {
     this.set('pollster.options', {
@@ -104,7 +105,7 @@ App.DagVerticesController = App.TablePageController.extend({
         }
       }).then(function(vertexProgressInfo) {
           App.Helpers.emData.mergeRecords(
-            that.get('displayedRecords'),
+            that.get('rowsDisplayed'),
             vertexProgressInfo,
             ['progress']
           );

http://git-wip-us.apache.org/repos/asf/tez/blob/0e7f54c9/tez-ui/src/main/webapp/app/scripts/controllers/polling-controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/controllers/polling-controller.js b/tez-ui/src/main/webapp/app/scripts/controllers/polling-controller.js
index 507ee49..f101c96 100644
--- a/tez-ui/src/main/webapp/app/scripts/controllers/polling-controller.js
+++ b/tez-ui/src/main/webapp/app/scripts/controllers/polling-controller.js
@@ -18,15 +18,18 @@
 
 var DEFAULT_MERGE_PROPS = ['status', 'progress'];
 
-App.PollingController = Em.ObjectController.extend({
+App.PollingController = App.BaseController.extend({
 
   pollster: null,
-  pollingEnabled: false,
+  pollingEnabled: true,
+  showAutoUpdate: true,
 
   pollingType: null,
   pollingOptions: null,
 
   init: function () {
+    var pollingEnabled;
+
     this._super();
     this.set('pollster', App.Helpers.EntityArrayPollster.create({
       store: this.get('store'),
@@ -37,8 +40,26 @@ App.PollingController = Em.ObjectController.extend({
 
       onFailure: this.onPollingFailure.bind(this)
     }));
+
+    pollingEnabled = this.fetchConfig('pollingEnabled');
+    if(pollingEnabled != undefined) {
+      this.set('pollingEnabled', pollingEnabled);
+    }
   },
 
+  pollingEnabledObserver: function () {
+    var pollingEnabled = this.get('pollingEnabled');
+
+    this.storeConfig('pollingEnabled', pollingEnabled);
+    this.send('pollingEnabledChanged', pollingEnabled);
+
+    if(!pollingEnabled && this.get('pollster.isRunning')) {
+      this.get('pollster').stop();
+      this.set('pollster.polledRecords', null);
+      this.applicationComplete();
+    }
+  }.observes('pollingEnabled'),
+
   onPollingFailure: function (error) {
     var appID = this.get('pollster.options.appID'),
         that = this;
@@ -61,6 +82,7 @@ App.PollingController = Em.ObjectController.extend({
   },
 
   applicationComplete: function () {
+    this.get('pollster').stop();
     this.set('pollster.polledRecords', null);
     if(this.load) {
       this.load();

http://git-wip-us.apache.org/repos/asf/tez/blob/0e7f54c9/tez-ui/src/main/webapp/app/scripts/controllers/table-page-controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/controllers/table-page-controller.js b/tez-ui/src/main/webapp/app/scripts/controllers/table-page-controller.js
index cf3d02c..6f14836 100644
--- a/tez-ui/src/main/webapp/app/scripts/controllers/table-page-controller.js
+++ b/tez-ui/src/main/webapp/app/scripts/controllers/table-page-controller.js
@@ -32,29 +32,25 @@ App.TablePageController = App.PollingController.extend(
 
       isRefreshable: true,
 
-      // -- TODO: TEZ-2785 : Following 3 must be moved to a parent class
-      isActive: false,
-
-      setup: function () {
-        this.set('isActive', true);
-      },
-      reset: function () {
-        this.set('isActive', false);
-      },
+      parentStatus: null,
 
       rowsDisplayedObserver: function () {
         this.set('pollster.targetRecords', this.get('rowsDisplayed'));
       }.observes('rowsDisplayed', 'pollster'),
 
       parentStatusObserver: function () {
-        var parentStatus = this.get('status');
-        if(parentStatus && parentStatus != 'RUNNING') {
+        var parentStatus = this.get('status'),
+            previousStatus = this.get('parentStatus');
+
+        if(parentStatus != previousStatus && previousStatus == 'RUNNING' && this.get('pollingEnabled')) {
           this.get('pollster').stop();
           this.loadData(true);
         }
+        this.set('parentStatus', parentStatus);
       }.observes('status'),
 
       applicationComplete: function () {
+        this.set('pollster.polledRecords', null);
         this.loadData(true);
       },
 
@@ -67,7 +63,7 @@ App.TablePageController = App.PollingController.extend(
         if(inProgress) {
           App.Helpers.Dialogs.alert(
             'Cannot sort',
-            'Sorting on %@ is disabled for in-progress DAGs!'.fmt(columnDef.get('headerCellName')),
+            'Sorting on %@ is disabled for running DAGs!'.fmt(columnDef.get('headerCellName')),
             this
           );
         }

http://git-wip-us.apache.org/repos/asf/tez/blob/0e7f54c9/tez-ui/src/main/webapp/app/scripts/controllers/task_attempt_controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/controllers/task_attempt_controller.js b/tez-ui/src/main/webapp/app/scripts/controllers/task_attempt_controller.js
index ebb8d32..03a62dd 100644
--- a/tez-ui/src/main/webapp/app/scripts/controllers/task_attempt_controller.js
+++ b/tez-ui/src/main/webapp/app/scripts/controllers/task_attempt_controller.js
@@ -16,15 +16,13 @@
  * limitations under the License.
  */
 
-App.TaskAttemptController = Em.ObjectController.extend(App.Helpers.DisplayHelper, {
+App.TaskAttemptController = App.BaseController.extend(App.Helpers.DisplayHelper, {
   controllerName: 'TaskAttemptController',
 
   pageTitle: 'TaskAttempt',
 
   loading: true,
 
-  isActive: false,
-
   pollster: App.Helpers.EntityArrayPollster.create(),
 
   init: function () {
@@ -36,23 +34,17 @@ App.TaskAttemptController = Em.ObjectController.extend(App.Helpers.DisplayHelper
     });
   },
 
-  setup: function () {
-    this.set('isActive', true);
-  },
-  reset: function () {
-    this.set('isActive', false);
-  },
-
   pollsterControl: function () {
     if(this.get('task.vertex.dag.status') == 'RUNNING' &&
         this.get('task.vertex.dag.amWebServiceVersion') != '1' &&
+        this.get('pollingEnabled') &&
         this.get('isActive')) {
       this.get('pollster').start();
     }
     else {
       this.get('pollster').stop();
     }
-  }.observes('task.vertex.dag.status', 'task.vertex.dag.amWebServiceVersion', 'isActive'),
+  }.observes('task.vertex.dag.status', 'task.vertex.dag.amWebServiceVersion', 'isActive', 'pollingEnabled'),
 
   pollsterOptionsObserver: function () {
     var model = this.get('model');

http://git-wip-us.apache.org/repos/asf/tez/blob/0e7f54c9/tez-ui/src/main/webapp/app/scripts/controllers/task_controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/controllers/task_controller.js b/tez-ui/src/main/webapp/app/scripts/controllers/task_controller.js
index 564b529..33a67fe 100644
--- a/tez-ui/src/main/webapp/app/scripts/controllers/task_controller.js
+++ b/tez-ui/src/main/webapp/app/scripts/controllers/task_controller.js
@@ -23,27 +23,19 @@ App.TaskController = App.PollingController.extend(App.Helpers.DisplayHelper, App
 
   loading: true,
 
-  isActive: false,
-
   pollingType: 'taskInfo',
 
-  setup: function () {
-    this.set('isActive', true);
-  },
-  reset: function () {
-    this.set('isActive', false);
-  },
-
   pollsterControl: function () {
     if(this.get('vertex.dag.status') == 'RUNNING' &&
         this.get('vertex.dag.amWebServiceVersion') != '1' &&
+        this.get('pollingEnabled') &&
         this.get('isActive')) {
       this.get('pollster').start();
     }
     else {
       this.get('pollster').stop();
     }
-  }.observes('vertex.dag.status', 'vertex.dag.amWebServiceVersion', 'isActive'),
+  }.observes('vertex.dag.status', 'vertex.dag.amWebServiceVersion', 'isActive', 'pollingEnabled'),
 
   pollsterOptionsObserver: function () {
     var model = this.get('model');

http://git-wip-us.apache.org/repos/asf/tez/blob/0e7f54c9/tez-ui/src/main/webapp/app/scripts/controllers/task_index_controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/controllers/task_index_controller.js b/tez-ui/src/main/webapp/app/scripts/controllers/task_index_controller.js
index 3d49248..71643c2 100644
--- a/tez-ui/src/main/webapp/app/scripts/controllers/task_index_controller.js
+++ b/tez-ui/src/main/webapp/app/scripts/controllers/task_index_controller.js
@@ -17,7 +17,7 @@
  */
 
  //TODO: watch individual counters.
-App.TaskIndexController = Em.ObjectController.extend(App.ModelRefreshMixin, {
+App.TaskIndexController = App.BaseController.extend(App.ModelRefreshMixin, {
   controllerName: 'TaskIndexController',
 
   taskStatus: function() {

http://git-wip-us.apache.org/repos/asf/tez/blob/0e7f54c9/tez-ui/src/main/webapp/app/scripts/controllers/task_task_attempts_controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/controllers/task_task_attempts_controller.js b/tez-ui/src/main/webapp/app/scripts/controllers/task_task_attempts_controller.js
index 73151bf..0d787a9 100644
--- a/tez-ui/src/main/webapp/app/scripts/controllers/task_task_attempts_controller.js
+++ b/tez-ui/src/main/webapp/app/scripts/controllers/task_task_attempts_controller.js
@@ -35,6 +35,7 @@ App.TaskAttemptsController = App.TablePageController.extend(App.AutoCounterColum
         this.get('vertex.dag.amWebServiceVersion') != '1' &&
         !this.get('loading') &&
         this.get('isActive') &&
+        this.get('pollingEnabled') &&
         this. get('rowsDisplayed.length') > 0) {
       this.get('pollster').start();
     }
@@ -42,7 +43,7 @@ App.TaskAttemptsController = App.TablePageController.extend(App.AutoCounterColum
       this.get('pollster').stop();
     }
   }.observes('vertex.dag.status',
-    'vertex.dag.amWebServiceVersion', 'rowsDisplayed', 'loading', 'isActive'),
+    'vertex.dag.amWebServiceVersion', 'rowsDisplayed', 'loading', 'isActive', 'pollingEnabled'),
 
   pollsterOptionsObserver: function () {
     this.set('pollster.options', {

http://git-wip-us.apache.org/repos/asf/tez/blob/0e7f54c9/tez-ui/src/main/webapp/app/scripts/controllers/tez-app-controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/controllers/tez-app-controller.js b/tez-ui/src/main/webapp/app/scripts/controllers/tez-app-controller.js
index 33561af..fd25ac6 100644
--- a/tez-ui/src/main/webapp/app/scripts/controllers/tez-app-controller.js
+++ b/tez-ui/src/main/webapp/app/scripts/controllers/tez-app-controller.js
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
 
-App.TezAppController = Em.ObjectController.extend(App.Helpers.DisplayHelper, App.ModelRefreshMixin, {
+App.TezAppController = App.BaseController.extend(App.Helpers.DisplayHelper, App.ModelRefreshMixin, {
   controllerName: 'AppController',
 
   pageTitle: 'App',
@@ -36,22 +36,16 @@ App.TezAppController = Em.ObjectController.extend(App.Helpers.DisplayHelper, App
     });
   },
 
-  setup: function () {
-    this.set('isActive', true);
-  },
-  reset: function () {
-    this.set('isActive', false);
-  },
-
   pollsterControl: function () {
     if(this.get('appDetail.finalAppStatus') == 'UNDEFINED' &&
+        this.get('pollingEnabled') &&
         this.get('isActive')) {
       this.get('pollster').start();
     }
     else {
       this.get('pollster').stop();
     }
-  }.observes('appDetail.finalAppStatus', 'isActive'),
+  }.observes('appDetail.finalAppStatus', 'isActive', 'pollingEnabled'),
 
   load: function () {
     var tezApp = this.get('content'),

http://git-wip-us.apache.org/repos/asf/tez/blob/0e7f54c9/tez-ui/src/main/webapp/app/scripts/controllers/tez-app-dags-controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/controllers/tez-app-dags-controller.js b/tez-ui/src/main/webapp/app/scripts/controllers/tez-app-dags-controller.js
index 3cbecae..5112745 100644
--- a/tez-ui/src/main/webapp/app/scripts/controllers/tez-app-dags-controller.js
+++ b/tez-ui/src/main/webapp/app/scripts/controllers/tez-app-dags-controller.js
@@ -25,6 +25,8 @@ App.TezAppDagsController = App.TablePageController.extend({
   filterEntityType: 'tezApp',
   filterEntityId: Ember.computed.alias('appId'),
 
+  showAutoUpdate: false,
+
   afterLoad: function () {
     var data = this.get('data'),
         loaders = [],

http://git-wip-us.apache.org/repos/asf/tez/blob/0e7f54c9/tez-ui/src/main/webapp/app/scripts/controllers/tez-app-index-controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/controllers/tez-app-index-controller.js b/tez-ui/src/main/webapp/app/scripts/controllers/tez-app-index-controller.js
index 27c83e7..1f58c82 100644
--- a/tez-ui/src/main/webapp/app/scripts/controllers/tez-app-index-controller.js
+++ b/tez-ui/src/main/webapp/app/scripts/controllers/tez-app-index-controller.js
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
 
-App.TezAppIndexController = Em.ObjectController.extend(App.ModelRefreshMixin, {
+App.TezAppIndexController = App.PollingController.extend(App.ModelRefreshMixin, {
 
   needs: "tezApp",
   controllerName: 'TezAppIndexController',

http://git-wip-us.apache.org/repos/asf/tez/blob/0e7f54c9/tez-ui/src/main/webapp/app/scripts/controllers/vertex_controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/controllers/vertex_controller.js b/tez-ui/src/main/webapp/app/scripts/controllers/vertex_controller.js
index a7b8ac7..e6e58a5 100644
--- a/tez-ui/src/main/webapp/app/scripts/controllers/vertex_controller.js
+++ b/tez-ui/src/main/webapp/app/scripts/controllers/vertex_controller.js
@@ -22,27 +22,20 @@ App.VertexController = App.PollingController.extend(App.Helpers.DisplayHelper, A
   pageTitle: 'Vertex',
 
   loading: true,
-  isActive: false,
 
   pollingType: 'vertexInfo',
 
-  setup: function () {
-    this.set('isActive', true);
-  },
-  reset: function () {
-    this.set('isActive', false);
-  },
-
   pollsterControl: function () {
     if(this.get('dag.status') == 'RUNNING' &&
         this.get('dag.amWebServiceVersion') != '1' &&
+        this.get('pollingEnabled') &&
         this.get('isActive')) {
       this.get('pollster').start();
     }
     else {
       this.get('pollster').stop();
     }
-  }.observes('dag.status', 'dag.amWebServiceVersion', 'isActive'),
+  }.observes('dag.status', 'dag.amWebServiceVersion', 'isActive', 'pollingEnabled'),
 
   pollsterOptionsObserver: function () {
     var model = this.get('model');

http://git-wip-us.apache.org/repos/asf/tez/blob/0e7f54c9/tez-ui/src/main/webapp/app/scripts/controllers/vertex_index_controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/controllers/vertex_index_controller.js b/tez-ui/src/main/webapp/app/scripts/controllers/vertex_index_controller.js
index cffea22..d379f06 100644
--- a/tez-ui/src/main/webapp/app/scripts/controllers/vertex_index_controller.js
+++ b/tez-ui/src/main/webapp/app/scripts/controllers/vertex_index_controller.js
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
 
-App.VertexIndexController = Em.ObjectController.extend(App.ModelRefreshMixin, {
+App.VertexIndexController = App.BaseController.extend(App.ModelRefreshMixin, {
   controllerName: 'VertexIndexController',
 
   needs: 'vertex',

http://git-wip-us.apache.org/repos/asf/tez/blob/0e7f54c9/tez-ui/src/main/webapp/app/scripts/controllers/vertex_task_attempts_controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/controllers/vertex_task_attempts_controller.js b/tez-ui/src/main/webapp/app/scripts/controllers/vertex_task_attempts_controller.js
index 8f1e8f5..750bd92 100644
--- a/tez-ui/src/main/webapp/app/scripts/controllers/vertex_task_attempts_controller.js
+++ b/tez-ui/src/main/webapp/app/scripts/controllers/vertex_task_attempts_controller.js
@@ -35,13 +35,14 @@ App.VertexTaskAttemptsController = App.TablePageController.extend(App.AutoCounte
         this.get('dag.amWebServiceVersion') != '1' &&
         !this.get('loading') &&
         this.get('isActive') &&
-        this. get('rowsDisplayed.length') > 0) {
+        this.get('pollingEnabled') &&
+        this.get('rowsDisplayed.length') > 0) {
       this.get('pollster').start();
     }
     else {
       this.get('pollster').stop();
     }
-  }.observes('dag.status', 'dag.amWebServiceVersion', 'rowsDisplayed', 'loading', 'isActive'),
+  }.observes('dag.status', 'dag.amWebServiceVersion', 'rowsDisplayed', 'loading', 'isActive', 'pollingEnabled'),
 
   pollsterOptionsObserver: function () {
     this.set('pollster.options', {

http://git-wip-us.apache.org/repos/asf/tez/blob/0e7f54c9/tez-ui/src/main/webapp/app/scripts/controllers/vertex_tasks_controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/controllers/vertex_tasks_controller.js b/tez-ui/src/main/webapp/app/scripts/controllers/vertex_tasks_controller.js
index 88b8dee..bb7e292 100644
--- a/tez-ui/src/main/webapp/app/scripts/controllers/vertex_tasks_controller.js
+++ b/tez-ui/src/main/webapp/app/scripts/controllers/vertex_tasks_controller.js
@@ -34,13 +34,14 @@ App.VertexTasksController = App.TablePageController.extend(App.AutoCounterColumn
     if(this.get('dag.status') == 'RUNNING' &&
         this.get('dag.amWebServiceVersion') != '1' &&
         !this.get('loading') && this.get('isActive') &&
-        this. get('rowsDisplayed.length') > 0) {
+        this.get('pollingEnabled') &&
+        this.get('rowsDisplayed.length') > 0) {
       this.get('pollster').start();
     }
     else {
       this.get('pollster').stop();
     }
-  }.observes('dag.status', 'dag.amWebServiceVersion', 'rowsDisplayed', 'loading', 'isActive'),
+  }.observes('dag.status', 'dag.amWebServiceVersion', 'rowsDisplayed', 'loading', 'isActive', 'pollingEnabled'),
 
   pollsterOptionsObserver: function () {
     this.set('pollster.options', {

http://git-wip-us.apache.org/repos/asf/tez/blob/0e7f54c9/tez-ui/src/main/webapp/app/scripts/helpers/entity-array-pollster.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/helpers/entity-array-pollster.js b/tez-ui/src/main/webapp/app/scripts/helpers/entity-array-pollster.js
index 4cf97cf..8557b56 100644
--- a/tez-ui/src/main/webapp/app/scripts/helpers/entity-array-pollster.js
+++ b/tez-ui/src/main/webapp/app/scripts/helpers/entity-array-pollster.js
@@ -37,8 +37,8 @@ App.Helpers.EntityArrayPollster = App.Helpers.Pollster.extend({
 
   start: function(interval) {
     if(!this.get('isRunning')) {
-      this._super(true, interval);
       this.set('isRunning', true);
+      this._super(true, interval);
     }
   },
 
@@ -61,11 +61,11 @@ App.Helpers.EntityArrayPollster = App.Helpers.Pollster.extend({
     }
   },
 
-  _optionObserver: function () {
-    if(this.get('options')) {
-      Em.run.later(this, this.onPoll, 10);
+  _preRequisitesObserver: function () {
+    if(this.get('isRunning')) {
+      this.onPoll();
     }
-  }.observes('options'),
+  }.observes('options', 'targetRecords'),
 
   _callIfRunning: function (that, funName) {
     return function (data) {

http://git-wip-us.apache.org/repos/asf/tez/blob/0e7f54c9/tez-ui/src/main/webapp/app/scripts/router.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/router.js b/tez-ui/src/main/webapp/app/scripts/router.js
index ab551a1..ceb8dd9 100644
--- a/tez-ui/src/main/webapp/app/scripts/router.js
+++ b/tez-ui/src/main/webapp/app/scripts/router.js
@@ -62,10 +62,6 @@ App.Router.map(function() {
 
 /* --- Router helper functions --- */
 
-function renderTableWithSpinner () {
-  this.render('common/table-with-spinner');
-}
-
 function renderSwimlanes () {
   this.render('common/swimlanes');
 }
@@ -116,6 +112,24 @@ function setupControllerFactory(format) {
   };
 }
 
+/* --- Base route class --- */
+App.BaseRoute = Em.Route.extend({
+  setupController: setupControllerFactory(),
+  resetController: function() {
+    if(this.controller.reset) {
+      this.controller.reset();
+    }
+  },
+  actions: {
+    pollingEnabledChanged: function (enabled) {
+      if(this.get('controller.pollster')) {
+        this.set('controller.pollingEnabled', enabled);
+      }
+      return true;
+    }
+  }
+});
+
 App.ApplicationRoute = Em.Route.extend({
   actions: {
     willTransition: function(transition) {
@@ -129,12 +143,12 @@ App.ApplicationRoute = Em.Route.extend({
       var err = App.Helpers.misc.formatError(error, defaultError);
       var msg = 'error code: %@, message: %@'.fmt(err.errCode, err.msg);
       App.Helpers.ErrorBar.getInstance().show(msg, error.details);
-    }
+    },
   }
 });
 /* --- Dag related routes --- */
 
-App.DagsRoute = Em.Route.extend({
+App.DagsRoute = App.BaseRoute.extend({
   queryParams:  {
     count: App.Helpers.misc.defaultQueryParamsConfig,
     fromID: App.Helpers.misc.defaultQueryParamsConfig,
@@ -146,7 +160,7 @@ App.DagsRoute = Em.Route.extend({
   setupController: setupControllerFactory('All Dags'),
 });
 
-App.DagRoute = Em.Route.extend({
+App.DagRoute = App.BaseRoute.extend({
   model: function(params) {
     return this.store.find('dag', params.dag_id);
   },
@@ -154,18 +168,13 @@ App.DagRoute = Em.Route.extend({
     return this.controllerFor('dag').loadAdditional(model);
   },
   setupController: setupControllerFactory('Dag: %@ (%@)', 'name', 'id'),
-  resetController: function() {
-    if(this.controller.reset) {
-      this.controller.reset();
-    }
-  }
 });
 
-App.DagViewRoute = Em.Route.extend({
+App.DagViewRoute = App.BaseRoute.extend({
   setupController: setupControllerFactory()
 });
 
-App.DagSwimlaneRoute = Em.Route.extend({
+App.DagSwimlaneRoute = App.BaseRoute.extend({
   renderTemplate: renderSwimlanes,
   model: function(params) {
     var model = this.modelFor('dag'),
@@ -178,50 +187,40 @@ App.DagSwimlaneRoute = Em.Route.extend({
 
 /* --- Task related routes --- */
 
-App.TaskRoute = Em.Route.extend({
+App.TaskRoute = App.BaseRoute.extend({
   model: function(params) {
     return this.store.find('task', params.task_id);
   },
   afterModel: function(model) {
     return this.controllerFor('task').loadAdditional(model);
   },
-  resetController: function () {
-    if(this.controller.reset) {
-      this.controller.reset();
-    }
-  },
   setupController: setupControllerFactory('Task: %@', 'id')
 });
 
-App.TasksRoute = Em.Route.extend({
+App.TasksRoute = App.BaseRoute.extend({
   setupController: setupControllerFactory()
 });
 
 /* --- Vertex related routes --- */
 
-App.VertexRoute = Em.Route.extend({
+App.VertexRoute = App.BaseRoute.extend({
   model: function(params) {
     return this.store.find('vertex', params.vertex_id);
   },
-  resetController: function () {
-    if(this.controller.reset) {
-      this.controller.reset();
-    }
-  },
   afterModel: function(model) {
     return this.controllerFor('vertex').loadAdditional(model);
   },
   setupController: setupControllerFactory('Vertex: %@ (%@)', 'name', 'id')
 });
 
-App.VertexAdditionalsRoute = Em.Route.extend({
+App.VertexAdditionalsRoute = App.BaseRoute.extend({
   setupController: function(controller, model) {
     this._super(controller, model);
     controller.loadEntities();
   }
 });
 
-App.InputRoute = Em.Route.extend({
+App.InputRoute = App.BaseRoute.extend({
   model: function (params) {
     var model = this.modelFor('vertex');
     return model.get('inputs').findBy('id', params.input_id);
@@ -229,7 +228,7 @@ App.InputRoute = Em.Route.extend({
   setupController: setupControllerFactory()
 });
 
-App.OutputRoute = Em.Route.extend({
+App.OutputRoute = App.BaseRoute.extend({
   model: function (params) {
     var model = this.modelFor('vertex');
     return model.get('outputs').findBy('id', params.input_id);
@@ -237,7 +236,7 @@ App.OutputRoute = Em.Route.extend({
   setupController: setupControllerFactory()
 });
 
-App.VertexSwimlaneRoute = Em.Route.extend({
+App.VertexSwimlaneRoute = App.BaseRoute.extend({
   renderTemplate: renderSwimlanes,
   model: function(params) {
     var model = this.modelFor('vertex'),
@@ -250,34 +249,24 @@ App.VertexSwimlaneRoute = Em.Route.extend({
 
 /* --- Task Attempt related routes--- */
 
-App.TaskAttemptRoute = Em.Route.extend({
+App.TaskAttemptRoute = App.BaseRoute.extend({
   model: function(params) {
     return this.store.find('task_attempt', params.task_attempt_id);
   },
   afterModel: function(model) {
     return this.controllerFor('task_attempt').loadAdditional(model);
   },
-  resetController: function () {
-    if(this.controller.reset) {
-      this.controller.reset();
-    }
-  },
   setupController: setupControllerFactory('Task Attempt: %@', 'id')
 });
 
-App.TaskAttemptsRoute = Em.Route.extend({
+App.TaskAttemptsRoute = App.BaseRoute.extend({
   renderTemplate: renderTable,
-  resetController: function () {
-    if(this.controller.reset) {
-      this.controller.reset();
-    }
-  },
   setupController: setupControllerFactory('Task Attempt: %@', 'id')
 });
 
 /* --- Tez-app related routes --- */
 
-App.TezAppRoute = Em.Route.extend({
+App.TezAppRoute = App.BaseRoute.extend({
   model: function(params) {
     var store = this.store;
     return store.find('tezApp', 'tez_' + params.app_id).then(function (tezApp){
@@ -290,35 +279,20 @@ App.TezAppRoute = Em.Route.extend({
       });
     });
   },
-  resetController: function () {
-    if(this.controller.reset) {
-      this.controller.reset();
-    }
-  },
   setupController: setupControllerFactory('Application: %@', 'id')
 });
 
-App.TezAppDagsRoute = Em.Route.extend({
+App.TezAppDagsRoute = App.BaseRoute.extend({
   renderTemplate: renderTable,
-  resetController: function () {
-    if(this.controller.reset) {
-      this.controller.reset();
-    }
-  },
   setupController: setupControllerFactory()
 });
 
-App.TezAppConfigsRoute = Em.Route.extend({
+App.TezAppConfigsRoute = App.BaseRoute.extend({
   renderTemplate: renderConfigs
 });
 
 /* --- Shared routes --- */
-App.DagIndexRoute = Em.Route.extend({
-  resetController: function () {
-    if(this.controller.reset) {
-      this.controller.reset();
-    }
-  },
+App.DagIndexRoute = App.BaseRoute.extend({
   setupController: setupControllerFactory()
 });
 
@@ -327,12 +301,7 @@ App.DagTasksRoute =
     App.DagTaskAttemptsRoute =
     App.VertexTasksRoute =
     App.VertexTaskAttemptsRoute =
-    Em.Route.extend({
-      resetController: function () {
-        if(this.controller.reset) {
-          this.controller.reset();
-        }
-      },
+    App.BaseRoute.extend({
       renderTemplate: renderTable,
       setupController: setupControllerFactory()
     });
@@ -341,12 +310,7 @@ App.DagCountersRoute =
     App.VertexCountersRoute =
     App.TaskCountersRoute =
     App.TaskAttemptCountersRoute =
-    Em.Route.extend({
-      resetController: function () {
-        if(this.controller.reset) {
-          this.controller.reset();
-        }
-      },
+    App.BaseRoute.extend({
       renderTemplate: function() {
         this.render('common/counters');
       }

http://git-wip-us.apache.org/repos/asf/tez/blob/0e7f54c9/tez-ui/src/main/webapp/app/styles/main.less
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/styles/main.less b/tez-ui/src/main/webapp/app/styles/main.less
index 51e28e8..1344edf 100644
--- a/tez-ui/src/main/webapp/app/styles/main.less
+++ b/tez-ui/src/main/webapp/app/styles/main.less
@@ -76,6 +76,13 @@ body, html {
       top: 2px;
     }
 
+    .auto-update {
+      .inline-block;
+      .align-checknradio;
+
+      padding-left: 10px;
+    }
+
     .align-children-right {
       vertical-align: top;
     }

http://git-wip-us.apache.org/repos/asf/tez/blob/0e7f54c9/tez-ui/src/main/webapp/app/styles/shared.less
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/styles/shared.less b/tez-ui/src/main/webapp/app/styles/shared.less
index fc6b9f5..07befa4 100644
--- a/tez-ui/src/main/webapp/app/styles/shared.less
+++ b/tez-ui/src/main/webapp/app/styles/shared.less
@@ -45,6 +45,11 @@
   pointer-events: none;
 }
 
+.inactive {
+  .no-pointer;
+  opacity: 0.4;
+}
+
 .no-wrap {
   white-space: nowrap;
 }
@@ -100,4 +105,12 @@
     background-color: #EEE;
     border-radius: 8px;
   }
-}
\ No newline at end of file
+}
+
+.align-checknradio {
+  input[type=checkbox], input[type=radio] {
+    vertical-align: middle;
+    position: relative;
+    bottom: .2em;
+  }
+}

http://git-wip-us.apache.org/repos/asf/tez/blob/0e7f54c9/tez-ui/src/main/webapp/app/templates/components/load-time.hbs
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/templates/components/load-time.hbs b/tez-ui/src/main/webapp/app/templates/components/load-time.hbs
index 3f6881f..90bac27 100644
--- a/tez-ui/src/main/webapp/app/templates/components/load-time.hbs
+++ b/tez-ui/src/main/webapp/app/templates/components/load-time.hbs
@@ -20,6 +20,16 @@
   <div class="panel-body">
     <div class="horizontal-half">
       <i class='fa fa-clock-o'></i>
+
+      {{#if targetObject.showAutoUpdate}}
+        <div class="auto-update">
+          {{view App.Checkbox
+          classNames='inline-display checkbox'
+          checked=targetObject.pollingEnabled
+          }}
+          Auto Refresh
+        </div>
+      {{/if}}
     </div><div class="horizontal-half align-children-right">
       <span class="margin-small-horizontal">
         {{#if displayTime}}