You are viewing a plain text version of this content. The canonical link for it is here.
Posted to mapreduce-commits@hadoop.apache.org by ac...@apache.org on 2011/09/08 22:59:35 UTC

svn commit: r1166901 - in /hadoop/common/trunk/hadoop-mapreduce-project: ./ hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/ hadoop-mapreduce-client/hadoop-mapreduce-client-hs/ hadoop-mapreduc...

Author: acmurthy
Date: Thu Sep  8 20:59:34 2011
New Revision: 1166901

URL: http://svn.apache.org/viewvc?rev=1166901&view=rev
Log:
MAPREDUCE-2677. Fixed 404 for some links from HistoryServer. Contributed by Robert Evans.

Added:
    hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsAboutPage.java
    hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsCountersPage.java
    hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsJobPage.java
    hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsNavBlock.java
    hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsTaskPage.java
    hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsTasksPage.java
    hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsWebApp.java
Modified:
    hadoop/common/trunk/hadoop-mapreduce-project/CHANGES.txt
    hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/App.java
    hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/AppController.java
    hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/AttemptsPage.java
    hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/NavBlock.java
    hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/TaskPage.java
    hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/TasksBlock.java
    hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/pom.xml
    hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/CompletedJob.java
    hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/HistoryClientService.java
    hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HSWebApp.java
    hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsController.java
    hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsView.java
    hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/test/java/org/apache/hadoop/mapreduce/v2/hs/webapp/TestHSWebApp.java
    hadoop/common/trunk/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/webapp/view/HtmlPage.java
    hadoop/common/trunk/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/webapp/view/TwoColumnLayout.java

Modified: hadoop/common/trunk/hadoop-mapreduce-project/CHANGES.txt
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-mapreduce-project/CHANGES.txt?rev=1166901&r1=1166900&r2=1166901&view=diff
==============================================================================
--- hadoop/common/trunk/hadoop-mapreduce-project/CHANGES.txt (original)
+++ hadoop/common/trunk/hadoop-mapreduce-project/CHANGES.txt Thu Sep  8 20:59:34 2011
@@ -1236,6 +1236,9 @@ Release 0.23.0 - Unreleased
    MAPREDUCE-2844. Fixed display of nodes in UI. (Ravi Teja Ch N V via
    acmurthy) 
 
+   MAPREDUCE-2677. Fixed 404 for some links from HistoryServer. (Robert Evans
+   via acmurthy) 
+
 Release 0.22.0 - Unreleased
 
   INCOMPATIBLE CHANGES

Modified: hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/App.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/App.java?rev=1166901&r1=1166900&r2=1166901&view=diff
==============================================================================
--- hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/App.java (original)
+++ hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/App.java Thu Sep  8 20:59:34 2011
@@ -28,11 +28,27 @@ import org.apache.hadoop.mapreduce.v2.ap
 @RequestScoped
 public class App {
   final AppContext context;
-  Job job;
-  Task task;
+  private Job job;
+  private Task task;
 
   @Inject
   App(AppContext ctx) {
     context = ctx;
   }
+
+  void setJob(Job job) {
+    this.job = job;
+  }
+
+  public Job getJob() {
+    return job;
+  }
+
+  void setTask(Task task) {
+    this.task = task;
+  }
+
+  public Task getTask() {
+    return task;
+  }
 }

Modified: hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/AppController.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/AppController.java?rev=1166901&r1=1166900&r2=1166901&view=diff
==============================================================================
--- hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/AppController.java (original)
+++ hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/AppController.java Thu Sep  8 20:59:34 2011
@@ -31,9 +31,13 @@ import org.apache.hadoop.yarn.conf.YarnC
 import org.apache.hadoop.yarn.util.Apps;
 import org.apache.hadoop.yarn.util.Times;
 import org.apache.hadoop.yarn.webapp.Controller;
+import org.apache.hadoop.yarn.webapp.View;
 
 import com.google.inject.Inject;
 
+/**
+ * This class renders the various pages that the web app supports.
+ */
 public class AppController extends Controller implements AMParams {
   final App app;
   
@@ -50,10 +54,16 @@ public class AppController extends Contr
     this(app, conf, ctx, "am");
   }
 
+  /**
+   * Render the default(index.html) page for the Application Controller
+   */
   @Override public void index() {
     setTitle(join("MapReduce Application ", $(APP_ID)));
   }
 
+  /**
+   * Render the /info page with an overview of current application.
+   */
   public void info() {
     info("Application Master Overview").
       _("Application ID:", $(APP_ID)).
@@ -65,22 +75,52 @@ public class AppController extends Contr
     render(InfoPage.class);
   }
 
+  /**
+   * @return The class that will render the /job page
+   */
+  protected Class<? extends View> jobPage() {
+    return JobPage.class;
+  }
+  
+  /**
+   * Render the /job page
+   */
   public void job() {
     requireJob();
-    render(JobPage.class);
+    render(jobPage());
   }
 
