You are viewing a plain text version of this content. The canonical link for it is here.
Posted to common-commits@hadoop.apache.org by om...@apache.org on 2011/03/04 05:32:46 UTC

svn commit: r1077590 [2/2] - in /hadoop/common/branches/branch-0.20-security-patches: ./ bin/ src/core/org/apache/hadoop/http/ src/mapred/org/apache/hadoop/mapred/ src/test/org/apache/hadoop/mapred/ src/webapps/history/ src/webapps/job/

Added: hadoop/common/branches/branch-0.20-security-patches/src/webapps/history/jobhistoryhome.jsp
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-0.20-security-patches/src/webapps/history/jobhistoryhome.jsp?rev=1077590&view=auto
==============================================================================
--- hadoop/common/branches/branch-0.20-security-patches/src/webapps/history/jobhistoryhome.jsp (added)
+++ hadoop/common/branches/branch-0.20-security-patches/src/webapps/history/jobhistoryhome.jsp Fri Mar  4 04:32:45 2011
@@ -0,0 +1,573 @@
+<%@ page
+  contentType="text/html; charset=UTF-8"
+  import="java.io.*"
+  import="java.net.URLEncoder"
+  import="java.util.*"
+  import="java.util.regex.Pattern"
+  import="java.util.regex.Matcher"
+  import="java.util.concurrent.atomic.AtomicBoolean"
+  import="org.apache.hadoop.mapred.*"
+  import="org.apache.hadoop.util.*"
+  import="org.apache.hadoop.fs.*"
+  import="javax.servlet.jsp.*"
+  import="java.text.SimpleDateFormat"
+  import="org.apache.hadoop.http.HtmlQuoting"
+%>
+<%	
+  JobConf jobConf = (JobConf) application.getAttribute("jobConf");
+  String trackerAddress = jobConf.get("mapred.job.tracker.http.address");
+  String trackerName =
+           StringUtils.simpleHostname(trackerAddress);
+%>
+<%!	
+  private static SimpleDateFormat dateFormat = 
+                                    new SimpleDateFormat("d/MM HH:mm:ss");
+%>
+<%!	private static final long serialVersionUID = 1L;
+%>
+<html>
+<head>
+<script type="text/JavaScript">
+<!--
+function showUserHistory(search)
+{
+var url
+if (search == null || "".equals(search)) {
+  url="jobhistoryhome.jsp";
+} else {
+  url="jobhistoryhome.jsp?pageno=1&search=" + search;
+}
+window.location.href = url;
+}
+//-->
+</script>
+<link rel="stylesheet" type="text/css" href="/static/hadoop.css">
+<title><%= trackerName %> Hadoop Map/Reduce History Viewer</title>
+<link rel="stylesheet" type="text/css" href="/static/hadoop.css">
+</head>
+<body>
+<h1> <a href="http://<%=trackerAddress%>/jobtracker.jsp"><%= trackerName %></a> Hadoop Map/Reduce
+     <a href="jobhistoryhome.jsp">History Viewer</a></h1>
+<hr>
+<%
+  //{ // these braces are here to make indentation work and 
+  //  {// must be removed.
+
+    final int JOB_ID_START = 0;
+
+    final int FILENAME_JOBID_END = JOB_ID_START + 3;
+
+    final int FILENAME_SUBMIT_TIMESTAMP_PART = FILENAME_JOBID_END;
+    
+    final int FILENAME_USER_PART = FILENAME_JOBID_END + 1;
+
+    final int FILENAME_JOBNAME_PART = FILENAME_JOBID_END + 2;
+
+    final int[] SCAN_SIZES = { 20, 50, 200 };
+
+    final int FILES_PER_SCAN = 1000;
+
+    final int DEFAULT_PAGE_SIZE = 100;
+
+    final String DEFAULT_DATE_GLOB_COMPONENT = "*/*/*";
+
+    final String SERIAL_NUMBER_GLOB_COMPONENT = "/*";
+
+    final String search = (request.getParameter("search") == null)
+                          ? ""
+                          : request.getParameter("search");
+
+    final String dateSplit[] = search.split(";");
+
+    final String soughtDate = dateSplit.length > 1 ? dateSplit[1] : "";
+
+    final String parts[] = dateSplit[0].split(":");
+
+    final String rawUser = (parts.length >= 1)
+                            ? parts[0].toLowerCase()
+                            : "";
+
+    final String userInFname
+      = escapeUnderscores(JobHistory.JobInfo.encodeJobHistoryFileName(
+            HtmlQuoting.unquoteHtmlChars(rawUser))).toLowerCase();
+
+    final int currentScanSizeIndex
+      = (request.getParameter("scansize") == null)
+           ? 0 : Integer.parseInt(request.getParameter("scansize"));
+
+    final String SEARCH_PARSE_REGEX
+      = "([0-1]?[0-9])/([0-3]?[0-9])/((?:2[0-9])[0-9][0-9])";
+
+    final Pattern dateSearchParse = Pattern.compile(SEARCH_PARSE_REGEX);
+
+    final String rawJobname = (parts.length >= 2)
+                               ? parts[1].toLowerCase()
+                               : "";
+
+    final String jobnameKeywordInFname
+      = escapeUnderscores(JobHistory.JobInfo.encodeJobHistoryFileName(
+            HtmlQuoting.unquoteHtmlChars(rawJobname))).toLowerCase();
+
+    PathFilter jobLogFileFilter = new PathFilter() {
+      private boolean matchUser(String fileName) {
+        // return true if 
+        //  - user is not specified
+        //  - user matches
+        return "".equals(userInFname)
+           || userInFname.equals(fileName.split("_")[FILENAME_USER_PART]
+                .toLowerCase());
+      }
+
+      private boolean matchJobName(String fileName) {
+        // return true if 
+        //  - jobname is not specified
+        //  - jobname contains the keyword
+        return "".equals(jobnameKeywordInFname) 
+                 || fileName.split("_")[FILENAME_JOBNAME_PART].toLowerCase()
+                       .contains(jobnameKeywordInFname);
+      }
+
+      public boolean accept(Path path) {
+        String name = path.getName();
+
+        return !(name.endsWith(".xml")) && matchUser(name) && matchJobName(name);
+      }
+    };
+    
+    FileSystem fs = (FileSystem) application.getAttribute("fileSys");
+    String historyLogDir = (String) application.getAttribute("historyLogDir");
+    if (fs == null) {
+      out.println("Null file system. May be namenode is in safemode!");
+      return;
+    }
+
+    Comparator<Path> lastPathFirst
+      = new Comparator<Path>() {
+          public int compare(Path path1, Path path2) {
+            // these are backwards because we want the lexically lesser names
+            // to occur later in the sort.
+            return path2.getName().compareTo(path1.getName());
+          }
+    };
+
+    Comparator<Path> latestFirstCreationTimeComparator
+      = new Comparator<Path>() {
+          public int compare(Path p1, Path p2) {
+            String dp1 = null;
+            String dp2 = null;
+        
+            try {
+              dp1 = JobHistory.JobInfo.decodeJobHistoryFileName(p1.getName());
+              dp2 = JobHistory.JobInfo.decodeJobHistoryFileName(p2.getName());
+            } catch (IOException ioe) {
+              throw new RuntimeException(ioe);
+            }
+                
+            String[] split1 = dp1.split("_");
+            String[] split2 = dp2.split("_");
+        
+            // compare job tracker start time
+            // reverse the sense, because we want the newest records first
+            int res = new Date(Long.parseLong(split2[1]))
+               .compareTo(new Date(Long.parseLong(split1[1])));
+            // compare the submit times next
+            // again, reverse the sense
+            if (res == 0) {
+              res = new Date(Long.parseLong(split2[3]))
+                .compareTo(new Date(Long.parseLong(split1[3])));
+            }
+            // lastly, compare the serial numbers [a certain tiebreaker]
+            // again, reverse the sense
+            if (res == 0) {
+              Long l1 = Long.parseLong(split2[2]);
+              res = l1.compareTo(Long.parseLong(split1[2]));
+            }
+            return res;
+      }
+    };
+
+    String versionComponent = JobHistory.DONE_DIRECTORY_FORMAT_DIRNAME;
+
+    String trackerComponent = "*";
+
+    // build the glob
+    // first find the date component
+    String dateComponent = DEFAULT_DATE_GLOB_COMPONENT;
+
+    Matcher dateMatcher = dateSearchParse.matcher(soughtDate);
+
+    // burst the sought date: must be [m]m/[d]d/[2y]yy
+    if (dateMatcher.matches()) {
+      String year = dateMatcher.group(3);
+      if (year.length() == 2) {
+        year = "20" + year;
+      }
+
+      String month = dateMatcher.group(1);
+      if (month.length() == 1) {
+        month = "0" + month;
+      }
+
+      String date = dateMatcher.group(2);
+      if (date.length() == 1) {
+        date = "0" + date;
+      }
+
+      dateComponent = year + "/" + month + "/" + date;
+    }
+
+    // now we find all of the serial numbers.  This looks up all the serial
+    // number directories, but not the individual files.
+    Path historyPath = new Path(historyLogDir);
+
+    String leadGlob = (versionComponent
+            + "/" + trackerComponent
+            + "/" + dateComponent);
+
+    // Atomicity is unimportant here.
+    // I would have used MutableBoxedBoolean if such had been provided.
+    AtomicBoolean hasLegacyFiles = new AtomicBoolean(false);
+
+    Path[] snPaths
+      = FileUtil.stat2Paths(JobHistory.localGlobber
+                            (fs, historyPath, "/" + leadGlob, null, hasLegacyFiles));
+
+    Arrays.sort(snPaths, lastPathFirst);
+
+    int arrayLimit = 0;
+    int tranchesSeen = 0;
+
+    Path lastPath = null;
+
+    while (arrayLimit < snPaths.length
+           && tranchesSeen <= SCAN_SIZES[currentScanSizeIndex]) {
+      if (lastPath == null
+          || lastPathFirst.compare(lastPath, snPaths[arrayLimit]) != 0) {
+        ++tranchesSeen;
+        lastPath = snPaths[arrayLimit];
+      }
+
+      ++arrayLimit;
+    }
+
+    if (tranchesSeen > SCAN_SIZES[currentScanSizeIndex]) {
+      --arrayLimit;
+    }
+
+    // arrayLimit points to the first element [which could be element 0] that 
+    // we shouldn't consider
+
+    int numHistoryFiles = 0;
+
+    Path[] jobFiles = null;
+
+    {
+      Path[][] pathVectorVector = new Path[arrayLimit][];
+
+      for (int i = 0; i < arrayLimit; ++i) {
+        pathVectorVector[i]
+          = FileUtil.stat2Paths(fs.listStatus(snPaths[i], jobLogFileFilter));
+        numHistoryFiles += pathVectorVector[i].length;
+      }
+
+      jobFiles = new Path[numHistoryFiles];
+
+      int pathsCursor = 0;
+
+      for (int i = 0; i < arrayLimit; ++i) {
+        System.arraycopy(pathVectorVector[i], 0, jobFiles, pathsCursor,
+                         pathVectorVector[i].length);
+        pathsCursor += pathVectorVector[i].length;
+      }
+    }
+
+    boolean sizeIsExact = arrayLimit == snPaths.length;
+
+    // sizeIsExact will be true if arrayLimit is zero.
+    long lengthEstimate
+      = sizeIsExact ? numHistoryFiles
+                    : (long) numHistoryFiles * snPaths.length / arrayLimit;
+
+    if (hasLegacyFiles.get()) {
+      out.println("<h2>This history has some legacy files.  "
+                  + "<a href=\"legacyjobhistory.jsp\">go to Legacy History Viewer</a>"
+                  + "</h2>");
+    }
+
+    out.println("<!--  user : " + rawUser +
+        ", jobname : " + rawJobname + "-->");
+    if (null == jobFiles || jobFiles.length == 0)  {
+      out.println("No files found!"); 
+      return ; 
+    }
+
+    // get the pageno
+    int pageno = request.getParameter("pageno") == null
+                ? 1
+                : Integer.parseInt(request.getParameter("pageno"));
+
+    // get the total number of files to display
+    int size = DEFAULT_PAGE_SIZE;
+
+    // if show-all is requested or jobfiles < size(100)
+    if (pageno == -1 || size > jobFiles.length) {
+      size = jobFiles.length;
+    }
+
+    if (pageno == -1) { // special case 'show all'
+      pageno = 1;
+    }
+
+    int maxPageNo = (jobFiles.length + size - 1) / size;
+    // int maxPageNo = (int)Math.ceil((float)jobFiles.length / size);
+
+    // check and fix pageno
+    if (pageno < 1 || pageno > maxPageNo) {
+      out.println("Invalid page index");
+      return ;
+    }
+
+    int length = size ; // determine the length of job history files to be displayed
+    if (pageno == maxPageNo) {
+      // find the number of files to be shown on the last page
+      int startOnLast = ((pageno - 1) * size) + 1;
+      length = jobFiles.length - startOnLast + 1;
+    }
+
+    // Display the search box
+    out.println("<form name=search><b> Filter (username:jobname) </b>"); // heading
+    out.println("<input type=text name=search size=\"20\" "
+                + "value=\"" + search + "\">"); // search box
+    out.println("<input type=submit value=\"Filter!\" onClick=\"showUserHistory"
+                + "(document.getElementById('search').value)\"></form>");
+    out.println("<p><span class=\"small\">Specify [user][:jobname keyword(s)]"
+                + "[;MM/DD/YYYY] .  Each of the three components is "
+                + "optional.  Filter components are conjunctive.</span></p>");
+    out.println("<p><span class=\"small\">Example: 'smith' will display jobs"
+                + " submitted by user 'smith'. 'smith:sort' will display "
+                + "jobs from user 'smith' having a 'sort' keyword in the jobname."
+                + " ';07/04/2010' restricts to July 4, 2010</span></p>"); // example
+    out.println("<hr>");
+
+    //Show the status
+    int start = (pageno - 1) * size + 1;
+
+    // DEBUG
+    out.println("<!-- pageno : " + pageno + ", size : " + size + ", length : "
+                + length + ", start : " + start + ", maxpg : "
+                + maxPageNo + "-->");
+
+    out.println("<font size=5><b>Available Jobs in History </b></font>");
+    // display the number of jobs, start index, end index
+    out.println("(<i> <span class=\"small\">Displaying <b>" + length
+                + "</b> jobs from <b>" + start + "</b> to <b>"
+                + (start + length - 1) + "</b> out of "
+                + (sizeIsExact
+                   ? "" : "approximately ") + "<b>"
+                + lengthEstimate + "</b> jobs"
+                + (sizeIsExact
+                   ? ""
+                   : ", <b>" + numHistoryFiles + "</b> gotten"));
+    if (!"".equals(rawUser)) {
+      // show the user if present
+      out.println(" for user <b>" + rawUser + "</b>");
+    }
+    if (!"".equals(rawJobname)) {
+      out.println(" with jobname having the keyword <b>" +
+          rawJobname + "</b> in it.");
+      // show the jobname keyword if present
+    }
+    if (!DEFAULT_DATE_GLOB_COMPONENT.equals(dateComponent)) {
+      out.println(" for the date <b>" + soughtDate + "</b>");
+    }
+    out.print("</span></i>)");
+
+    final String searchPart = "&search=" + search;
+
+    final String scansizePart = "&scansize=" + currentScanSizeIndex;
+
+    final String searchPlusScan = searchPart + scansizePart;
+
+    // show the expand scope link, if we're restricted
+    if (sizeIsExact || currentScanSizeIndex == SCAN_SIZES.length - 1) {
+      out.println("[<span class=\"small\">get more results</span>]");
+    } else {
+      out.println(" [<span class=\"small\"><a href=\"jobhistoryhome.jsp?pageno=1"
+                  + searchPart + "&scansize=" + (currentScanSizeIndex + 1)
+                  + "\">get more results</a></span>]");
+    }
+
+    // show the 'show-all' link
+    out.println(" [<span class=\"small\"><a href=\"jobhistoryhome.jsp?pageno=-1"
+                + searchPlusScan + "\">show in one page</a></span>]");
+
+    // show the 'first-page' link
+    if (pageno > 1) {
+      out.println(" [<span class=\"small\"><a href=\"jobhistoryhome.jsp?pageno=1"
+                  + searchPlusScan + "\">first page</a></span>]");
+    } else {
+      out.println("[<span class=\"small\">first page]</span>");
+    }
+
+    // show the 'last-page' link
+    if (pageno < maxPageNo) {
+      out.println(" [<span class=\"small\"><a href=\"jobhistoryhome.jsp?pageno="
+                  + maxPageNo + searchPlusScan + "\">last page</a></span>]");
+    } else {
+      out.println("<span class=\"small\">[last page]</span>");
+    }
+
+    // sort the files on creation time.
+    Arrays.sort(jobFiles, latestFirstCreationTimeComparator);
+
+    out.println("<br><br>");
+
+    // print the navigation info (top)
+    printNavigationTool(pageno, size, maxPageNo, searchPlusScan, out);
+
+    out.print("<table align=center border=2 cellpadding=\"5\" cellspacing=\"2\">");
+    out.print("<tr>");
+    out.print("<td>Job submit time</td>" +
+              "<td>Job Id</td><td>Name</td><td>User</td>") ; 
+    out.print("</tr>"); 
+    
+    Set<String> displayedJobs = new HashSet<String>();
+    for (int i = start - 1; i < start + length - 1; ++i) {
+      Path jobFile = jobFiles[i];
+
+      String fname = jobFile.getName();
+      String marker = JobHistory.nonOccursString(fname);
+      String reescapedFname = JobHistory.replaceStringInstances(fname,
+                  JobHistory.UNDERSCORE_ESCAPE, marker);
+      
+      String decodedJobFileName = 
+          JobHistory.JobInfo.decodeJobHistoryFileName(reescapedFname);
+
+      String[] jobDetails = decodedJobFileName.split("_");
+      String trackerStartTime = jobDetails[1];
+      String jobId = (jobDetails[JOB_ID_START]
+                      + "_" + jobDetails[JOB_ID_START + 1]
+                      + "_" + jobDetails[JOB_ID_START + 2]);
+      String submitTimestamp = jobDetails[FILENAME_SUBMIT_TIMESTAMP_PART];
+      String userName = JobHistory.replaceStringInstances(jobDetails[FILENAME_USER_PART],
+                  marker, JobHistory.UNDERSCORE_ESCAPE);
+      String jobName = JobHistory.replaceStringInstances(jobDetails[FILENAME_JOBNAME_PART],
+                  marker, JobHistory.UNDERSCORE_ESCAPE);
+      
+      // Check if the job is already displayed. There can be multiple job 
+      // history files for jobs that have restarted
+      if (displayedJobs.contains(jobId)) {
+        continue;
+      } else {
+        displayedJobs.add(jobId);
+      }
+      
+      // Encode the logfile name again to cancel the decoding done by the browser
+      String preEncodedJobFileName = 
+          JobHistory.JobInfo.encodeJobHistoryFileName(jobFile.getName());
+
+      String encodedJobFileName = 
+          JobHistory.replaceStringInstances(preEncodedJobFileName, "%5F", "%255F");
+%>
+<center>
+<%	
+      printJob(submitTimestamp, jobId,
+               jobName, userName, new Path(jobFile.getParent(), encodedJobFileName), 
+               out) ; 
+%>
+</center> 
+<%
+    } // end while trackers 
+    out.print("</table>");
+
+    // show the navigation info (bottom)
+    printNavigationTool(pageno, size, maxPageNo, searchPlusScan, out);
+%>
+<%!
+    private void printJob(String timestamp,
+                          String jobId, String jobName,
+                          String user, Path logFile, JspWriter out)
+    throws IOException {
+      out.print("<tr>"); 
+      out.print("<td>" + new Date(Long.parseLong(timestamp)) + "</td>"); 
+      out.print("<td>" + "<a href=\"jobdetailshistory.jsp?logFile=" 
+          + logFile.toString() + "\">" + jobId + "</a></td>");
+      out.print("<td>"
+                + HtmlQuoting.quoteHtmlChars(unescapeUnderscores(jobName))
+                + "</td>"); 
+      out.print("<td>"
+                + HtmlQuoting.quoteHtmlChars(unescapeUnderscores(user))
+                + "</td>"); 
+      out.print("</tr>");
+    }
+
+    private String escapeUnderscores(String rawString) {
+      return convertStrings(rawString, "_", "%5F");
+    }
+
+    private String unescapeUnderscores(String rawString) {
+      return convertStrings(rawString, "%5F", "_");
+    }
+
+    // inefficient if there are a lot of underscores
+    private String convertStrings(String escapedString, String from, String to) {
+      int firstEscape = escapedString.indexOf(from);
+
+      if (firstEscape < 0) {
+        return escapedString;
+      }
+
+      return escapedString.substring(0, firstEscape)
+            + to
+            + unescapeUnderscores(escapedString.substring
+                                    (firstEscape + from.length()));
+    }
+
+    private void printNavigationTool(int pageno, int size, int max,
+                                     String searchPlusScan, JspWriter out)
+         throws IOException {
+      
+      final int NUMBER_INDICES_TO_SHOW = 5;
+
+      int numIndexToShow = NUMBER_INDICES_TO_SHOW; // num indexes to show on either side
+
+      //TODO check this on boundary cases
+      out.print("<center> <");
+
+      // show previous link
+      if (pageno > 1) {
+        out.println("<a href=\"jobhistoryhome.jsp?pageno=" + (pageno - 1)
+                    + searchPlusScan + "\">Previous</a>");
+      }
+
+      // display the numbered index 1 2 3 4
+      int firstPage = pageno - numIndexToShow;
+      if (firstPage < 1) {
+        firstPage = 1; // boundary condition
+      }
+
+      int lastPage = pageno + numIndexToShow;
+      if (lastPage > max) {
+        lastPage = max; // boundary condition
+      }
+
+      // debug
+      out.println("<!--DEBUG : firstPage : " + firstPage + ", lastPage : " + lastPage + " -->");
+
+      for (int i = firstPage; i <= lastPage; ++i) {
+        if (i != pageno) {// needs hyperlink
+          out.println(" <a href=\"jobhistoryhome.jsp?pageno=" + i
+                      + searchPlusScan + "\">" + i + "</a> ");
+        } else { // current page
+          out.println(i);
+        }
+      }
+
+      // show the next link
+      if (pageno < max) {
+        out.println("<a href=\"jobhistoryhome.jsp?pageno=" + (pageno + 1) + searchPlusScan + "\">Next</a>");
+      }
+      out.print("></center>");
+    }
+%> 
+</body></html>

