Author: acmurthy Date: Mon Mar 16 21:00:46 2009 New Revision: 755003 URL: http://svn.apache.org/viewvc?rev=755003&view=rev Log: HADOOP-5442. Paginate jobhistory display and added some search capabilities. Contributed by Amar Kamat. Modified: hadoop/core/trunk/CHANGES.txt hadoop/core/trunk/src/webapps/job/jobhistory.jsp Modified: hadoop/core/trunk/CHANGES.txt URL: http://svn.apache.org/viewvc/hadoop/core/trunk/CHANGES.txt?rev=755003&r1=755002&r2=755003&view=diff ============================================================================== --- hadoop/core/trunk/CHANGES.txt (original) +++ hadoop/core/trunk/CHANGES.txt Mon Mar 16 21:00:46 2009 @@ -159,6 +159,9 @@ HADOOP-5358. Provide scripting functionality to the synthetic load generator. (Jakob Homan via hairong) + HADOOP-5442. Paginate jobhistory display and added some search + capabilities. (Amar Kamat via acmurthy) + OPTIMIZATIONS BUG FIXES Modified: hadoop/core/trunk/src/webapps/job/jobhistory.jsp URL: http://svn.apache.org/viewvc/hadoop/core/trunk/src/webapps/job/jobhistory.jsp?rev=755003&r1=755002&r2=755003&view=diff ============================================================================== --- hadoop/core/trunk/src/webapps/job/jobhistory.jsp (original) +++ hadoop/core/trunk/src/webapps/job/jobhistory.jsp Mon Mar 16 21:00:46 2009 @@ -29,23 +29,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"); %> -Hadoop Map/Reduce Administration + + +<%= trackerName %> Hadoop Map/Reduce History Viewer -

Hadoop Map/Reduce History Viewer

+

<%= trackerName %> Hadoop Map/Reduce + History Viewer


-

Available History

<% + 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()); } }; @@ -57,11 +103,85 @@ } Path[] jobFiles = FileUtil.stat2Paths(fs.listStatus(new Path(historyLogDir), jobLogFileFilter)); - if (null == jobFiles ) { - out.println("NULL files !!!"); + out.println(""); + 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("
Filter (username:jobname) "); // heading + out.println(""); // search box + out.println("
"); + out.println("Example: 'smith' will display jobs either submitted by user 'smith'. 'smith:sort' will display jobs from user 'smith' having 'sort' keyword in the jobname."); // example + out.println("
"); + + //Show the status + int start = (pageno - 1) * size + 1; + + // DEBUG + out.println(""); + + out.println("Available Jobs in History "); + // display the number of jobs, start index, end index + out.println("( Displaying " + length + " jobs from " + start + " to " + (start + length - 1) + " out of " + jobFiles.length + " jobs"); + if (!"".equals(user)) { + out.println(" for user " + user + ""); // show the user if present + } + if (!"".equals(jobname)) { + out.println(" with jobname having the keyword " + jobname + " in it."); // show the jobname keyword if present + } + out.print(")"); + + // show the 'show-all' link + out.println(" [show all]"); + + // show the 'first-page' link + if (pageno > 1) { + out.println(" [first page]"); + } else { + out.println("[first page]"); + } + + // show the 'last-page' link + if (pageno < maxPageNo) { + out.println(" [last page]"); + } else { + out.println("[last page]"); + } + // sort the files on creation time. Arrays.sort(jobFiles, new Comparator() { public int compare(Path p1, Path p2) { @@ -93,8 +213,12 @@ } }); + out.println("

"); + + // print the navigation info (top) + printNavigation(pageno, size, maxPageNo, search, out); + out.print(""); - out.print("\n"); out.print(""); out.print("" + "" + @@ -102,7 +226,9 @@ out.print(""); Set displayedJobs = new HashSet(); - 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()); @@ -110,7 +236,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 @@ -128,12 +254,16 @@
<% printJob(trackerHostName, trackerStartTime, jobId, - jobName, user, new Path(jobFile.getParent(), encodedJobFileName), + jobName, userName, new Path(jobFile.getParent(), encodedJobFileName), out) ; %>
<% } // end while trackers + out.print("
Available Jobs
Job tracker Host NameJob tracker Start time
"); + + // show the navigation info (bottom) + printNavigation(pageno, size, maxPageNo, search, out); %> <%! private void printJob(String trackerHostName, String trackerid, @@ -149,5 +279,46 @@ out.print("" + user + ""); out.print(""); } + + 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("
<"); + + // show previous link + if (pageno > 1) { + out.println("Previous"); + } + + // 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(""); + + for (int i = firstPage; i <= lastPage; ++i) { + if (i != pageno) {// needs hyperlink + out.println(" " + i + " "); + } else { // current page + out.println(i); + } + } + + // show the next link + if (pageno < max) { + out.println("Next"); + } + out.print(">
"); + } %>