|
@@ -10,23 +10,69 @@
|
|
|
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");
|
|
|
%>
|
|
|
<html>
|
|
|
<head>
|
|
|
-<title>Hadoop Map/Reduce Administration</title>
|
|
|
+<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>Hadoop Map/Reduce History Viewer</h1>
|
|
|
+<h1> <a href="jobtracker.jsp"><%= trackerName %></a> Hadoop Map/Reduce
|
|
|
+ <a href="jobhistory.jsp">History Viewer</a></h1>
|
|
|
<hr>
|
|
|
-<h2>Available History </h2>
|
|
|
<%
|
|
|
+ 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() {
|
|
|
+ private boolean matchUser(String fileName) {
|
|
|
+ // return true if
|
|
|
+ // - user is not specified
|
|
|
+ // - user matches
|
|
|
+ return "".equals(user) || user.equals(fileName.split("_")[5]);
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean matchJobName(String fileName) {
|
|
|
+ // return true if
|
|
|
+ // - jobname is not specified
|
|
|
+ // - jobname contains the keyword
|
|
|
+ return "".equals(jobname) || fileName.split("_")[6].toLowerCase().contains(jobname);
|
|
|
+ }
|
|
|
+
|
|
|
public boolean accept(Path path) {
|
|
|
- return !(path.getName().endsWith(".xml"));
|
|
|
+ return !(path.getName().endsWith(".xml")) && matchUser(path.getName()) && matchJobName(path.getName());
|
|
|
}
|
|
|
};
|
|
|
|
|
@@ -38,11 +84,85 @@
|
|
|
}
|
|
|
Path[] jobFiles = FileUtil.stat2Paths(fs.listStatus(new Path(historyLogDir),
|
|
|
jobLogFileFilter));
|
|
|
- if (null == jobFiles ) {
|
|
|
- out.println("NULL files !!!");
|
|
|
+ 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)) {
|
|
|
+ out.println(" for user <b>" + user + "</b>"); // show the user if present
|
|
|
+ }
|
|
|
+ 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=\"jobhistory.jsp?pageno=-1&search=" + search + "\">show all</a></span>]");
|
|
|
+
|
|
|
+ // show the 'first-page' link
|
|
|
+ if (pageno > 1) {
|
|
|
+ out.println(" [<span class=\"small\"><a href=\"jobhistory.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=\"jobhistory.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) {
|
|
@@ -74,8 +194,12 @@
|
|
|
}
|
|
|
});
|
|
|
|
|
|
+ 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><td align=\"center\" colspan=\"9\"><b>Available Jobs </b></td></tr>\n");
|
|
|
out.print("<tr>");
|
|
|
out.print("<td>Job tracker Host Name</td>" +
|
|
|
"<td>Job tracker Start time</td>" +
|
|
@@ -83,7 +207,9 @@
|
|
|
out.print("</tr>");
|
|
|
|
|
|
Set<String> displayedJobs = new HashSet<String>();
|
|
|
- for (Path jobFile: jobFiles) {
|
|
|
+ for (int i = start - 1; i < start + length - 1; ++i) {
|
|
|
+ Path jobFile = jobFiles[i];
|
|
|
+
|
|
|
String decodedJobFileName =
|
|
|
JobHistory.JobInfo.decodeJobHistoryFileName(jobFile.getName());
|
|
|
|
|
@@ -91,7 +217,7 @@
|
|
|
String trackerHostName = jobDetails[0];
|
|
|
String trackerStartTime = jobDetails[1];
|
|
|
String jobId = jobDetails[2] + "_" +jobDetails[3] + "_" + jobDetails[4] ;
|
|
|
- String user = jobDetails[5];
|
|
|
+ String userName = jobDetails[5];
|
|
|
String jobName = jobDetails[6];
|
|
|
|
|
|
// Check if the job is already displayed. There can be multiple job
|
|
@@ -109,12 +235,16 @@
|
|
|
<center>
|
|
|
<%
|
|
|
printJob(trackerHostName, trackerStartTime, jobId,
|
|
|
- jobName, user, new Path(jobFile.getParent(), encodedJobFileName),
|
|
|
+ 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,
|
|
@@ -130,5 +260,46 @@
|
|
|
out.print("<td>" + 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=\"jobhistory.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=\"jobhistory.jsp?pageno=" + i + "&search=" + search + "\">" + i + "</a> ");
|
|
|
+ } else { // current page
|
|
|
+ out.println(i);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // show the next link
|
|
|
+ if (pageno < max) {
|
|
|
+ out.println("<a href=\"jobhistory.jsp?pageno=" + (pageno + 1) + "&search=" + search + "\">Next</a>");
|
|
|
+ }
|
|
|
+ out.print("></center>");
|
|
|
+ }
|
|
|
%>
|
|
|
</body></html>
|