Added: hadoop/common/branches/branch-0.20-security-patches/src/webapps/history/jobtaskshistory.jsp
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-0.20-security-patches/src/webapps/history/jobtaskshistory.jsp?rev=1077590&view=auto
==============================================================================
--- hadoop/common/branches/branch-0.20-security-patches/src/webapps/history/jobtaskshistory.jsp (added)
+++ hadoop/common/branches/branch-0.20-security-patches/src/webapps/history/jobtaskshistory.jsp Fri Mar  4 04:32:45 2011
@@ -0,0 +1,77 @@
+<%@ page
+  contentType="text/html; charset=UTF-8"
+  import="javax.servlet.http.*"
+  import="java.io.*"
+  import="java.util.*"
+  import="org.apache.hadoop.http.HtmlQuoting"
+  import="org.apache.hadoop.mapred.*"
+  import="org.apache.hadoop.fs.*"
+  import="org.apache.hadoop.util.*"
+  import="java.text.SimpleDateFormat"
+  import="org.apache.hadoop.mapred.JobHistory.*"
+%>
+
+<%!	
+  private static SimpleDateFormat dateFormat =
+                                    new SimpleDateFormat("d/MM HH:mm:ss") ; 
+%>
+<%!	private static final long serialVersionUID = 1L;
+%>
+
+<%	
+  String logFile = request.getParameter("logFile");
+  String encodedLogFileName = JobHistory.JobInfo.encodeJobHistoryFilePath(logFile);
+  String jobid = JSPUtil.getJobID(new Path(logFile).getName());
+  String taskStatus = request.getParameter("status"); 
+  String taskType = request.getParameter("taskType"); 
+  
+  FileSystem fs = (FileSystem) application.getAttribute("fileSys");
+  JobConf jobConf = (JobConf) application.getAttribute("jobConf");
+  ACLsManager aclsManager = (ACLsManager) application.getAttribute("aclManager");
+  JobHistory.JobInfo job = JSPUtil.checkAccessAndGetJobInfo(request,
+      response, jobConf, aclsManager, fs, new Path(logFile));
+  if (job == null) {
+    return;
+  }
+  Map<String, JobHistory.Task> tasks = job.getAllTasks(); 
+%>
+<html>
+<body>
+<h2><%=taskStatus%> <%=taskType %> task list for <a href="jobdetailshistory.jsp?logFile=<%=encodedLogFileName%>"><%=jobid %> </a></h2>
+<center>
+<table border="2" cellpadding="5" cellspacing="2">
+<tr><td>Task Id</td><td>Start Time</td><td>Finish Time<br/></td><td>Error</td></tr>
+<%
+  for (JobHistory.Task task : tasks.values()) {
+    if (taskType.equals(task.get(Keys.TASK_TYPE))){
+      Map <String, TaskAttempt> taskAttempts = task.getTaskAttempts();
+      for (JobHistory.TaskAttempt taskAttempt : taskAttempts.values()) {
+        if (taskStatus.equals(taskAttempt.get(Keys.TASK_STATUS)) || 
+          taskStatus.equals("all")){
+          printTask(encodedLogFileName, taskAttempt, out); 
+        }
+      }
+    }
+  }
+%>
+</table>
+<%!
+  private void printTask(String logFile,
+    JobHistory.TaskAttempt attempt, JspWriter out) throws IOException{
+    out.print("<tr>"); 
+    out.print("<td>" + "<a href=\"taskdetailshistory.jsp?logFile="+ logFile
+     +"&tipid="+attempt.get(Keys.TASKID)+"\">" +
+          attempt.get(Keys.TASKID) + "</a></td>");
+    out.print("<td>" + StringUtils.getFormattedTimeWithDiff(dateFormat, 
+          attempt.getLong(Keys.START_TIME), 0 ) + "</td>");
+    out.print("<td>" + StringUtils.getFormattedTimeWithDiff(dateFormat, 
+          attempt.getLong(Keys.FINISH_TIME),
+          attempt.getLong(Keys.START_TIME) ) + "</td>");
+    out.print("<td>" + HtmlQuoting.quoteHtmlChars(attempt.get(Keys.ERROR)) +
+        "</td>");
+    out.print("</tr>"); 
+  }
+%>
+</center>
+</body>
+</html>

