blob: eb2a1b13aa9cac13d7632968b400cbdc8075a4dd [file] [log] [blame]
<%!
/**
* Licensed 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
import="javax.servlet.*"
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.mapred.JSPUtil.JobWithViewAccessCheck"
import="org.apache.hadoop.util.*"
import="java.lang.Integer"
import="java.text.SimpleDateFormat"
import="org.codehaus.jackson.map.ObjectMapper"
%>
<%! private static final long serialVersionUID = 1L;
%>
<%! static SimpleDateFormat dateFormat = new SimpleDateFormat("d-MMM-yyyy HH:mm:ss") ; %>
<%!
public static class ErrorResponse {
private final long errorCode;
private final String errorDescription;
// Constructor
ErrorResponse(long ec, String ed) {
errorCode = ec;
errorDescription = ed;
}
// Getters
public long getErrorCode() { return errorCode; }
public String getErrorDescription() { return errorDescription; }
}
public static class JobTasksResponse {
public static class JobTaskInfo {
private final String taskId;
private final float completionPercent;
private final String status;
private final String startTime;
private final String finishTime;
private final long durationSecs;
// Constructor
JobTaskInfo(TaskReport tr) {
taskId = tr.getTaskID().toString();
completionPercent = tr.getProgress() * 100.0f;
status = tr.getState();
startTime = dateFormat.format(new Date(tr.getStartTime()));
finishTime = dateFormat.format(new Date(tr.getFinishTime()));
durationSecs = (tr.getFinishTime() - tr.getStartTime())/1000;
}
// Getters
public String getTaskId() { return taskId; }
public float getCompletionPercent() { return completionPercent; }
public String getStatus() { return status; }
public String getStartTime() { return startTime; }
public String getFinishTime() { return finishTime; }
public long getDurationSecs() { return durationSecs; }
}
private final String jobId;
private final String type;
private final String state;
private final int pageNum;
private final int startIndex;
private final int endIndex;
private final Collection<JobTaskInfo> jobTasksInfo;
// Constructor
JobTasksResponse(String ji, String t, String s, int pn, int si, int ei) {
jobId = ji;
type = t;
state = s;
pageNum = pn;
startIndex = si;
endIndex = ei;
jobTasksInfo = new ArrayList<JobTaskInfo>();
}
// To add one JobTaskInfo object at a time.
void addJobTaskInfo(JobTaskInfo ti) { jobTasksInfo.add(ti); }
// Getters
public String getJobId() { return jobId; }
public String getType() { return type; }
public String getState() { return state; }
public int getPageNum() { return pageNum; }
public int getStartIndex() { return startIndex; }
public int getEndIndex() { return endIndex; }
public Collection<JobTaskInfo> getTasksInfo() { return jobTasksInfo; }
}
%>
<%
String response_format = request.getParameter("format");
if (response_format != null) {
/* Eventually, the HTML output should also be driven off of these *Response
* objects.
*
* Someday.
*/
JobTasksResponse theJobTasksResponse = null;
ErrorResponse theErrorResponse = null;
final JobTracker tracker = (JobTracker) application.getAttribute("job.tracker");
String trackerName =
StringUtils.simpleHostname(tracker.getJobTrackerMachine());
String jobid = request.getParameter("jobid");
if (jobid != null) {
final JobID jobidObj = JobID.forName(jobid);
JobWithViewAccessCheck myJob = JSPUtil.checkAccessAndGetJob(tracker, jobidObj,
request, response);
/* Proceed only if the user is authorized to view this job. */
if (myJob.isViewJobAllowed()) {
JobInProgress job = myJob.getJob();
if (job != null) {
String type = request.getParameter("type");
String pagenum = request.getParameter("pagenum");
String state = request.getParameter("state");
state = (state!=null) ? state : "all";
int pnum = Integer.parseInt(pagenum);
int next_page = pnum+1;
int numperpage = 2000;
TaskReport[] reports = null;
int start_index = (pnum - 1) * numperpage;
int end_index = start_index + numperpage;
if ("map".equals(type)) {
reports = tracker.getMapTaskReports(jobidObj);
} else if ("reduce".equals(type)) {
reports = tracker.getReduceTaskReports(jobidObj);
} else if ("cleanup".equals(type)) {
reports = tracker.getCleanupTaskReports(jobidObj);
} else if ("setup".equals(type)) {
reports = tracker.getSetupTaskReports(jobidObj);
}
// Filtering the reports if some filter is specified
if (!"all".equals(state)) {
List<TaskReport> filteredReports = new ArrayList<TaskReport>();
for (int i = 0; i < reports.length; ++i) {
if (("completed".equals(state) && reports[i].getCurrentStatus() == TIPStatus.COMPLETE)
|| ("running".equals(state) && reports[i].getCurrentStatus() == TIPStatus.RUNNING)
|| ("killed".equals(state) && reports[i].getCurrentStatus() == TIPStatus.KILLED)
|| ("pending".equals(state) && reports[i].getCurrentStatus() == TIPStatus.PENDING)) {
filteredReports.add(reports[i]);
}
}
// using filtered reports instead of all the reports
reports = filteredReports.toArray(new TaskReport[0]);
filteredReports = null;
}
int report_len = reports.length;
if (report_len > start_index) {
if (end_index > report_len){
end_index = report_len;
}
theJobTasksResponse = new JobTasksResponse
(jobid, type, state, pnum, start_index, end_index);
for (int i = start_index ; i < end_index; i++) {
TaskReport report = reports[i];
theJobTasksResponse.addJobTaskInfo(
new JobTasksResponse.JobTaskInfo(
report
)
);
}
} else {
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
theErrorResponse = new ErrorResponse(4102, "No Tasks At Start Index " + start_index);
}
} else {
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
theErrorResponse = new ErrorResponse(4101, "JobID " + jobid + " Not Found");
}
} else {
/* TODO XXX Try and factor out JSPUtil.setErrorAndForward() for re-use
* (and to not make it blindly dispatch to job_authorization_error.jsp,
* which is all HTML.
*/
/* TODO XXX Make this return JSON, not HTML. */
/* Nothing to do here, since JSPUtil.setErrorAndForward() has already been
* called from inside JSPUtil.checkAccessAndGetJob().
*/
}
} else {
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
theErrorResponse = new ErrorResponse(4100, "Missing JobID");
}
/* ------------ Response generation begins here ------------ */
/* For now, "json" is the only supported format.
*
* As more formats are supported, this should become a cascading
* if-elsif-else block.
*/
if ("json".equals(response_format)) {
response.setContentType("application/json");
ObjectMapper responseObjectMapper = new ObjectMapper();
/* A lack of an error response implies we have a meaningful
* application response? Why not!
*/
out.println(responseObjectMapper.writeValueAsString
((theErrorResponse == null) ? theJobTasksResponse : theErrorResponse));
} else {
response.setStatus(HttpServletResponse.SC_NOT_IMPLEMENTED);
}
} else {
%>
<%
// Spit out HTML only in the absence of the "format" query parameter.
response.setContentType("text/html; charset=UTF-8");
final JobTracker tracker = (JobTracker) application.getAttribute("job.tracker");
String trackerName =
StringUtils.simpleHostname(tracker.getJobTrackerMachine());
String jobid = request.getParameter("jobid");
if (jobid == null) {
out.println("<h2>Missing 'jobid'!</h2>");
return;
}
final JobID jobidObj = JobID.forName(jobid);
JobWithViewAccessCheck myJob = JSPUtil.checkAccessAndGetJob(tracker, jobidObj,
request, response);
if (!myJob.isViewJobAllowed()) {
return; // user is not authorized to view this job
}
JobInProgress job = myJob.getJob();
String type = request.getParameter("type");
String pagenum = request.getParameter("pagenum");
String state = request.getParameter("state");
state = (state!=null) ? state : "all";
int pnum = Integer.parseInt(pagenum);
int next_page = pnum+1;
int numperpage = 2000;
TaskReport[] reports = null;
int start_index = (pnum - 1) * numperpage;
int end_index = start_index + numperpage;
int report_len = 0;
if ("map".equals(type)) {
reports = (job != null) ? tracker.getMapTaskReports(jobidObj) : null;
} else if ("reduce".equals(type)) {
reports = (job != null) ? tracker.getReduceTaskReports(jobidObj) : null;
} else if ("cleanup".equals(type)) {
reports = (job != null) ? tracker.getCleanupTaskReports(jobidObj) : null;
} else if ("setup".equals(type)) {
reports = (job != null) ? tracker.getSetupTaskReports(jobidObj) : null;
}
%>
<!DOCTYPE html>
<html>
<head>
<title>Hadoop <%=type%> task list for <%=jobid%> on <%=trackerName%></title>
<link rel="stylesheet" type="text/css" href="/static/hadoop.css">
</head>
<body>
<h1>Hadoop <%=type%> task list for
<a href="jobdetails.jsp?jobid=<%=jobid%>"><%=jobid%></a> on
<a href="jobtracker.jsp"><%=trackerName%></a></h1>
<%
if (job == null) {
out.print("<b>Job " + jobid + " not found.</b><br>\n");
return;
}
// Filtering the reports if some filter is specified
if (!"all".equals(state)) {
List<TaskReport> filteredReports = new ArrayList<TaskReport>();
for (int i = 0; i < reports.length; ++i) {
if (("completed".equals(state) && reports[i].getCurrentStatus() == TIPStatus.COMPLETE)
|| ("running".equals(state) && reports[i].getCurrentStatus() == TIPStatus.RUNNING)
|| ("killed".equals(state) && reports[i].getCurrentStatus() == TIPStatus.KILLED)
|| ("pending".equals(state) && reports[i].getCurrentStatus() == TIPStatus.PENDING)) {
filteredReports.add(reports[i]);
}
}
// using filtered reports instead of all the reports
reports = filteredReports.toArray(new TaskReport[0]);
filteredReports = null;
}
report_len = reports.length;
if (report_len <= start_index) {
out.print("<b>No such tasks</b>");
} else {
out.print("<hr>");
out.print("<h2>" + Character.toUpperCase(state.charAt(0))
+ state.substring(1).toLowerCase() + " Tasks</h2>");
out.print("<center>");
out.print("<table border=2 cellpadding=\"5\" cellspacing=\"2\">");
out.print("<tr><td align=\"center\">Task</td><td>Complete</td><td>Status</td>" +
"<td>Start Time</td><td>Finish Time</td><td>Errors</td><td>Counters</td></tr>");
if (end_index > report_len){
end_index = report_len;
}
for (int i = start_index ; i < end_index; i++) {
TaskReport report = reports[i];
out.print("<tr><td><a href=\"taskdetails.jsp?tipid=" +
report.getTaskID() + "\">" + report.getTaskID() + "</a></td>");
out.print("<td>" + StringUtils.formatPercent(report.getProgress(),2) +
ServletUtil.percentageGraph(report.getProgress() * 100f, 80) + "</td>");
out.print("<td>" + HtmlQuoting.quoteHtmlChars(report.getState()) + "<br/></td>");
out.println("<td>" + StringUtils.getFormattedTimeWithDiff(dateFormat, report.getStartTime(),0) + "<br/></td>");
out.println("<td>" + StringUtils.getFormattedTimeWithDiff(dateFormat,
report.getFinishTime(), report.getStartTime()) + "<br/></td>");
String[] diagnostics = report.getDiagnostics();
out.print("<td><pre>");
for (int j = 0; j < diagnostics.length ; j++) {
out.println(HtmlQuoting.quoteHtmlChars(diagnostics[j]));
}
out.println("</pre><br/></td>");
out.println("<td>" +
"<a href=\"taskstats.jsp?tipid=" + report.getTaskID() +
"\">" + report.getCounters().size() +
"</a></td></tr>");
}
out.print("</table>");
out.print("</center>");
}
if (end_index < report_len) {
out.print("<div style=\"text-align:right\">" +
"<a href=\"jobtasks.jsp?jobid="+ jobid + "&type=" + type +
"&pagenum=" + next_page + "&state=" + state +
"\">" + "Next" + "</a></div>");
}
if (start_index != 0) {
out.print("<div style=\"text-align:right\">" +
"<a href=\"jobtasks.jsp?jobid="+ jobid + "&type=" + type +
"&pagenum=" + (pnum -1) + "&state=" + state + "\">" + "Prev" + "</a></div>");
}
%>
<hr>
<a href="jobtracker.jsp">Go back to JobTracker</a><br>
<%
out.println(ServletUtil.htmlFooter());
%>
<%
} // if (response_format != null)
%>