+  /**
+   * @return the class that will render the /jobcounters page
+   */
+  protected Class<? extends View> countersPage() {
+    return CountersPage.class;
+  }
+  
+  /**
+   * Render the /jobcounters page
+   */
   public void jobCounters() {
     requireJob();
-    if (app.job != null) {
+    if (app.getJob() != null) {
       setTitle(join("Counters for ", $(JOB_ID)));
     }
-    render(CountersPage.class);
+    render(countersPage());
   }
 
+  /**
+   * @return the class that will render the /tasks page
+   */
+  protected Class<? extends View> tasksPage() {
+    return TasksPage.class;
+  }
+  
+  /**
+   * Render the /tasks page
+   */
   public void tasks() {
     requireJob();
-    if (app.job != null) {
+    if (app.getJob() != null) {
       try {
         String tt = $(TASK_TYPE);
         tt = tt.isEmpty() ? "All" : StringUtils.capitalize(MRApps.taskType(tt).
@@ -90,20 +130,40 @@ public class AppController extends Contr
         badRequest(e.getMessage());
       }
     }
-    render(TasksPage.class);
+    render(tasksPage());
+  }
+  
+  /**
+   * @return the class that will render the /task page
+   */
+  protected Class<? extends View> taskPage() {
+    return TaskPage.class;
   }
   
+  /**
+   * Render the /task page
+   */
   public void task() {
     requireTask();
-    if (app.task != null) {
+    if (app.getTask() != null) {
       setTitle(join("Attempts for ", $(TASK_ID)));
     }
-    render(TaskPage.class);
+    render(taskPage());
   }
 
+  /**
+   * @return the class that will render the /attempts page
+   */
+  protected Class<? extends View> attemptsPage() {
+    return AttemptsPage.class;
+  }
+  
+  /**
+   * Render the attempts page
+   */
   public void attempts() {
     requireJob();
-    if (app.job != null) {
+    if (app.getJob() != null) {
       try {
         String taskType = $(TASK_TYPE);
         if (taskType.isEmpty()) {
@@ -119,27 +179,38 @@ public class AppController extends Contr
         badRequest(e.getMessage());
       }
     }
-    render(AttemptsPage.class);
+    render(attemptsPage());
   }
 
+  /**
+   * Render a BAD_REQUEST error.
+   * @param s the error message to include.
+   */
   void badRequest(String s) {
     setStatus(response().SC_BAD_REQUEST);
     setTitle(join("Bad request: ", s));
   }
 
+  /**
+   * Render a NOT_FOUND error.
+   * @param s the error message to include.
+   */
   void notFound(String s) {
     setStatus(response().SC_NOT_FOUND);
     setTitle(join("Not found: ", s));
   }
 
+  /**
+   * Ensure that a JOB_ID was passed into the page.
+   */
   void requireJob() {
     try {
       if ($(JOB_ID).isEmpty()) {
         throw new RuntimeException("missing job ID");
       }
       JobId jobID = MRApps.toJobID($(JOB_ID));
-      app.job = app.context.getJob(jobID);
-      if (app.job == null) {
+      app.setJob(app.context.getJob(jobID));
+      if (app.getJob() == null) {
         notFound($(JOB_ID));
       }
     } catch (Exception e) {
@@ -147,18 +218,21 @@ public class AppController extends Contr
     }
   }
 
+  /**
+   * Ensure that a TASK_ID was passed into the page.
+   */
   void requireTask() {
     try {
       if ($(TASK_ID).isEmpty()) {
         throw new RuntimeException("missing task ID");
       }
       TaskId taskID = MRApps.toTaskID($(TASK_ID));
-      app.job = app.context.getJob(taskID.getJobId());
-      if (app.job == null) {
+      app.setJob(app.context.getJob(taskID.getJobId()));
+      if (app.getJob() == null) {
         notFound(MRApps.toString(taskID.getJobId()));
       } else {
-        app.task = app.job.getTask(taskID);
-        if (app.task == null) {
+        app.setTask(app.getJob().getTask(taskID));
+        if (app.getTask() == null) {
           notFound($(TASK_ID));
         }
       }

Modified: hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/AttemptsPage.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/AttemptsPage.java?rev=1166901&r1=1166900&r2=1166901&view=diff
==============================================================================
--- hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/AttemptsPage.java (original)
+++ hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/AttemptsPage.java Thu Sep  8 20:59:34 2011
@@ -57,7 +57,7 @@ public class AttemptsPage extends TaskPa
       String attemptStateStr = $(ATTEMPT_STATE);
       TaskAttemptStateUI neededState = MRApps
           .taskAttemptState(attemptStateStr);
-      for (Task task : super.app.job.getTasks(taskType).values()) {
+      for (Task task : super.app.getJob().getTasks(taskType).values()) {
         Map<TaskAttemptId, TaskAttempt> attempts = task.getAttempts();
         for (TaskAttempt attempt : attempts.values()) {
           if (neededState.correspondsTo(attempt.getState())) {

Modified: hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/NavBlock.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/NavBlock.java?rev=1166901&r1=1166900&r2=1166901&view=diff
==============================================================================
--- hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/NavBlock.java (original)
+++ hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/NavBlock.java Thu Sep  8 20:59:34 2011
@@ -45,8 +45,8 @@ public class NavBlock extends HtmlBlock 
         ul().
           li().a(url("app/info"), "About")._().
           li().a(url("app"), "Jobs")._()._();
-    if (app.job != null) {
-      String jobid = MRApps.toString(app.job.getID());
+    if (app.getJob() != null) {
+      String jobid = MRApps.toString(app.getJob().getID());
       nav.
         h3("Job").
         ul().

Modified: hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/TaskPage.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/TaskPage.java?rev=1166901&r1=1166900&r2=1166901&view=diff
==============================================================================
--- hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/TaskPage.java (original)
+++ hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/TaskPage.java Thu Sep  8 20:59:34 2011
@@ -98,11 +98,11 @@ public class TaskPage extends AppView {
     }
 
     protected boolean isValidRequest() {
-      return app.task != null;
+      return app.getTask() != null;
     }
 
     protected Collection<TaskAttempt> getTaskAttempts() {
-      return app.task.getAttempts().values();
+      return app.getTask().getAttempts().values();
     }
   }
 

Modified: hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/TasksBlock.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/TasksBlock.java?rev=1166901&r1=1166900&r2=1166901&view=diff
==============================================================================
--- hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/TasksBlock.java (original)
+++ hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/TasksBlock.java Thu Sep  8 20:59:34 2011
@@ -42,7 +42,7 @@ public class TasksBlock extends HtmlBloc
   }
 
   @Override protected void render(Block html) {
-    if (app.job == null) {
+    if (app.getJob() == null) {
       html.
         h2($(TITLE));
       return;
@@ -63,7 +63,7 @@ public class TasksBlock extends HtmlBloc
             th("Finish Time").
             th("Elapsed Time")._()._().
         tbody();
-    for (Task task : app.job.getTasks().values()) {
+    for (Task task : app.getJob().getTasks().values()) {
       if (type != null && task.getType() != type) {
         continue;
       }

Modified: hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/pom.xml
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/pom.xml?rev=1166901&r1=1166900&r2=1166901&view=diff
==============================================================================
--- hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/pom.xml (original)
+++ hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/pom.xml Thu Sep  8 20:59:34 2011
@@ -43,6 +43,12 @@
       <type>test-jar</type>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.apache.hadoop</groupId>
+      <artifactId>hadoop-yarn-common</artifactId>
+      <type>test-jar</type>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
   <build>
     <plugins>

Modified: hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/CompletedJob.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/CompletedJob.java?rev=1166901&r1=1166900&r2=1166901&view=diff
==============================================================================
--- hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/CompletedJob.java (original)
+++ hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/CompletedJob.java Thu Sep  8 20:59:34 2011
@@ -279,7 +279,8 @@ public class CompletedJob implements org
 
   @Override
   public boolean isUber() {
-    throw new YarnException("Not yet implemented!");
+    LOG.warn("isUber is not yet implemented");
+    return false;
   }
 
   @Override

Modified: hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/HistoryClientService.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/HistoryClientService.java?rev=1166901&r1=1166900&r2=1166901&view=diff
==============================================================================
--- hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/HistoryClientService.java (original)
+++ hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/HistoryClientService.java Thu Sep  8 20:59:34 2011
@@ -62,7 +62,7 @@ import org.apache.hadoop.mapreduce.v2.ap
 import org.apache.hadoop.mapreduce.v2.api.records.TaskType;
 import org.apache.hadoop.mapreduce.v2.app.job.Job;
 import org.apache.hadoop.mapreduce.v2.app.job.Task;
-import org.apache.hadoop.mapreduce.v2.hs.webapp.HSWebApp;
+import org.apache.hadoop.mapreduce.v2.hs.webapp.HsWebApp;
 import org.apache.hadoop.mapreduce.v2.jobhistory.JHConfig;
 import org.apache.hadoop.mapreduce.v2.security.client.ClientHSSecurityInfo;
 import org.apache.hadoop.net.NetUtils;
@@ -132,7 +132,7 @@ public class HistoryClientService extend
   }
 
   private void initializeWebApp(Configuration conf) {
-    webApp = new HSWebApp(history);
+    webApp = new HsWebApp(history);
     String bindAddress = conf.get(JHConfig.HS_WEBAPP_BIND_ADDRESS,
         JHConfig.DEFAULT_HS_WEBAPP_BIND_ADDRESS);
     WebApps.$for("yarn", this).at(bindAddress).start(webApp); 

Added: hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsAboutPage.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsAboutPage.java?rev=1166901&view=auto
==============================================================================
--- hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsAboutPage.java (added)
+++ hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsAboutPage.java Thu Sep  8 20:59:34 2011
@@ -0,0 +1,52 @@
+/**
+* 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.
+*/
+
+package org.apache.hadoop.mapreduce.v2.hs.webapp;
+
+import static org.apache.hadoop.yarn.webapp.view.JQueryUI.ACCORDION;
+import static org.apache.hadoop.yarn.webapp.view.JQueryUI.initID;
+
+import org.apache.hadoop.util.VersionInfo;
+import org.apache.hadoop.yarn.webapp.SubView;
+import org.apache.hadoop.yarn.webapp.view.InfoBlock;
+
+/**
+ * A Page the shows info about the history server
+ */
+public class HsAboutPage extends HsView {
+
+  /*
+   * (non-Javadoc)
+   * @see org.apache.hadoop.mapreduce.v2.hs.webapp.HsView#preHead(org.apache.hadoop.yarn.webapp.hamlet.Hamlet.HTML)
+   */
+  @Override protected void preHead(Page.HTML<_> html) {
+    commonPreHead(html);
+    //override the nav config from commonPReHead
+    set(initID(ACCORDION, "nav"), "{autoHeight:false, active:0}");
+  }
+
+  /**
+   * The content of this page is the attempts block
+   * @return AttemptsBlock.class
+   */
+  @Override protected Class<? extends SubView> content() {
+    info("History Server").
+      _("BuildVersion", VersionInfo.getBuildVersion());
+    return InfoBlock.class;
+  }
+}

Modified: hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsController.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsController.java?rev=1166901&r1=1166900&r2=1166901&view=diff
==============================================================================
--- hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsController.java (original)
+++ hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsController.java Thu Sep  8 20:59:34 2011
@@ -21,41 +21,123 @@ package org.apache.hadoop.mapreduce.v2.h
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.mapreduce.v2.app.webapp.App;
 import org.apache.hadoop.mapreduce.v2.app.webapp.AppController;
+import org.apache.hadoop.yarn.webapp.View;
 
 import com.google.inject.Inject;
 
+/**
+ * This class renders the various pages that the History Server WebApp supports
+ */
 public class HsController extends AppController {
   
   @Inject HsController(App app, Configuration conf, RequestContext ctx) {
     super(app, conf, ctx, "History");
   }
 
+  /*
+   * (non-Javadoc)
+   * @see org.apache.hadoop.mapreduce.v2.app.webapp.AppController#index()
+   */
   @Override
   public void index() {
-    // TODO Auto-generated method stub
     setTitle("JobHistory");
   }
+  
+  /*
+   * (non-Javadoc)
+   * @see org.apache.hadoop.mapreduce.v2.app.webapp.AppController#jobPage()
+   */
+  @Override
+  protected Class<? extends View> jobPage() {
+    return HsJobPage.class;
+  }
+  
+  /*
+   * (non-Javadoc)
+   * @see org.apache.hadoop.mapreduce.v2.app.webapp.AppController#countersPage()
+   */
+  @Override
+  protected Class<? extends View> countersPage() {
+    return HsCountersPage.class;
+  }
+  
+  /*
+   * (non-Javadoc)
+   * @see org.apache.hadoop.mapreduce.v2.app.webapp.AppController#tasksPage()
+   */
+  @Override
+  protected Class<? extends View> tasksPage() {
+    return HsTasksPage.class;
+  }
+
+  /*
+   * (non-Javadoc)
+   * @see org.apache.hadoop.mapreduce.v2.app.webapp.AppController#taskPage()
+   */
+  @Override
+  protected Class<? extends View> taskPage() {
+    return HsTaskPage.class;
+  }
 
   // Need all of these methods here also as Guice doesn't look into parent
   // classes.
+  
+  /*
+   * (non-Javadoc)
+   * @see org.apache.hadoop.mapreduce.v2.app.webapp.AppController#job()
+   */
+  @Override
   public void job() {
     super.job();
   }
 
+  /*
+   * (non-Javadoc)
+   * @see org.apache.hadoop.mapreduce.v2.app.webapp.AppController#jobCounters()
+   */
+  @Override
   public void jobCounters() {
     super.jobCounters();
   }
 
+  /*
+   * (non-Javadoc)
+   * @see org.apache.hadoop.mapreduce.v2.app.webapp.AppController#tasks()
+   */
+  @Override
   public void tasks() {
     super.tasks();
   }
   
+  /*
+   * (non-Javadoc)
+   * @see org.apache.hadoop.mapreduce.v2.app.webapp.AppController#task()
+   */
+  @Override
   public void task() {
     super.task();
   }
 
+  /*
+   * (non-Javadoc)
+   * @see org.apache.hadoop.mapreduce.v2.app.webapp.AppController#attempts()
+   */
   @Override
   public void attempts() {
     super.attempts();
   }
+  
+  /**
+   * @return the page about the current server.
+   */
+  protected Class<? extends View> aboutPage() {
+    return HsAboutPage.class;
+  }
+  
+  /**
+   * Render a page about the current server.
+   */
+  public void about() {
+    render(aboutPage());
+  }
 }

Added: hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsCountersPage.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsCountersPage.java?rev=1166901&view=auto
==============================================================================
--- hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsCountersPage.java (added)
+++ hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsCountersPage.java Thu Sep  8 20:59:34 2011
@@ -0,0 +1,63 @@
+/**
+* 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.
+*/
+
+package org.apache.hadoop.mapreduce.v2.hs.webapp;
+
+import org.apache.hadoop.mapreduce.v2.app.webapp.CountersBlock;
+import org.apache.hadoop.yarn.webapp.SubView;
+
+import static org.apache.hadoop.yarn.webapp.view.JQueryUI.*;
+
+/**
+ * Render the counters page
+ */
+public class HsCountersPage extends HsView {
+
+  /*
+   * (non-Javadoc)
+   * @see org.apache.hadoop.mapreduce.v2.hs.webapp.HsView#preHead(org.apache.hadoop.yarn.webapp.hamlet.Hamlet.HTML)
+   */
+  @Override protected void preHead(Page.HTML<_> html) {
+    commonPreHead(html);
+    set(initID(ACCORDION, "nav"), "{autoHeight:false, active:1}");
+    set(DATATABLES_SELECTOR, "#counters .dt-counters");
+    set(initSelector(DATATABLES),
+        "{bJQueryUI:true, sDom:'t', iDisplayLength:-1}");
+  }
+
+  /*
+   * (non-Javadoc)
+   * @see org.apache.hadoop.yarn.webapp.view.TwoColumnLayout#postHead(org.apache.hadoop.yarn.webapp.hamlet.Hamlet.HTML)
+   */
+  @Override protected void postHead(Page.HTML<_> html) {
+    html.
+      style("#counters, .dt-counters { table-layout: fixed }",
+            "#counters th { overflow: hidden; vertical-align: center }",
+            "#counters .dataTables_wrapper { min-height: 1em }",
+            "#counters .group { width: 10em }",
+            "#counters .name { width: 30em }");
+  }
+
+  /**
+   * The content of this page is the CountersBlock now.
+   * @return CountersBlock.class
+   */
+  @Override protected Class<? extends SubView> content() {
+    return CountersBlock.class;
+  }
+}

Added: hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsJobPage.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsJobPage.java?rev=1166901&view=auto
==============================================================================
--- hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsJobPage.java (added)
+++ hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsJobPage.java Thu Sep  8 20:59:34 2011
@@ -0,0 +1,54 @@
+/**
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package org.apache.hadoop.mapreduce.v2.hs.webapp;
+
+import static org.apache.hadoop.mapreduce.v2.app.webapp.AMParams.JOB_ID;
+import static org.apache.hadoop.yarn.util.StringHelper.join;
+import static org.apache.hadoop.yarn.webapp.view.JQueryUI.ACCORDION;
+import static org.apache.hadoop.yarn.webapp.view.JQueryUI.initID;
+
+import org.apache.hadoop.mapreduce.v2.app.webapp.JobBlock;
+import org.apache.hadoop.yarn.webapp.SubView;
+
+/**
+ * Render a page that describes a specific job.
+ */
+public class HsJobPage extends HsView {
+
+  /*
+   * (non-Javadoc)
+   * @see org.apache.hadoop.mapreduce.v2.hs.webapp.HsView#preHead(org.apache.hadoop.yarn.webapp.hamlet.Hamlet.HTML)
+   */
+  @Override protected void preHead(Page.HTML<_> html) {
+    String jobID = $(JOB_ID);
+    set(TITLE, jobID.isEmpty() ? "Bad request: missing job ID"
+               : join("MapReduce Job ", $(JOB_ID)));
+    commonPreHead(html);
+    //Override the nav config from the commonPreHead
+    set(initID(ACCORDION, "nav"), "{autoHeight:false, active:1}");
+  }
+
+  /**
+   * The content of this page is the JobBlock
+   * @return JobBlock.class
+   */
+  @Override protected Class<? extends SubView> content() {
+    return JobBlock.class;
+  }
+}

Added: hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsNavBlock.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsNavBlock.java?rev=1166901&view=auto
==============================================================================
--- hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsNavBlock.java (added)
+++ hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsNavBlock.java Thu Sep  8 20:59:34 2011
@@ -0,0 +1,66 @@
+/**
+* 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.
+*/
+
+package org.apache.hadoop.mapreduce.v2.hs.webapp;
+
+import org.apache.hadoop.mapreduce.v2.app.webapp.App;
+import org.apache.hadoop.mapreduce.v2.util.MRApps;
+import org.apache.hadoop.yarn.webapp.hamlet.Hamlet;
+import org.apache.hadoop.yarn.webapp.hamlet.Hamlet.DIV;
+import org.apache.hadoop.yarn.webapp.view.HtmlBlock;
+
+import com.google.inject.Inject;
+
+/**
+ * The navigation block for the history server
+ */
+public class HsNavBlock extends HtmlBlock {
+  final App app;
+
+  @Inject HsNavBlock(App app) { this.app = app; }
+
+  /*
+   * (non-Javadoc)
+   * @see org.apache.hadoop.yarn.webapp.view.HtmlBlock#render(org.apache.hadoop.yarn.webapp.view.HtmlBlock.Block)
+   */
+  @Override protected void render(Block html) {
+    DIV<Hamlet> nav = html.
+      div("#nav").
+      h3("Application").
+        ul().
+          li().a("about", "About")._().
+          li().a(url("app"), "Jobs")._()._();
+    if (app.getJob() != null) {
+      String jobid = MRApps.toString(app.getJob().getID());
+      nav.
+        h3("Job").
+        ul().
+          li().a(url("job", jobid), "Overview")._().
+          li().a(url("jobcounters", jobid), "Counters")._().
+          li().a(url("tasks", jobid, "m"), "Map tasks")._().
+          li().a(url("tasks", jobid, "r"), "Reduce tasks")._()._();
+    }
+    nav.
+      h3("Tools").
+        ul().
+          li().a("/conf", "Configuration")._().
+          li().a("/stacks", "Server stacks")._().
+          li().a("/metrics", "Server metrics")._()._()._().
+    div("#themeswitcher")._();
+  }
+}

Added: hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsTaskPage.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsTaskPage.java?rev=1166901&view=auto
==============================================================================
--- hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsTaskPage.java (added)
+++ hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsTaskPage.java Thu Sep  8 20:59:34 2011
@@ -0,0 +1,159 @@
+/**
+* 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.
+*/
+
+package org.apache.hadoop.mapreduce.v2.hs.webapp;
+
+import static org.apache.hadoop.yarn.util.StringHelper.percent;
+import static org.apache.hadoop.yarn.webapp.view.JQueryUI.ACCORDION;
+import static org.apache.hadoop.yarn.webapp.view.JQueryUI.DATATABLES;
+import static org.apache.hadoop.yarn.webapp.view.JQueryUI.DATATABLES_ID;
+import static org.apache.hadoop.yarn.webapp.view.JQueryUI.initID;
+import static org.apache.hadoop.yarn.webapp.view.JQueryUI.tableInit;
+
+import java.util.Collection;
+
+import org.apache.hadoop.mapreduce.v2.app.job.TaskAttempt;
+import org.apache.hadoop.mapreduce.v2.app.webapp.App;
+import org.apache.hadoop.mapreduce.v2.util.MRApps;
+import org.apache.hadoop.util.StringUtils;
+import org.apache.hadoop.yarn.api.records.ContainerId;
+import org.apache.hadoop.yarn.util.ConverterUtils;
+import org.apache.hadoop.yarn.util.Times;
+import org.apache.hadoop.yarn.webapp.SubView;
+import org.apache.hadoop.yarn.webapp.hamlet.Hamlet;
+import org.apache.hadoop.yarn.webapp.hamlet.Hamlet.TABLE;
+import org.apache.hadoop.yarn.webapp.hamlet.Hamlet.TBODY;
+import org.apache.hadoop.yarn.webapp.hamlet.Hamlet.TD;
+import org.apache.hadoop.yarn.webapp.hamlet.Hamlet.TR;
+import org.apache.hadoop.yarn.webapp.view.HtmlBlock;
+
+import com.google.common.base.Joiner;
+import com.google.inject.Inject;
+
+/**
+ * A Page the shows the status of a given task
+ */
+public class HsTaskPage extends HsView {
+
+  /**
+   * A Block of HTML that will render a given task attempt. 
+   */
+  static class AttemptsBlock extends HtmlBlock {
+    final App app;
+
+    @Inject
+    AttemptsBlock(App ctx) {
+      app = ctx;
+    }
+
+    @Override
+    protected void render(Block html) {
+      if (!isValidRequest()) {
+        html.
+          h2($(TITLE));
+        return;
+      }
+      TBODY<TABLE<Hamlet>> tbody = html.
+      table("#attempts").
+        thead().
+          tr().
+            th(".id", "Attempt").
+            th(".progress", "Progress").
+            th(".state", "State").
+            th(".node", "node").
+            th(".tsh", "Started").
+            th(".tsh", "Finished").
+            th(".tsh", "Elapsed").
+            th(".note", "Note")._()._().
+        tbody();
+      for (TaskAttempt ta : getTaskAttempts()) {
+        String taid = MRApps.toString(ta.getID());
+        String progress = percent(ta.getProgress());
+        ContainerId containerId = ta.getAssignedContainerID();
+
+        String nodeHttpAddr = ta.getNodeHttpAddress();
+        long startTime = ta.getLaunchTime();
+        long finishTime = ta.getFinishTime();
+        long elapsed = Times.elapsed(startTime, finishTime);
+        TD<TR<TBODY<TABLE<Hamlet>>>> nodeTd = tbody.
+          tr().
+            td(".id", taid).
+            td(".progress", progress).
+            td(".state", ta.getState().toString()).
+            td().
+              a(".nodelink", url("http://", nodeHttpAddr), nodeHttpAddr);
+        if (containerId != null) {
+          String containerIdStr = ConverterUtils.toString(containerId);
+          nodeTd._(" ").
+            a(".logslink", url("http://", nodeHttpAddr, "yarn", "containerlogs",
+              containerIdStr), "logs");
+        }
+        nodeTd._().
+          td(".ts", Times.format(startTime)).
+          td(".ts", Times.format(finishTime)).
+          td(".dt", StringUtils.formatTime(elapsed)).
+          td(".note", Joiner.on('\n').join(ta.getDiagnostics()))._();
+      }
+      tbody._()._();
+    }
+
+    /**
+     * @return true if this is a valid request else false.
+     */
+    protected boolean isValidRequest() {
+      return app.getTask() != null;
+    }
+
+    /**
+     * @return all of the attempts to render.
+     */
+    protected Collection<TaskAttempt> getTaskAttempts() {
+      return app.getTask().getAttempts().values();
+    }
+  }
+
+  /*
+   * (non-Javadoc)
+   * @see org.apache.hadoop.mapreduce.v2.hs.webapp.HsView#preHead(org.apache.hadoop.yarn.webapp.hamlet.Hamlet.HTML)
+   */
+  @Override protected void preHead(Page.HTML<_> html) {
+    commonPreHead(html);
+    //override the nav config from commonPReHead
+    set(initID(ACCORDION, "nav"), "{autoHeight:false, active:1}");
+    //Set up the java script and CSS for the attempts table
+    set(DATATABLES_ID, "attempts");
+    set(initID(DATATABLES, "attempts"), attemptsTableInit());
+    setTableStyles(html, "attempts");
+  }
+
+  /**
+   * The content of this page is the attempts block
+   * @return AttemptsBlock.class
+   */
+  @Override protected Class<? extends SubView> content() {
+    return AttemptsBlock.class;
+  }
+
+  /**
+   * @return The end of the JS map that is the jquery datatable config for the
+   * attempts table. 
+   */
+  private String attemptsTableInit() {
+    return tableInit().append("}").toString();
+  }
+}

Added: hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsTasksPage.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsTasksPage.java?rev=1166901&view=auto
==============================================================================
--- hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsTasksPage.java (added)
+++ hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsTasksPage.java Thu Sep  8 20:59:34 2011
@@ -0,0 +1,65 @@
+/**
+* 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.
+*/
+
+package org.apache.hadoop.mapreduce.v2.hs.webapp;
+
+import static org.apache.hadoop.yarn.webapp.view.JQueryUI.ACCORDION;
+import static org.apache.hadoop.yarn.webapp.view.JQueryUI.DATATABLES;
+import static org.apache.hadoop.yarn.webapp.view.JQueryUI.DATATABLES_ID;
+import static org.apache.hadoop.yarn.webapp.view.JQueryUI.initID;
+import static org.apache.hadoop.yarn.webapp.view.JQueryUI.tableInit;
+
+import org.apache.hadoop.mapreduce.v2.app.webapp.TasksBlock;
+import org.apache.hadoop.yarn.webapp.SubView;
+
+/**
+ * A page showing the tasks for a given application.
+ */
+public class HsTasksPage extends HsView {
+
+  /*
+   * (non-Javadoc)
+   * @see org.apache.hadoop.mapreduce.v2.hs.webapp.HsView#preHead(org.apache.hadoop.yarn.webapp.hamlet.Hamlet.HTML)
+   */
+  @Override protected void preHead(Page.HTML<_> html) {
+    commonPreHead(html);
+    set(DATATABLES_ID, "tasks");
+    set(initID(ACCORDION, "nav"), "{autoHeight:false, active:1}");
+    set(initID(DATATABLES, "tasks"), tasksTableInit());
+    setTableStyles(html, "tasks");
+  }
+
+  /**
+   * The content of this page is the TasksBlock
+   * @return TasksBlock.class
+   */
+  @Override protected Class<? extends SubView> content() {
+    return TasksBlock.class;
+  }
+
+  /**
+   * @return the end of the JS map that is the jquery datatable configuration
+   * for the tasks table.
+   */
+  private String tasksTableInit() {
+    return tableInit().
+        append(",aoColumns:[{sType:'title-numeric'},{sType:'title-numeric',").
+        append("bSearchable:false},null,{sType:'title-numeric'},").
+        append("{sType:'title-numeric'},{sType:'title-numeric'}]}").toString();
+  }
+}

Modified: hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsView.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsView.java?rev=1166901&r1=1166900&r2=1166901&view=diff
==============================================================================
--- hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsView.java (original)
+++ hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsView.java Thu Sep  8 20:59:34 2011
@@ -24,7 +24,14 @@ import org.apache.hadoop.yarn.webapp.vie
 
 import static org.apache.hadoop.yarn.webapp.view.JQueryUI.*;
 
+/**
+ * A view that should be used as the base class for all history server pages.
+ */
 public class HsView extends TwoColumnLayout {
+  /*
+   * (non-Javadoc)
+   * @see org.apache.hadoop.yarn.webapp.view.TwoColumnLayout#preHead(org.apache.hadoop.yarn.webapp.hamlet.Hamlet.HTML)
+   */
   @Override protected void preHead(Page.HTML<_> html) {
     commonPreHead(html);
     set(DATATABLES_ID, "jobs");
@@ -32,10 +39,13 @@ public class HsView extends TwoColumnLay
     setTableStyles(html, "jobs");
   }
 
+  /**
+   * The prehead that should be common to all subclasses.
+   * @param html used to render.
+   */
   protected void commonPreHead(Page.HTML<_> html) {
-    //html.meta_http("refresh", "10");
     set(ACCORDION_ID, "nav");
-    set(initID(ACCORDION, "nav"), "{autoHeight:false, active:1}");
+    set(initID(ACCORDION, "nav"), "{autoHeight:false, active:0}");
     set(THEMESWITCHER_ID, "themeswitcher");
   }
 
@@ -43,17 +53,27 @@ public class HsView extends TwoColumnLay
    * (non-Javadoc)
    * @see org.apache.hadoop.yarn.webapp.view.TwoColumnLayout#nav()
    */
-
   @Override
   protected Class<? extends SubView> nav() {
-    return org.apache.hadoop.mapreduce.v2.app.webapp.NavBlock.class;
+    return HsNavBlock.class;
   }
 
+  /*
+   * (non-Javadoc)
+   * @see org.apache.hadoop.yarn.webapp.view.TwoColumnLayout#content()
+   */
   @Override
   protected Class<? extends SubView> content() {
     return JobsBlock.class;
   }
-
+  
+  //TODO We need a way to move all of the javascript/CSS that is for a subview
+  // into that subview.
+  /**
+   * @return The end of a javascript map that is the jquery datatable 
+   * configuration for the jobs table.  the Jobs table is assumed to be
+   * rendered by the class returned from {@link #content()} 
+   */
   private String jobsTableInit() {
     return tableInit().
         append(",aoColumns:[{sType:'title-numeric'},").

Added: hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsWebApp.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsWebApp.java?rev=1166901&view=auto
==============================================================================
--- hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsWebApp.java (added)
+++ hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsWebApp.java Thu Sep  8 20:59:34 2011
@@ -0,0 +1,50 @@
+/**
+* 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.
+*/
+
+package org.apache.hadoop.mapreduce.v2.hs.webapp;
+
+import static org.apache.hadoop.yarn.util.StringHelper.pajoin;
+
+import org.apache.hadoop.mapreduce.v2.app.AppContext;
+import org.apache.hadoop.mapreduce.v2.app.webapp.AMParams;
+import org.apache.hadoop.mapreduce.v2.hs.HistoryContext;
+import org.apache.hadoop.yarn.webapp.WebApp;
+
+public class HsWebApp extends WebApp implements AMParams {
+
+  private HistoryContext history;
+
+  public HsWebApp(HistoryContext history) {
+    this.history = history;
+  }
+
+  @Override
+  public void setup() {
+    bind(AppContext.class).toInstance(history);
+    route("/", HsController.class);
+    route("/app", HsController.class);
+    route(pajoin("/job", JOB_ID), HsController.class, "job");
+    route(pajoin("/jobcounters", JOB_ID), HsController.class, "jobCounters");
+    route(pajoin("/tasks", JOB_ID, TASK_TYPE), HsController.class, "tasks");
+    route(pajoin("/attempts", JOB_ID, TASK_TYPE, ATTEMPT_STATE),
+        HsController.class, "attempts");
+    route(pajoin("/task", TASK_ID), HsController.class, "task");
+    route("/about", HsController.class, "about");
+  }
+}
+

Modified: hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/test/java/org/apache/hadoop/mapreduce/v2/hs/webapp/TestHSWebApp.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/test/java/org/apache/hadoop/mapreduce/v2/hs/webapp/TestHSWebApp.java?rev=1166901&r1=1166900&r2=1166901&view=diff
==============================================================================
--- hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/test/java/org/apache/hadoop/mapreduce/v2/hs/webapp/TestHSWebApp.java (original)
+++ hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/test/java/org/apache/hadoop/mapreduce/v2/hs/webapp/TestHSWebApp.java Thu Sep  8 20:59:34 2011
@@ -1,27 +1,126 @@
 /**
- * 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.
- */
+* 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.
+*/
 
 package org.apache.hadoop.mapreduce.v2.hs.webapp;
 
-import org.apache.hadoop.yarn.webapp.WebApps;
+import static org.apache.hadoop.mapreduce.v2.app.webapp.AMParams.APP_ID;
+import static org.junit.Assert.assertEquals;
+
+import java.util.Map;
+
+import org.apache.hadoop.mapreduce.v2.api.records.JobId;
+import org.apache.hadoop.mapreduce.v2.app.AppContext;
+import org.apache.hadoop.mapreduce.v2.app.MockJobs;
+import org.apache.hadoop.mapreduce.v2.app.job.Job;
+import org.apache.hadoop.yarn.Clock;
+import org.apache.hadoop.yarn.api.records.ApplicationAttemptId;
+import org.apache.hadoop.yarn.api.records.ApplicationId;
+import org.apache.hadoop.yarn.event.EventHandler;
+import org.apache.hadoop.yarn.util.Apps;
+import org.apache.hadoop.yarn.webapp.test.WebAppTests;
+import org.junit.Test;
+
+import com.google.inject.Injector;
 
 public class TestHSWebApp {
-  public static void main(String[] args) {
-    WebApps.$for("yarn").at(19888).start().joinThread();
+
+  static class TestAppContext implements AppContext {
+    final ApplicationAttemptId appAttemptID;
+    final ApplicationId appID;
+    final String user = MockJobs.newUserName();
+    final Map<JobId, Job> jobs;
+    final long startTime = System.currentTimeMillis();
+
+    TestAppContext(int appid, int numJobs, int numTasks, int numAttempts) {
+      appID = MockJobs.newAppID(appid);
+      appAttemptID = MockJobs.newAppAttemptID(appID, 0);
+      jobs = MockJobs.newJobs(appID, numJobs, numTasks, numAttempts);
+    }
+
+    TestAppContext() {
+      this(0, 1, 1, 1);
+    }
+
+    @Override
+    public ApplicationAttemptId getApplicationAttemptId() {
+      return appAttemptID;
+    }
+
+    @Override
+    public ApplicationId getApplicationID() {
+      return appID;
+    }
+
+    @Override
+    public CharSequence getUser() {
+      return user;
+    }
+
+    @Override
+    public Job getJob(JobId jobID) {
+      return jobs.get(jobID);
+    }
+
+    @Override
+    public Map<JobId, Job> getAllJobs() {
+      return jobs; // OK
+    }
+
+    @Override
+    public EventHandler getEventHandler() {
+      return null;
+    }
+
+    @Override
+    public Clock getClock() {
+      return null;
+    }
+
+    @Override
+    public String getApplicationName() {
+      return "TestApp";
+    }
+
+    @Override
+    public long getStartTime() {
+      return startTime;
+    }
+  }
+
+  @Test public void testAppControllerIndex() {
+    TestAppContext ctx = new TestAppContext();
+    Injector injector = WebAppTests.createMockInjector(AppContext.class, ctx);
+    HsController controller = injector.getInstance(HsController.class);
+    controller.index();
+    assertEquals(Apps.toString(ctx.appID), controller.get(APP_ID,""));
+  }
+
+  @Test public void testJobView() {
+    WebAppTests.testPage(HsJobPage.class, AppContext.class, new TestAppContext());
+  }
+
+  @Test public void testTasksView() {
+    WebAppTests.testPage(HsTasksPage.class, AppContext.class,
+                         new TestAppContext());
+  }
+
+  @Test public void testTaskView() {
+    WebAppTests.testPage(HsTaskPage.class, AppContext.class,
+                         new TestAppContext());
   }
 }

Modified: hadoop/common/trunk/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/webapp/view/HtmlPage.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/webapp/view/HtmlPage.java?rev=1166901&r1=1166900&r2=1166901&view=diff
==============================================================================
--- hadoop/common/trunk/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/webapp/view/HtmlPage.java (original)
+++ hadoop/common/trunk/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/webapp/view/HtmlPage.java Thu Sep  8 20:59:34 2011
@@ -26,6 +26,11 @@ import org.apache.hadoop.yarn.webapp.Sub
 import org.apache.hadoop.yarn.webapp.WebAppException;
 import org.apache.hadoop.yarn.webapp.hamlet.Hamlet;
 
+/**
+ * The parent class of all HTML pages.  Override 
+ * {@link #render(org.apache.hadoop.yarn.webapp.hamlet.Hamlet.HTML)}
+ * to actually render the page.
+ */
 public abstract class HtmlPage extends TextView {
 
   public static class _ implements Hamlet._ {
@@ -79,6 +84,10 @@ public abstract class HtmlPage extends T
     }
   }
 
+  /**
+   * Render the the HTML page.
+   * @param html the page to render data to.
+   */
   protected abstract void render(Page.HTML<_> html);
 }
 

Modified: hadoop/common/trunk/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/webapp/view/TwoColumnLayout.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/webapp/view/TwoColumnLayout.java?rev=1166901&r1=1166900&r2=1166901&view=diff
==============================================================================
--- hadoop/common/trunk/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/webapp/view/TwoColumnLayout.java (original)
+++ hadoop/common/trunk/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/webapp/view/TwoColumnLayout.java Thu Sep  8 20:59:34 2011
@@ -18,21 +18,25 @@
 
 package org.apache.hadoop.yarn.webapp.view;
 
-import com.google.common.collect.Lists;
-import com.google.inject.Inject;
-import java.util.List;
+import static org.apache.hadoop.yarn.util.StringHelper.join;
 
-import static org.apache.hadoop.yarn.util.StringHelper.*;
-import static org.apache.hadoop.yarn.webapp.Params.*;
+import java.util.List;
 
 import org.apache.hadoop.yarn.webapp.SubView;
 
+import com.google.common.collect.Lists;
+
 /**
- * A simpler two column layout implementation. Works with resizable themes.
+ * A simpler two column layout implementation with a header, a navigation bar
+ * on the left, content on the right, and a footer. Works with resizable themes.
  * @see TwoColumnCssLayout
  */
 public class TwoColumnLayout extends HtmlPage {
 
+  /*
+   * (non-Javadoc)
+   * @see org.apache.hadoop.yarn.webapp.view.HtmlPage#render(org.apache.hadoop.yarn.webapp.hamlet.Hamlet.HTML)
+   */
   @Override protected void render(Page.HTML<_> html) {
     preHead(html);
     html.
@@ -65,28 +69,55 @@ public class TwoColumnLayout extends Htm
               _(content())._()._()._()._()._();
   }
 
+  /**
+   * Do what needs to be done before the header is rendered.  This usually
+   * involves setting page variables for Javascript and CSS rendering.
+   * @param html the html to use to render. 
+   */
   protected void preHead(Page.HTML<_> html) {
   }
 
+  /**
+   * Do what needs to be done after the header is rendered.
+   * @param html the html to use to render. 
+   */
   protected void postHead(Page.HTML<_> html) {
   }
 
+  /**
+   * @return the class that will render the header of the page.
+   */
   protected Class<? extends SubView> header() {
     return HeaderBlock.class;
   }
 
+  /**
+   * @return the class that will render the content of the page.
+   */
   protected Class<? extends SubView> content() {
     return LipsumBlock.class;
   }
 
+  /**
+   * @return the class that will render the navigation bar.
+   */
   protected Class<? extends SubView> nav() {
     return NavBlock.class;
   }
 
+  /**
+   * @return the class that will render the footer.
+   */
   protected Class<? extends SubView> footer() {
     return FooterBlock.class;
   }
 
+  /**
+   * Sets up a table to be a consistent style.
+   * @param html the HTML to use to render.
+   * @param tableId the ID of the table to set styles on.
+   * @param innerStyles any other styles to add to the table.
+   */
   protected void setTableStyles(Page.HTML<_> html, String tableId,
                                 String... innerStyles) {
     List<String> styles = Lists.newArrayList();