Added: hadoop/common/branches/branch-0.20-security-patches/src/webapps/history/legacyjobhistory.jsp
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-0.20-security-patches/src/webapps/history/legacyjobhistory.jsp?rev=1077590&view=auto
==============================================================================
--- hadoop/common/branches/branch-0.20-security-patches/src/webapps/history/legacyjobhistory.jsp (added)
+++ hadoop/common/branches/branch-0.20-security-patches/src/webapps/history/legacyjobhistory.jsp Fri Mar  4 04:32:45 2011
@@ -0,0 +1,321 @@
+<%@ page
+  contentType="text/html; charset=UTF-8"
+  import="java.io.*"
+  import="java.util.*"
+  import="org.apache.hadoop.mapred.*"
+  import="org.apache.hadoop.util.*"
+  import="org.apache.hadoop.fs.*"
+  import="javax.servlet.jsp.*"
+  import="java.text.SimpleDateFormat"
+  import="org.apache.hadoop.http.HtmlQuoting"
+  import="org.apache.hadoop.mapred.*"
+%>
+<%	
+    JobConf jobConf = (JobConf)application.getAttribute("jobConf");
+    String trackerAddress = jobConf.get("mapred.job.tracker.http.address");
+    String trackerName = StringUtils.simpleHostname(trackerAddress);
+%>
+<%!	
+  private static SimpleDateFormat dateFormat = 
+                                    new SimpleDateFormat("d/MM HH:mm:ss");
+%>
+<%!	private static final long serialVersionUID = 1L;
+%>
+<html>
+<head>
+<script type="text/JavaScript">
+<!--
+function showUserHistory(search)
+{
+var url
+if (search == null || "".equals(search)) {
+  url="legacyjobhistory.jsp";
+} else {
+  url="legacyjobhistory.jsp?pageno=1&search=" + search;
+}
+window.location.href = url;
+}
+//-->
+</script>
+<link rel="stylesheet" type="text/css" href="/static/hadoop.css">
+<title><%= trackerName %> Hadoop Map/Reduce History Viewer</title>
+<link rel="stylesheet" type="text/css" href="/static/hadoop.css">
+</head>
+<body>
+<h1> <a href="http://<%=trackerAddress%>/jobtracker.jsp"><%= trackerName %></a> Hadoop Map/Reduce
+     <a href="jobhistoryhome.jsp">History Viewer</a></h1>
+<hr>
+<%
+    final String search = (request.getParameter("search") == null)
+                          ? ""
+                          : request.getParameter("search");
+
+    String parts[] = search.split(":");
+
+    final String user = (parts.length >= 1)
+                        ? parts[0].toLowerCase()
+                        : "";
+    final String jobname = (parts.length >= 2)
+                           ? parts[1].toLowerCase()
+                           : "";
+    PathFilter jobLogFileFilter = new PathFilter() {
+      // unquote params before encoding for search
+      final String uqUser = JobHistory.JobInfo.encodeJobHistoryFileName(
+            HtmlQuoting.unquoteHtmlChars(user));
+      final String uqJobname = JobHistory.JobInfo.encodeJobHistoryFileName(
+            HtmlQuoting.unquoteHtmlChars(jobname));
+      private boolean matchUser(String fileName) {
+        // return true if 
+        //  - user is not specified
+        //  - user matches
+        return "".equals(uqUser) || uqUser.equals(fileName.split("_")[5]);
+      }
+
+      private boolean matchJobName(String fileName) {
+        // return true if 
+        //  - jobname is not specified
+        //  - jobname contains the keyword
+        return "".equals(uqJobname) || fileName.split("_")[6].toLowerCase().contains(uqJobname);
+      }
+
+      public boolean accept(Path path) {
+        return !(path.getName().endsWith(".xml")) && matchUser(path.getName()) && matchJobName(path.getName());
+      }
+    };
+    
+    FileSystem fs = (FileSystem) application.getAttribute("fileSys");
+    String historyLogDir = (String) application.getAttribute("historyLogDir");
+    if (fs == null) {
+      out.println("Null file system. May be namenode is in safemode!");
+      return;
+    }
+    
+    Path[] jobFiles 
+       = JobHistory.filteredStat2Paths(fs.listStatus(new Path(historyLogDir),
+                                                    jobLogFileFilter),
+                                       false, null);
+
+    out.println("<!--  user : " + user +
+        ", jobname : " + jobname + "-->");
+    if (null == jobFiles || jobFiles.length == 0)  {
+      out.println("No files found!"); 
+      return ; 
+    }
+
+    // get the pageno
+    int pageno = request.getParameter("pageno") == null
+                ? 1
+                : Integer.parseInt(request.getParameter("pageno"));
+
+    // get the total number of files to display
+    int size = 100;
+
+    // if show-all is requested or jobfiles < size(100)
+    if (pageno == -1 || size > jobFiles.length) {
+      size = jobFiles.length;
+    }
+
+    if (pageno == -1) { // special case 'show all'
+      pageno = 1;
+    }
+
+    int maxPageNo = (int)Math.ceil((float)jobFiles.length / size);
+
+    // check and fix pageno
+    if (pageno < 1 || pageno > maxPageNo) {
+      out.println("Invalid page index");
+      return ;
+    }
+
+    int length = size ; // determine the length of job history files to be displayed
+    if (pageno == maxPageNo) {
+      // find the number of files to be shown on the last page
+      int startOnLast = ((pageno - 1) * size) + 1;
+      length = jobFiles.length - startOnLast + 1;
+    }
+
+    // Display the search box
+    out.println("<form name=search><b> Filter (username:jobname) </b>"); // heading
+    out.println("<input type=text name=search size=\"20\" value=\"" + search + "\">"); // search box
+    out.println("<input type=submit value=\"Filter!\" onClick=\"showUserHistory(document.getElementById('search').value)\"></form>");
+    out.println("<span class=\"small\">Example: 'smith' will display jobs either submitted by user 'smith'. 'smith:sort' will display jobs from user 'smith' having 'sort' keyword in the jobname.</span>"); // example
+    out.println("<hr>");
+
+    //Show the status
+    int start = (pageno - 1) * size + 1;
+
+    // DEBUG
+    out.println("<!-- pageno : " + pageno + ", size : " + size + ", length : " + length + ", start : " + start + ", maxpg : " + maxPageNo + "-->");
+
+    out.println("<font size=5><b>Available Jobs in History </b></font>");
+    // display the number of jobs, start index, end index
+    out.println("(<i> <span class=\"small\">Displaying <b>" + length + "</b> jobs from <b>" + start + "</b> to <b>" + (start + length - 1) + "</b> out of <b>" + jobFiles.length + "</b> jobs");
+    if (!"".equals(user)) {
+      // show the user if present
+      out.println(" for user <b>" + user + "</b>");
+    }
+    if (!"".equals(jobname)) {
+      out.println(" with jobname having the keyword <b>" +
+          jobname + "</b> in it."); // show the jobname keyword if present
+    }
+    out.print("</span></i>)");
+
+    // show the 'show-all' link
+    out.println(" [<span class=\"small\"><a href=\"legacyjobhistory.jsp?pageno=-1&search=" + search + "\">show all</a></span>]");
+
+    // show the 'first-page' link
+    if (pageno > 1) {
+      out.println(" [<span class=\"small\"><a href=\"legacyjobhistory.jsp?pageno=1&search=" + search + "\">first page</a></span>]");
+    } else {
+      out.println("[<span class=\"small\">first page]</span>");
+    }
+
+    // show the 'last-page' link
+    if (pageno < maxPageNo) {
+      out.println(" [<span class=\"small\"><a href=\"legacyjobhistory.jsp?pageno=" + maxPageNo + "&search=" + search + "\">last page</a></span>]");
+    } else {
+      out.println("<span class=\"small\">[last page]</span>");
+    }
+
+    // sort the files on creation time.
+    Arrays.sort(jobFiles, new Comparator<Path>() {
+      public int compare(Path p1, Path p2) {
+        String dp1 = null;
+        String dp2 = null;
+        
+        try {
+          dp1 = JobHistory.JobInfo.decodeJobHistoryFileName(p1.getName());
+          dp2 = JobHistory.JobInfo.decodeJobHistoryFileName(p2.getName());
+        } catch (IOException ioe) {
+            throw new RuntimeException(ioe);
+        }
+                
+        String[] split1 = dp1.split("_");
+        String[] split2 = dp2.split("_");
+        
+        // compare job tracker start time
+        int res = new Date(Long.parseLong(split1[1])).compareTo(
+                             new Date(Long.parseLong(split2[1])));
+        if (res == 0) {
+          res = new Date(Long.parseLong(split1[3])).compareTo(
+                           new Date(Long.parseLong(split2[3])));
+        }
+        if (res == 0) {
+          Long l1 = Long.parseLong(split1[4]);
+          res = l1.compareTo(Long.parseLong(split2[4]));
+        }
+        return res;
+      }
+    });
+
+    out.println("<br><br>");
+
+    // print the navigation info (top)
+    printNavigation(pageno, size, maxPageNo, search, out);
+
+    out.print("<table align=center border=2 cellpadding=\"5\" cellspacing=\"2\">");
+    out.print("<tr>");
+    out.print("<td>Job tracker Host Name</td>" +
+              "<td>Job tracker Start time</td>" +
+              "<td>Job Id</td><td>Name</td><td>User</td>") ; 
+    out.print("</tr>"); 
+    
+    Set<String> displayedJobs = new HashSet<String>();
+    for (int i = start - 1; i < start + length - 1; ++i) {
+      Path jobFile = jobFiles[i];
+      
+      String decodedJobFileName = 
+          JobHistory.JobInfo.decodeJobHistoryFileName(jobFile.getName());
+
+      String[] jobDetails = decodedJobFileName.split("_");
+      String trackerHostName = jobDetails[0];
+      String trackerStartTime = jobDetails[1];
+      String jobId = jobDetails[2] + "_" +jobDetails[3] + "_" + jobDetails[4] ;
+      String userName = jobDetails[5];
+      String jobName = jobDetails[6];
+      
+      // Check if the job is already displayed. There can be multiple job 
+      // history files for jobs that have restarted
+      if (displayedJobs.contains(jobId)) {
+        continue;
+      } else {
+        displayedJobs.add(jobId);
+      }
+      
+      // Encode the logfile name again to cancel the decoding done by the browser
+      String encodedJobFileName = 
+          JobHistory.JobInfo.encodeJobHistoryFileName(jobFile.getName());
+%>
+<center>
+<%	
+      printJob(trackerHostName, trackerStartTime, jobId,
+               jobName, userName, new Path(jobFile.getParent(), encodedJobFileName), 
+               out) ; 
+%>
+</center> 
+<%
+    } // end while trackers 
+    out.print("</table>");
+
+    // show the navigation info (bottom)
+    printNavigation(pageno, size, maxPageNo, search, out);
+%>
+<%!
+    private void printJob(String trackerHostName, String trackerid,
+                          String jobId, String jobName,
+                          String user, Path logFile, JspWriter out)
+    throws IOException {
+      out.print("<tr>"); 
+      out.print("<td>" + trackerHostName + "</td>"); 
+      out.print("<td>" + new Date(Long.parseLong(trackerid)) + "</td>"); 
+      out.print("<td>" + "<a href=\"jobdetailshistory.jsp?logFile=" 
+          + logFile.toString() + "\">" + jobId + "</a></td>");
+      out.print("<td>" + HtmlQuoting.quoteHtmlChars(jobName) + "</td>"); 
+      out.print("<td>" + HtmlQuoting.quoteHtmlChars(user) + "</td>"); 
+      out.print("</tr>");
+    }
+
+    private void printNavigation(int pageno, int size, int max, String search, 
+                                 JspWriter out) throws IOException {
+      int numIndexToShow = 5; // num indexes to show on either side
+
+      //TODO check this on boundary cases
+      out.print("<center> <");
+
+      // show previous link
+      if (pageno > 1) {
+        out.println("<a href=\"legacyjobhistory.jsp?pageno=" + (pageno - 1) +
+            "&search=" + search + "\">Previous</a>");
+      }
+
+      // display the numbered index 1 2 3 4
+      int firstPage = pageno - numIndexToShow;
+      if (firstPage < 1) {
+        firstPage = 1; // boundary condition
+      }
+
+      int lastPage = pageno + numIndexToShow;
+      if (lastPage > max) {
+        lastPage = max; // boundary condition
+      }
+
+      // debug
+      out.println("<!--DEBUG : firstPage : " + firstPage + ", lastPage : " + lastPage + " -->");
+
+      for (int i = firstPage; i <= lastPage; ++i) {
+        if (i != pageno) {// needs hyperlink
+          out.println(" <a href=\"legacyjobhistory.jsp?pageno=" + i + "&search=" +
+              search + "\">" + i + "</a> ");
+        } else { // current page
+          out.println(i);
+        }
+      }
+
+      // show the next link
+      if (pageno < max) {
+        out.println("<a href=\"legacyjobhistory.jsp?pageno=" + (pageno + 1) + "&search=" + search + "\">Next</a>");
+      }
+      out.print("></center>");
+    }
+%> 
+</body></html>

Added: hadoop/common/branches/branch-0.20-security-patches/src/webapps/history/loadhistory.jsp
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-0.20-security-patches/src/webapps/history/loadhistory.jsp?rev=1077590&view=auto
==============================================================================
--- hadoop/common/branches/branch-0.20-security-patches/src/webapps/history/loadhistory.jsp (added)
+++ hadoop/common/branches/branch-0.20-security-patches/src/webapps/history/loadhistory.jsp Fri Mar  4 04:32:45 2011
@@ -0,0 +1,46 @@
+<%@ page
+  contentType="text/html; charset=UTF-8"
+  import="org.apache.hadoop.mapred.*"
+  import="org.apache.hadoop.fs.*"
+  import="org.apache.hadoop.mapred.JobHistory.*"
+%>
+<%!	private static final long serialVersionUID = 1L;
+%>
+<%
+    PathFilter jobLogFileFilter = new PathFilter() {
+      public boolean accept(Path path) {
+        return !(path.getName().endsWith(".xml"));
+      }
+    };
+
+    FileSystem fs = (FileSystem) application.getAttribute("fileSys");
+    String jobId = request.getParameter("jobid");
+    JobHistory.JobInfo job = (JobHistory.JobInfo)
+                               request.getSession().getAttribute("job");
+    // if session attribute of JobInfo exists and is of different job's,
+    // then remove the attribute
+    // if the job has not yet finished, remove the attribute sothat it 
+    // gets refreshed.
+    boolean isJobComplete = false;
+    if (null != job) {
+      String jobStatus = job.get(Keys.JOB_STATUS);
+      isJobComplete = Values.SUCCESS.name() == jobStatus
+                      || Values.FAILED.name() == jobStatus
+                      || Values.KILLED.name() == jobStatus;
+    }
+    if (null != job && 
+       (!jobId.equals(job.get(Keys.JOBID)) 
+         || !isJobComplete)) {
+      // remove jobInfo from session, keep only one job in session at a time
+      request.getSession().removeAttribute("job"); 
+      job = null ; 
+    }
+	
+    if (null == job) {
+      String jobLogFile = request.getParameter("logFile");
+      job = new JobHistory.JobInfo(jobId); 
+      DefaultJobHistoryParser.parseJobTasks(jobLogFile, job, fs) ; 
+      request.getSession().setAttribute("job", job);
+      request.getSession().setAttribute("fs", fs);
+    }
+%>

Added: hadoop/common/branches/branch-0.20-security-patches/src/webapps/history/taskdetailshistory.jsp
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-0.20-security-patches/src/webapps/history/taskdetailshistory.jsp?rev=1077590&view=auto
==============================================================================
--- hadoop/common/branches/branch-0.20-security-patches/src/webapps/history/taskdetailshistory.jsp (added)
+++ hadoop/common/branches/branch-0.20-security-patches/src/webapps/history/taskdetailshistory.jsp Fri Mar  4 04:32:45 2011
@@ -0,0 +1,134 @@
+<%@ page
+  contentType="text/html; charset=UTF-8"
+  import="javax.servlet.http.*"
+  import="java.io.*"
+  import="java.util.*"
+  import="org.apache.hadoop.http.HtmlQuoting"
+  import="org.apache.hadoop.mapred.*"
+  import="org.apache.hadoop.fs.*"
+  import="org.apache.hadoop.util.*"
+  import="java.text.SimpleDateFormat"
+  import="org.apache.hadoop.mapred.JobHistory.*"
+%>
+
+<%!	private static SimpleDateFormat dateFormat = new SimpleDateFormat("d/MM HH:mm:ss") ; %>
+<%!	private static final long serialVersionUID = 1L;
+%>
+
+<%	
+  String logFile = request.getParameter("logFile");
+  String tipid = request.getParameter("tipid");
+  if (logFile == null || tipid == null) {
+    out.println("Missing job!!");
+    return;
+  }
+  String encodedLogFileName = JobHistory.JobInfo.encodeJobHistoryFilePath(logFile);
+  String jobid = JSPUtil.getJobID(new Path(encodedLogFileName).getName());
+  FileSystem fs = (FileSystem) application.getAttribute("fileSys");
+  JobConf jobConf = (JobConf) application.getAttribute("jobConf");
+  ACLsManager aclsManager = (ACLsManager) application.getAttribute("aclManager");
+  JobHistory.JobInfo job = JSPUtil.checkAccessAndGetJobInfo(request,
+      response, jobConf, aclsManager, fs, new Path(logFile));
+  if (job == null) {
+    return;
+  }
+  JobHistory.Task task = job.getAllTasks().get(tipid); 
+  String type = task.get(Keys.TASK_TYPE);
+%>
+<html>
+<body>
+<h2><%=tipid %> attempts for <a href="jobdetailshistory.jsp?logFile=<%=encodedLogFileName%>"> <%=jobid %> </a></h2>
+<center>
+<table border="2" cellpadding="5" cellspacing="2">
+<tr><td>Task Id</td><td>Start Time</td>
+<%	
+  if (Values.REDUCE.name().equals(type)) {
+%>
+    <td>Shuffle Finished</td><td>Sort Finished</td>
+<%
+  }
+%>
+<td>Finish Time</td><td>Host</td><td>Error</td><td>Task Logs</td>
+<td>Counters</td></tr>
+<%
+  for (JobHistory.TaskAttempt attempt : task.getTaskAttempts().values()) {
+    printTaskAttempt(attempt, type, out, encodedLogFileName);
+  }
+%>
+</table>
+</center>
+<%	
+  if (Values.MAP.name().equals(type)) {
+%>
+<h3>Input Split Locations</h3>
+<table border="2" cellpadding="5" cellspacing="2">
+<%
+    for (String split : StringUtils.split(task.get(Keys.SPLITS)))
+    {
+      out.println("<tr><td>" + split + "</td></tr>");
+    }
+%>
+</table>    
+<%
+  }
+%>
+<%!
+  private void printTaskAttempt(JobHistory.TaskAttempt taskAttempt,
+                                String type, JspWriter out,
+                                String logFile) 
+  throws Exception {
+    out.print("<tr>"); 
+    out.print("<td>" + taskAttempt.get(Keys.TASK_ATTEMPT_ID) + "</td>");
+    out.print("<td>" + StringUtils.getFormattedTimeWithDiff(dateFormat,
+              taskAttempt.getLong(Keys.START_TIME), 0 ) + "</td>"); 
+    if (Values.REDUCE.name().equals(type)) {
+      JobHistory.ReduceAttempt reduceAttempt = 
+            (JobHistory.ReduceAttempt)taskAttempt; 
+      out.print("<td>" + 
+                StringUtils.getFormattedTimeWithDiff(dateFormat, 
+                reduceAttempt.getLong(Keys.SHUFFLE_FINISHED), 
+                reduceAttempt.getLong(Keys.START_TIME)) + "</td>"); 
+      out.print("<td>" + StringUtils.getFormattedTimeWithDiff(dateFormat, 
+                reduceAttempt.getLong(Keys.SORT_FINISHED), 
+                reduceAttempt.getLong(Keys.SHUFFLE_FINISHED)) + "</td>"); 
+    }
+    out.print("<td>"+ StringUtils.getFormattedTimeWithDiff(dateFormat,
+              taskAttempt.getLong(Keys.FINISH_TIME), 
+              taskAttempt.getLong(Keys.START_TIME) ) + "</td>"); 
+    out.print("<td>" + taskAttempt.get(Keys.HOSTNAME) + "</td>");
+    out.print("<td>" + HtmlQuoting.quoteHtmlChars(taskAttempt.get(Keys.ERROR)) +
+        "</td>");
+
+    // Print task log urls
+    out.print("<td>");	
+    String taskLogsUrl = JobHistory.getTaskLogsUrl(taskAttempt);
+    if (taskLogsUrl != null) {
+	    String tailFourKBUrl = taskLogsUrl + "&start=-4097";
+	    String tailEightKBUrl = taskLogsUrl + "&start=-8193";
+	    String entireLogUrl = taskLogsUrl + "&all=true";
+	    out.print("<a href=\"" + tailFourKBUrl + "\">Last 4KB</a><br/>");
+	    out.print("<a href=\"" + tailEightKBUrl + "\">Last 8KB</a><br/>");
+	    out.print("<a href=\"" + entireLogUrl + "\">All</a><br/>");
+    } else {
+        out.print("n/a");
+    }
+    out.print("</td>");
+    Counters counters = 
+      Counters.fromEscapedCompactString(taskAttempt.get(Keys.COUNTERS));
+    if (counters != null) {
+      TaskAttemptID attemptId = 
+        TaskAttemptID.forName(taskAttempt.get(Keys.TASK_ATTEMPT_ID));
+      TaskID tipid = attemptId.getTaskID();
+      org.apache.hadoop.mapreduce.JobID jobId = tipid.getJobID();
+      out.print("<td>" 
+       + "<a href=\"taskstatshistory.jsp?attemptid=" + attemptId
+           + "&logFile=" + logFile + "\">"
+           + counters.size() + "</a></td>");
+    } else {
+      out.print("<td></td>");
+    }
+    out.print("</tr>"); 
+  }
+%>
+</body>
+</html>

Added: hadoop/common/branches/branch-0.20-security-patches/src/webapps/history/taskstatshistory.jsp
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-0.20-security-patches/src/webapps/history/taskstatshistory.jsp?rev=1077590&view=auto
==============================================================================
--- hadoop/common/branches/branch-0.20-security-patches/src/webapps/history/taskstatshistory.jsp (added)
+++ hadoop/common/branches/branch-0.20-security-patches/src/webapps/history/taskstatshistory.jsp Fri Mar  4 04:32:45 2011
@@ -0,0 +1,117 @@
+<%
+/*
+ * 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.
+ */
+%>
+<%@ page
+  contentType="text/html; charset=UTF-8"
+  import="javax.servlet.http.*"
+  import="java.io.*"
+  import="java.util.*"
+  import="org.apache.hadoop.http.HtmlQuoting"
+  import="org.apache.hadoop.mapred.*"
+  import="org.apache.hadoop.fs.*"
+  import="org.apache.hadoop.util.*"
+  import="java.text.*"
+  import="org.apache.hadoop.mapred.JobHistory.*" 
+%>
+<%! private static SimpleDateFormat dateFormat = new SimpleDateFormat("d/MM HH:mm:ss") ;
+    private static final long serialVersionUID = 1L;
+%>
+
+<%
+  String attemptid = request.getParameter("attemptid");
+  if(attemptid == null) {
+    out.println("No attemptid found! Pass a 'attemptid' parameter in the request.");
+    return;
+  }
+  TaskID tipid = TaskAttemptID.forName(attemptid).getTaskID();
+  String logFile = request.getParameter("logFile");
+  String encodedLogFileName = 
+    JobHistory.JobInfo.encodeJobHistoryFilePath(logFile);
+  String jobid = JSPUtil.getJobID(new Path(encodedLogFileName).getName());
+  Format decimal = new DecimalFormat();
+
+  FileSystem fs = (FileSystem) application.getAttribute("fileSys");
+  JobConf jobConf = (JobConf) application.getAttribute("jobConf");
+  ACLsManager aclsManager = (ACLsManager) application.getAttribute("aclManager");
+  JobHistory.JobInfo job = JSPUtil.checkAccessAndGetJobInfo(request,
+      response, jobConf, aclsManager, fs, new Path(logFile));
+  if (job == null) {
+    return;
+  }
+
+  JobHistory.Task task = job.getAllTasks().get(tipid.toString());
+  JobHistory.TaskAttempt attempt = task.getTaskAttempts().get(attemptid);
+
+  Counters counters = 
+    Counters.fromEscapedCompactString(attempt.get(Keys.COUNTERS));
+%>
+
+<html>
+  <head>
+    <title>Counters for <%=attemptid%></title>
+  </head>
+<body>
+<h1>Counters for <%=attemptid%></h1>
+
+<hr>
+
+<%
+  if (counters == null) {
+%>
+    <h3>No counter information found for this attempt</h3>
+<%
+  } else {    
+%>
+    <table>
+<%
+      for (String groupName : counters.getGroupNames()) {
+        Counters.Group group = counters.getGroup(groupName);
+        String displayGroupName = group.getDisplayName();
+%>
+        <tr>
+          <td colspan="3"><br/><b>
+          <%=HtmlQuoting.quoteHtmlChars(displayGroupName)%></b></td>
+        </tr>
+<%
+        Iterator<Counters.Counter> ctrItr = group.iterator();
+        while(ctrItr.hasNext()) {
+          Counters.Counter counter = ctrItr.next();
+          String displayCounterName = counter.getDisplayName();
+          long value = counter.getCounter();
+%>
+          <tr>
+            <td width="50"></td>
+            <td><%=HtmlQuoting.quoteHtmlChars(displayCounterName)%></td>
+            <td align="right"><%=decimal.format(value)%></td>
+          </tr>
+<%
+        }
+      }
+%>
+    </table>
+<%
+  }
+%>
+
+<hr>
+<a href="jobdetailshistory.jsp?logFile=<%=encodedLogFileName%>">Go back to the job</a><br>
+<a href="jobhistoryhome.jsp">Go back to Job History Viewer</a><br>
+<%
+out.println(ServletUtil.htmlFooter());
+%>

Modified: hadoop/common/branches/branch-0.20-security-patches/src/webapps/job/jobdetails.jsp
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-0.20-security-patches/src/webapps/job/jobdetails.jsp?rev=1077590&r1=1077589&r2=1077590&view=diff
==============================================================================
--- hadoop/common/branches/branch-0.20-security-patches/src/webapps/job/jobdetails.jsp (original)
+++ hadoop/common/branches/branch-0.20-security-patches/src/webapps/job/jobdetails.jsp Fri Mar  4 04:32:45 2011
@@ -268,7 +268,8 @@
         out.println("<h2>Job " + jobId + " not known!</h2>");
         return;
       }
-      String historyUrl = "/jobdetailshistory.jsp?logFile=" + 
+      String historyUrl = JobHistoryServer.getHistoryUrlPrefix(tracker.conf) +
+          "/jobdetailshistory.jsp?logFile=" +
           JobHistory.JobInfo.encodeJobHistoryFilePath(historyFile);
       response.sendRedirect(response.encodeRedirectURL(historyUrl));
       return;

Modified: hadoop/common/branches/branch-0.20-security-patches/src/webapps/job/jobhistory.jsp
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-0.20-security-patches/src/webapps/job/jobhistory.jsp?rev=1077590&r1=1077589&r2=1077590&view=diff
==============================================================================
--- hadoop/common/branches/branch-0.20-security-patches/src/webapps/job/jobhistory.jsp (original)
+++ hadoop/common/branches/branch-0.20-security-patches/src/webapps/job/jobhistory.jsp Fri Mar  4 04:32:45 2011
@@ -1,574 +1,33 @@
-<%@ page
-  contentType="text/html; charset=UTF-8"
-  import="java.io.*"
-  import="java.net.URLEncoder"
-  import="java.util.*"
-  import="java.util.regex.Pattern"
-  import="java.util.regex.Matcher"
-  import="java.util.concurrent.atomic.AtomicBoolean"
-  import="org.apache.hadoop.mapred.*"
-  import="org.apache.hadoop.util.*"
-  import="org.apache.hadoop.fs.*"
-  import="javax.servlet.jsp.*"
-  import="java.text.SimpleDateFormat"
-  import="org.apache.hadoop.http.HtmlQuoting"
-  import="org.apache.hadoop.mapred.*"
-  import="org.apache.hadoop.mapred.JobHistory.*"
-%>
-<%	
-  JobTracker tracker = (JobTracker) application.getAttribute("job.tracker");
-  String trackerName =
-           StringUtils.simpleHostname(tracker.getJobTrackerMachine());
-%>
-<%!	
-  private static SimpleDateFormat dateFormat = 
-                                    new SimpleDateFormat("d/MM HH:mm:ss");
-%>
-<%!	private static final long serialVersionUID = 1L;
-%>
-<html>
-<head>
-<script type="text/JavaScript">
-<!--
-function showUserHistory(search)
-{
-var url
-if (search == null || "".equals(search)) {
-  url="jobhistory.jsp";
-} else {
-  url="jobhistory.jsp?pageno=1&search=" + search;
-}
-window.location.href = url;
-}
-//-->
-</script>
-<link rel="stylesheet" type="text/css" href="/static/hadoop.css">
-<title><%= trackerName %> Hadoop Map/Reduce History Viewer</title>
-<link rel="stylesheet" type="text/css" href="/static/hadoop.css">
-</head>
-<body>
-<h1> <a href="jobtracker.jsp"><%= trackerName %></a> Hadoop Map/Reduce 
-     <a href="jobhistory.jsp">History Viewer</a></h1>
-<hr>
 <%
-  //{ // these braces are here to make indentation work and 
-  //  {// must be removed.
-
-    final int JOB_ID_START = 0;
-
-    final int FILENAME_JOBID_END = JOB_ID_START + 3;
-
-    final int FILENAME_SUBMIT_TIMESTAMP_PART = FILENAME_JOBID_END;
-    
-    final int FILENAME_USER_PART = FILENAME_JOBID_END + 1;
-
-    final int FILENAME_JOBNAME_PART = FILENAME_JOBID_END + 2;
-
-    final int[] SCAN_SIZES = { 20, 50, 200 };
-
-    final int FILES_PER_SCAN = 1000;
-
-    final int DEFAULT_PAGE_SIZE = 100;
-
-    final String DEFAULT_DATE_GLOB_COMPONENT = "*/*/*";
-
-    final String SERIAL_NUMBER_GLOB_COMPONENT = "/*";
-
-    final String search = (request.getParameter("search") == null)
-                          ? ""
-                          : request.getParameter("search");
-
-    final String dateSplit[] = search.split(";");
-
-    final String soughtDate = dateSplit.length > 1 ? dateSplit[1] : "";
-
-    final String parts[] = dateSplit[0].split(":");
-
-    final String rawUser = (parts.length >= 1)
-                            ? parts[0].toLowerCase()
-                            : "";
-
-    final String userInFname
-      = escapeUnderscores(JobHistory.JobInfo.encodeJobHistoryFileName(
-            HtmlQuoting.unquoteHtmlChars(rawUser))).toLowerCase();
-
-    final int currentScanSizeIndex
-      = (request.getParameter("scansize") == null)
-           ? 0 : Integer.parseInt(request.getParameter("scansize"));
-
-    final String SEARCH_PARSE_REGEX
-      = "([0-1]?[0-9])/([0-3]?[0-9])/((?:2[0-9])[0-9][0-9])";
-
-    final Pattern dateSearchParse = Pattern.compile(SEARCH_PARSE_REGEX);
-
-    final String rawJobname = (parts.length >= 2)
-                               ? parts[1].toLowerCase()
-                               : "";
-
-    final String jobnameKeywordInFname
-      = escapeUnderscores(JobHistory.JobInfo.encodeJobHistoryFileName(
-            HtmlQuoting.unquoteHtmlChars(rawJobname))).toLowerCase();
-
-    PathFilter jobLogFileFilter = new PathFilter() {
-      private boolean matchUser(String fileName) {
-        // return true if 
-        //  - user is not specified
-        //  - user matches
-        return "".equals(userInFname)
-           || userInFname.equals(fileName.split("_")[FILENAME_USER_PART]
-                .toLowerCase());
-      }
-
-      private boolean matchJobName(String fileName) {
-        // return true if 
-        //  - jobname is not specified
-        //  - jobname contains the keyword
-        return "".equals(jobnameKeywordInFname) 
-                 || fileName.split("_")[FILENAME_JOBNAME_PART].toLowerCase()
-                       .contains(jobnameKeywordInFname);
-      }
-
-      public boolean accept(Path path) {
-        String name = path.getName();
-
-        return !(name.endsWith(".xml")) && matchUser(name) && matchJobName(name);
-      }
-    };
-    
-    FileSystem fs = (FileSystem) application.getAttribute("fileSys");
-    String historyLogDir = (String) application.getAttribute("historyLogDir");
-    if (fs == null) {
-      out.println("Null file system. May be namenode is in safemode!");
-      return;
-    }
-
-    Comparator<Path> lastPathFirst
-      = new Comparator<Path>() {
-          public int compare(Path path1, Path path2) {
-            // these are backwards because we want the lexically lesser names
-            // to occur later in the sort.
-            return path2.getName().compareTo(path1.getName());
-          }
-    };
-
-    Comparator<Path> latestFirstCreationTimeComparator
-      = new Comparator<Path>() {
-          public int compare(Path p1, Path p2) {
-            String dp1 = null;
-            String dp2 = null;
-        
-            try {
-              dp1 = JobHistory.JobInfo.decodeJobHistoryFileName(p1.getName());
-              dp2 = JobHistory.JobInfo.decodeJobHistoryFileName(p2.getName());
-            } catch (IOException ioe) {
-              throw new RuntimeException(ioe);
-            }
-                
-            String[] split1 = dp1.split("_");
-            String[] split2 = dp2.split("_");
-        
-            // compare job tracker start time
-            // reverse the sense, because we want the newest records first
-            int res = new Date(Long.parseLong(split2[1]))
-               .compareTo(new Date(Long.parseLong(split1[1])));
-            // compare the submit times next
-            // again, reverse the sense
-            if (res == 0) {
-              res = new Date(Long.parseLong(split2[3]))
-                .compareTo(new Date(Long.parseLong(split1[3])));
-            }
-            // lastly, compare the serial numbers [a certain tiebreaker]
-            // again, reverse the sense
-            if (res == 0) {
-              Long l1 = Long.parseLong(split2[2]);
-              res = l1.compareTo(Long.parseLong(split1[2]));
-            }
-            return res;
-      }
-    };
-
-    String versionComponent = JobHistory.DONE_DIRECTORY_FORMAT_DIRNAME;
-
-    String trackerComponent = "*";
-
-    // build the glob
-    // first find the date component
-    String dateComponent = DEFAULT_DATE_GLOB_COMPONENT;
-
-    Matcher dateMatcher = dateSearchParse.matcher(soughtDate);
-
-    // burst the sought date: must be [m]m/[d]d/[2y]yy
-    if (dateMatcher.matches()) {
-      String year = dateMatcher.group(3);
-      if (year.length() == 2) {
-        year = "20" + year;
-      }
-
-      String month = dateMatcher.group(1);
-      if (month.length() == 1) {
-        month = "0" + month;
-      }
-
-      String date = dateMatcher.group(2);
-      if (date.length() == 1) {
-        date = "0" + date;
-      }
-
-      dateComponent = year + "/" + month + "/" + date;
-    }
-
-    // now we find all of the serial numbers.  This looks up all the serial
-    // number directories, but not the individual files.
-    Path historyPath = new Path(historyLogDir);
-
-    String leadGlob = (versionComponent
-            + "/" + trackerComponent
-            + "/" + dateComponent);
-
-    // Atomicity is unimportant here.
-    // I would have used MutableBoxedBoolean if such had been provided.
-    AtomicBoolean hasLegacyFiles = new AtomicBoolean(false);
-
-    Path[] snPaths
-      = FileUtil.stat2Paths(JobHistory.localGlobber
-                            (fs, historyPath, "/" + leadGlob, null, hasLegacyFiles));
-
-    Arrays.sort(snPaths, lastPathFirst);
-
-    int arrayLimit = 0;
-    int tranchesSeen = 0;
-
-    Path lastPath = null;
-
-    while (arrayLimit < snPaths.length
-           && tranchesSeen <= SCAN_SIZES[currentScanSizeIndex]) {
-      if (lastPath == null
-          || lastPathFirst.compare(lastPath, snPaths[arrayLimit]) != 0) {
-        ++tranchesSeen;
-        lastPath = snPaths[arrayLimit];
-      }
-
-      ++arrayLimit;
-    }
-
-    if (tranchesSeen > SCAN_SIZES[currentScanSizeIndex]) {
-      --arrayLimit;
-    }
-
-    // arrayLimit points to the first element [which could be element 0] that 
-    // we shouldn't consider
-
-    int numHistoryFiles = 0;
-
-    Path[] jobFiles = null;
-
-    {
-      Path[][] pathVectorVector = new Path[arrayLimit][];
-
-      for (int i = 0; i < arrayLimit; ++i) {
-        pathVectorVector[i]
-          = FileUtil.stat2Paths(fs.listStatus(snPaths[i], jobLogFileFilter));
-        numHistoryFiles += pathVectorVector[i].length;
-      }
-
-      jobFiles = new Path[numHistoryFiles];
-
-      int pathsCursor = 0;
-
-      for (int i = 0; i < arrayLimit; ++i) {
-        System.arraycopy(pathVectorVector[i], 0, jobFiles, pathsCursor,
-                         pathVectorVector[i].length);
-        pathsCursor += pathVectorVector[i].length;
-      }
-    }
-
-    boolean sizeIsExact = arrayLimit == snPaths.length;
-
-    // sizeIsExact will be true if arrayLimit is zero.
-    long lengthEstimate
-      = sizeIsExact ? numHistoryFiles
-                    : (long) numHistoryFiles * snPaths.length / arrayLimit;
-
-    if (hasLegacyFiles.get()) {
-      out.println("<h2>This history has some legacy files.  "
-                  + "<a href=\"legacyjobhistory.jsp\">go to Legacy History Viewer</a>"
-                  + "</h2>");
-    }
-
-    out.println("<!--  user : " + rawUser +
-        ", jobname : " + rawJobname + "-->");
-    if (null == jobFiles || jobFiles.length == 0)  {
-      out.println("No files found!"); 
-      return ; 
-    }
-
-    // get the pageno
-    int pageno = request.getParameter("pageno") == null
-                ? 1
-                : Integer.parseInt(request.getParameter("pageno"));
-
-    // get the total number of files to display
-    int size = DEFAULT_PAGE_SIZE;
-
-    // if show-all is requested or jobfiles < size(100)
-    if (pageno == -1 || size > jobFiles.length) {
-      size = jobFiles.length;
-    }
-
-    if (pageno == -1) { // special case 'show all'
-      pageno = 1;
-    }
-
-    int maxPageNo = (jobFiles.length + size - 1) / size;
-    // int maxPageNo = (int)Math.ceil((float)jobFiles.length / size);
-
-    // check and fix pageno
-    if (pageno < 1 || pageno > maxPageNo) {
-      out.println("Invalid page index");
-      return ;
-    }
-
-    int length = size ; // determine the length of job history files to be displayed
-    if (pageno == maxPageNo) {
-      // find the number of files to be shown on the last page
-      int startOnLast = ((pageno - 1) * size) + 1;
-      length = jobFiles.length - startOnLast + 1;
-    }
-
-    // Display the search box
-    out.println("<form name=search><b> Filter (username:jobname) </b>"); // heading
-    out.println("<input type=text name=search size=\"20\" "
-                + "value=\"" + search + "\">"); // search box
-    out.println("<input type=submit value=\"Filter!\" onClick=\"showUserHistory"
-                + "(document.getElementById('search').value)\"></form>");
-    out.println("<p><span class=\"small\">Specify [user][:jobname keyword(s)]"
-                + "[;MM/DD/YYYY] .  Each of the three components is "
-                + "optional.  Filter components are conjunctive.</span></p>");
-    out.println("<p><span class=\"small\">Example: 'smith' will display jobs"
-                + " submitted by user 'smith'. 'smith:sort' will display "
-                + "jobs from user 'smith' having a 'sort' keyword in the jobname."
-                + " ';07/04/2010' restricts to July 4, 2010</span></p>"); // example
-    out.println("<hr>");
-
-    //Show the status
-    int start = (pageno - 1) * size + 1;
-
-    // DEBUG
-    out.println("<!-- pageno : " + pageno + ", size : " + size + ", length : "
-                + length + ", start : " + start + ", maxpg : "
-                + maxPageNo + "-->");
-
-    out.println("<font size=5><b>Available Jobs in History </b></font>");
-    // display the number of jobs, start index, end index
-    out.println("(<i> <span class=\"small\">Displaying <b>" + length
-                + "</b> jobs from <b>" + start + "</b> to <b>"
-                + (start + length - 1) + "</b> out of "
-                + (sizeIsExact
-                   ? "" : "approximately ") + "<b>"
-                + lengthEstimate + "</b> jobs"
-                + (sizeIsExact
-                   ? ""
-                   : ", <b>" + numHistoryFiles + "</b> gotten"));
-    if (!"".equals(rawUser)) {
-      // show the user if present
-      out.println(" for user <b>" + rawUser + "</b>");
-    }
-    if (!"".equals(rawJobname)) {
-      out.println(" with jobname having the keyword <b>" +
-          rawJobname + "</b> in it.");
-      // show the jobname keyword if present
-    }
-    if (!DEFAULT_DATE_GLOB_COMPONENT.equals(dateComponent)) {
-      out.println(" for the date <b>" + soughtDate + "</b>");
-    }
-    out.print("</span></i>)");
-
-    final String searchPart = "&search=" + search;
-
-    final String scansizePart = "&scansize=" + currentScanSizeIndex;
-
-    final String searchPlusScan = searchPart + scansizePart;
-
-    // show the expand scope link, if we're restricted
-    if (sizeIsExact || currentScanSizeIndex == SCAN_SIZES.length - 1) {
-      out.println("[<span class=\"small\">get more results</span>]");
-    } else {
-      out.println(" [<span class=\"small\"><a href=\"jobhistory.jsp?pageno=1"
-                  + searchPart + "&scansize=" + (currentScanSizeIndex + 1)
-                  + "\">get more results</a></span>]");
-    }
-
-    // show the 'show-all' link
-    out.println(" [<span class=\"small\"><a href=\"jobhistory.jsp?pageno=-1"
-                + searchPlusScan + "\">show in one page</a></span>]");
-
-    // show the 'first-page' link
-    if (pageno > 1) {
-      out.println(" [<span class=\"small\"><a href=\"jobhistory.jsp?pageno=1"
-                  + searchPlusScan + "\">first page</a></span>]");
-    } else {
-      out.println("[<span class=\"small\">first page]</span>");
-    }
-
-    // show the 'last-page' link
-    if (pageno < maxPageNo) {
-      out.println(" [<span class=\"small\"><a href=\"jobhistory.jsp?pageno="
-                  + maxPageNo + searchPlusScan + "\">last page</a></span>]");
-    } else {
-      out.println("<span class=\"small\">[last page]</span>");
-    }
-
-    // sort the files on creation time.
-    Arrays.sort(jobFiles, latestFirstCreationTimeComparator);
-
-    out.println("<br><br>");
-
-    // print the navigation info (top)
-    printNavigationTool(pageno, size, maxPageNo, searchPlusScan, out);
-
-    out.print("<table align=center border=2 cellpadding=\"5\" cellspacing=\"2\">");
-    out.print("<tr>");
-    out.print("<td>Job submit time</td>" +
-              "<td>Job Id</td><td>Name</td><td>User</td>") ; 
-    out.print("</tr>"); 
-    
-    Set<String> displayedJobs = new HashSet<String>();
-    for (int i = start - 1; i < start + length - 1; ++i) {
-      Path jobFile = jobFiles[i];
-
-      String fname = jobFile.getName();
-      String marker = JobHistory.nonOccursString(fname);
-      String reescapedFname = JobHistory.replaceStringInstances(fname,
-                  JobHistory.UNDERSCORE_ESCAPE, marker);
-      
-      String decodedJobFileName = 
-          JobHistory.JobInfo.decodeJobHistoryFileName(reescapedFname);
-
-      String[] jobDetails = decodedJobFileName.split("_");
-      String trackerStartTime = jobDetails[1];
-      String jobId = (jobDetails[JOB_ID_START]
-                      + "_" + jobDetails[JOB_ID_START + 1]
-                      + "_" + jobDetails[JOB_ID_START + 2]);
-      String submitTimestamp = jobDetails[FILENAME_SUBMIT_TIMESTAMP_PART];
-      String userName = JobHistory.replaceStringInstances(jobDetails[FILENAME_USER_PART],
-                  marker, JobHistory.UNDERSCORE_ESCAPE);
-      String jobName = JobHistory.replaceStringInstances(jobDetails[FILENAME_JOBNAME_PART],
-                  marker, JobHistory.UNDERSCORE_ESCAPE);
-      
-      // Check if the job is already displayed. There can be multiple job 
-      // history files for jobs that have restarted
-      if (displayedJobs.contains(jobId)) {
-        continue;
-      } else {
-        displayedJobs.add(jobId);
-      }
-      
-      // Encode the logfile name again to cancel the decoding done by the browser
-      String preEncodedJobFileName = 
-          JobHistory.JobInfo.encodeJobHistoryFileName(jobFile.getName());
-
-      String encodedJobFileName = 
-          JobHistory.replaceStringInstances(preEncodedJobFileName, "%5F", "%255F");
-%>
-<center>
-<%	
-      printJob(submitTimestamp, jobId,
-               jobName, userName, new Path(jobFile.getParent(), encodedJobFileName), 
-               out) ; 
+/*
+ * 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.
+ */
 %>
-</center> 
-<%
-    } // end while trackers 
-    out.print("</table>");
 
-    // show the navigation info (bottom)
-    printNavigationTool(pageno, size, maxPageNo, searchPlusScan, out);
+<%@ page
+    contentType="text/html; charset=UTF-8"
+    import="org.apache.hadoop.mapred.JobHistoryServer"
+    import="org.apache.hadoop.mapred.JobConf" 
 %>
-<%!
-    private void printJob(String timestamp,
-                          String jobId, String jobName,
-                          String user, Path logFile, JspWriter out)
-    throws IOException {
-      out.print("<tr>"); 
-      out.print("<td>" + new Date(Long.parseLong(timestamp)) + "</td>"); 
-      out.print("<td>" + "<a href=\"jobdetailshistory.jsp?logFile=" 
-          + logFile.toString() + "\">" + jobId + "</a></td>");
-      out.print("<td>"
-                + HtmlQuoting.quoteHtmlChars(unescapeUnderscores(jobName))
-                + "</td>"); 
-      out.print("<td>"
-                + HtmlQuoting.quoteHtmlChars(unescapeUnderscores(user))
-                + "</td>"); 
-      out.print("</tr>");
-    }
-
-    private String escapeUnderscores(String rawString) {
-      return convertStrings(rawString, "_", "%5F");
-    }
-
-    private String unescapeUnderscores(String rawString) {
-      return convertStrings(rawString, "%5F", "_");
-    }
 
-    // inefficient if there are a lot of underscores
-    private String convertStrings(String escapedString, String from, String to) {
-      int firstEscape = escapedString.indexOf(from);
-
-      if (firstEscape < 0) {
-        return escapedString;
-      }
-
-      return escapedString.substring(0, firstEscape)
-            + to
-            + unescapeUnderscores(escapedString.substring
-                                    (firstEscape + from.length()));
-    }
-
-    private void printNavigationTool(int pageno, int size, int max,
-                                     String searchPlusScan, JspWriter out)
-         throws IOException {
-      
-      final int NUMBER_INDICES_TO_SHOW = 5;
-
-      int numIndexToShow = NUMBER_INDICES_TO_SHOW; // num indexes to show on either side
-
-      //TODO check this on boundary cases
-      out.print("<center> <");
-
-      // show previous link
-      if (pageno > 1) {
-        out.println("<a href=\"jobhistory.jsp?pageno=" + (pageno - 1)
-                    + searchPlusScan + "\">Previous</a>");
-      }
-
-      // display the numbered index 1 2 3 4
-      int firstPage = pageno - numIndexToShow;
-      if (firstPage < 1) {
-        firstPage = 1; // boundary condition
-      }
-
-      int lastPage = pageno + numIndexToShow;
-      if (lastPage > max) {
-        lastPage = max; // boundary condition
-      }
-
-      // debug
-      out.println("<!--DEBUG : firstPage : " + firstPage + ", lastPage : " + lastPage + " -->");
-
-      for (int i = firstPage; i <= lastPage; ++i) {
-        if (i != pageno) {// needs hyperlink
-          out.println(" <a href=\"jobhistory.jsp?pageno=" + i
-                      + searchPlusScan + "\">" + i + "</a> ");
-        } else { // current page
-          out.println(i);
-        }
-      }
-
-      // show the next link
-      if (pageno < max) {
-        out.println("<a href=\"jobhistory.jsp?pageno=" + (pageno + 1) + searchPlusScan + "\">Next</a>");
-      }
-      out.print("></center>");
-    }
-%> 
-</body></html>
+<%
+    JobConf clusterConf = (JobConf) application.getAttribute("jobConf");
+    String historyUrl = JobHistoryServer.getHistoryUrlPrefix(clusterConf) +
+        "/jobhistoryhome.jsp";
+    response.sendRedirect(response.encodeRedirectURL(historyUrl));
+    return;
+%>
\ No newline at end of file

Modified: hadoop/common/branches/branch-0.20-security-patches/src/webapps/job/jobtracker.jsp
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-0.20-security-patches/src/webapps/job/jobtracker.jsp?rev=1077590&r1=1077589&r2=1077590&view=diff
==============================================================================
--- hadoop/common/branches/branch-0.20-security-patches/src/webapps/job/jobtracker.jsp (original)
+++ hadoop/common/branches/branch-0.20-security-patches/src/webapps/job/jobtracker.jsp Fri Mar  4 04:32:45 2011
@@ -174,7 +174,8 @@ if (failedJobs.size() > 0) {
 <hr>
 
 <h2 id="local_logs">Local Logs</h2>
-<a href="logs/">Log</a> directory, <a href="jobhistory.jsp">
+<a href="logs/">Log</a> directory,
+<a href="<%=JobHistoryServer.getHistoryUrlPrefix(tracker.conf)%>/jobhistoryhome.jsp">
 Job Tracker History</a>
 
 <%