Skip to content

Commit

Permalink
Add comments and fix the style
Browse files Browse the repository at this point in the history
  • Loading branch information
zsxwing committed Jul 15, 2015
1 parent 74285fa commit d9285f0
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 21 deletions.
63 changes: 63 additions & 0 deletions core/src/main/scala/org/apache/spark/ui/PagedTable.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,19 @@ package org.apache.spark.ui

import scala.xml.{Node, Unparsed}

/**
* A data source that provides data for a page.
*
* @param page the page number
* @param pageSize the number of rows in a page
*/
private[ui] abstract class PagedDataSource[T](page: Int, pageSize: Int) {

protected val data: Seq[T]

/**
* Slice the data for this page
*/
def pageData: PageData[T] = {
val dataSize = data.size
val totalPages = (dataSize + pageSize - 1) / pageSize
Expand All @@ -35,8 +44,15 @@ private[ui] abstract class PagedDataSource[T](page: Int, pageSize: Int) {

}

/**
* The data returned by `PagedDataSource.pageData`, including the page number, the number of total
* pages and the data in this page.
*/
private[ui] case class PageData[T](page: Int, totalPage: Int, data: Seq[T])

/**
* A paged table that will generate a HTML table for a specified page and also the page navigation.
*/
private[ui] trait PagedTable[T] {

def tableId: String
Expand All @@ -62,10 +78,46 @@ private[ui] trait PagedTable[T] {
</div>
}

/**
* Return a page navigation.
* <ul>
* <li>If the totalPages is 1, the page navigation will be empty</li>
* <li>
* If the totalPages is more than 1, it will create a page navigation including a group of
* page numbers and a form to submit the page number.
* </li>
* </ul>
*
* Here are some examples of the page navigation:
* {{{
* << < 11 12 13* 14 15 16 17 18 19 20 > >>
*
* This is the first group, so "<<" is hidden.
* < 1 2* 3 4 5 6 7 8 9 10 > >>
*
* This is the first group and the first page, so "<<" and "<" are hidden.
* 1 2* 3 4 5 6 7 8 9 10 > >>
*
* Assume totalPages is 19. This is the last group, so ">>" is hidden.
* << < 11 12 13* 14 15 16 17 18 19 >
*
* Assume totalPages is 19. This is the last group and the last page, so ">>" and ">" are hidden.
* << < 11 12 13 14 15 16 17 18 19*
*
* * means the current page number
* << means jumping to the first page of the previous group.
* < means jumping to the previous page.
* >> means jumping to the first page of the next group.
* > means jumping to the next page.
* }}}
*/
private[ui] def pageNavigation(page: Int, totalPages: Int): Seq[Node] = {
if (totalPages == 1) {
Nil
} else {
// A group includes all page numbers will be shown in the page navigation.
// The size of group is 10 means there are 10 page numbers will be shown.
// The first group is 1 to 10, the second is 2 to 20, and so on
val groupSize = 10
val firstGroup = 0
val lastGroup = (totalPages - 1) / groupSize
Expand All @@ -74,12 +126,15 @@ private[ui] trait PagedTable[T] {
val endPage = totalPages.min(startPage + groupSize - 1)
val pageTags = (startPage to endPage).map { p =>
if (p == page) {
// The current page should be disabled so that it cannot be clicked.
<li class="disabled"><a href="#">{p}</a></li>
} else {
<li class="active"><a href={pageLink(p)}>{p}</a></li>
}
}
val (goButtonJsFuncName, goButtonJsFunc) = goButtonJavascriptFunction
// When clicking the "Go" button, it will call this javascript method and then call
// "goButtonJsFuncName"
val formJs =
s"""$$(function(){
| $$( "#form-task-page" ).submit(function(event) {
Expand Down Expand Up @@ -152,7 +207,15 @@ private[ui] trait PagedTable[T] {
}
}

/**
* Return a link to jump to a page.
*/
def pageLink(page: Int): String

/**
* Only the implementation knows how to create the url with a page number, so we leave this one
* to the implementation. The implementation should create a JavaScript method that accepts a page
* number and jumps to the page. The return value is this method name and its JavaScript codes.
*/
def goButtonJavascriptFunction: (String, String)
}
48 changes: 27 additions & 21 deletions core/src/main/scala/org/apache/spark/ui/jobs/StagePage.scala
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,7 @@ private[ui] class StagePage(parent: StagesTab) extends WebUIPage("stage") {
maybeExpandDagViz ++
showAdditionalMetrics ++
makeTimeline(
// Only show the tasks in the table
stageData.taskData.values.toSeq.filter(t => taskIdsInPage.contains(t.taskInfo.taskId)),
currentTime) ++
<h4>Summary Metrics for {numCompleted} Completed Tasks</h4> ++
Expand Down Expand Up @@ -714,6 +715,10 @@ private[ui] case class TaskTableRowBytesSpilledData(
diskBytesSpilledSortable: String,
diskBytesSpilledReadable: String)

/**
* Contains all data that needs for sorting and generating HTML. Using this one rather than
* TaskUIData to avoid creating duplicate contents during sorting the data.
*/
private[ui] case class TaskTableRowData(
index: Int,
taskId: Long,
Expand Down Expand Up @@ -903,6 +908,9 @@ private[ui] class TaskDataSource(
)
}

/**
* Return Ordering according to sortColumn and desc
*/
private def ordering(sortColumn: String, desc: Boolean): Ordering[TaskTableRowData] = {
val ordering = sortColumn match {
case "Index" => new Ordering[TaskTableRowData] {
Expand Down Expand Up @@ -1122,9 +1130,11 @@ private[ui] class TaskPagedTable(

override def goButtonJavascriptFunction: (String, String) = {
val jsFuncName = "goToTaskPage"
val encodedSortColumn = URLEncoder.encode(sortColumn, "UTF-8")
val jsFunc = s"""
|function goToTaskPage(page) {
| var url = "${basePath}&task.sort=${sortColumn}&task.desc=${desc}" + "&task.page=" + page;
| var url = "${basePath}&task.sort=${encodedSortColumn}&task.desc=${desc}" +
| "&task.page=" + page;
| window.location.href = url;
|}
""".stripMargin
Expand Down Expand Up @@ -1173,7 +1183,7 @@ private[ui] class TaskPagedTable(
val headerLink =
s"$basePath&task.sort=${URLEncoder.encode(header, "UTF-8")}&task.desc=${!desc}"
val js = Unparsed(s"window.location.href='${headerLink}'")
val arrow = if (desc) "&#x25BE;" else "&#x25B4;"
val arrow = if (desc) "&#x25BE;" else "&#x25B4;" // UP or DOWN
<th class={cssClass} onclick={js}>
{header}
<span>&nbsp;{Unparsed(arrow)}</span>
Expand All @@ -1195,9 +1205,7 @@ private[ui] class TaskPagedTable(
<tr>
<td>{task.index}</td>
<td>{task.taskId}</td>
<td>{
if (task.speculative) s"${task.attempt} (speculative)" else task.attempt.toString
}</td>
<td>{if (task.speculative) s"${task.attempt} (speculative)" else task.attempt.toString}</td>
<td>{task.status}</td>
<td>{task.taskLocality}</td>
<td>{task.executorIdAndHost}</td>
Expand All @@ -1219,33 +1227,31 @@ private[ui] class TaskPagedTable(
{UIUtils.formatDuration(task.gettingResultTime)}
</td>
{if (task.accumulators.nonEmpty) {
<td>{Unparsed(task.accumulators.get)}</td>
}}
<td>{Unparsed(task.accumulators.get)}</td>
}}
{if (task.input.nonEmpty) {
<td>{task.input.get.inputReadable}</td>
}}
<td>{task.input.get.inputReadable}</td>
}}
{if (task.output.nonEmpty) {
<td>{task.output.get.outputReadable}</td>
}}
<td>{task.output.get.outputReadable}</td>
}}
{if (task.shuffleRead.nonEmpty) {
<td class={TaskDetailsClassNames.SHUFFLE_READ_BLOCKED_TIME}>
{task.shuffleRead.get.shuffleReadBlockedTimeReadable}
</td>
<td>
{task.shuffleRead.get.shuffleReadReadable}
<td class={TaskDetailsClassNames.SHUFFLE_READ_BLOCKED_TIME}>
{task.shuffleRead.get.shuffleReadBlockedTimeReadable}
</td>
<td>{task.shuffleRead.get.shuffleReadReadable}</td>
<td class={TaskDetailsClassNames.SHUFFLE_READ_REMOTE_SIZE}>
{task.shuffleRead.get.shuffleReadRemoteReadable}
</td>
}}
}}
{if (task.shuffleWrite.nonEmpty) {
<td>{task.shuffleWrite.get.writeTimeReadable}</td>
<td>{task.shuffleWrite.get.writeTimeReadable}</td>
<td>{task.shuffleWrite.get.shuffleWriteReadable}</td>
}}
}}
{if (task.bytesSpilled.nonEmpty) {
<td>{task.bytesSpilled.get.memoryBytesSpilledReadable}</td>
<td>{task.bytesSpilled.get.memoryBytesSpilledReadable}</td>
<td>{task.bytesSpilled.get.diskBytesSpilledReadable}</td>
}}
}}
{errorMessageCell(task.error)}
</tr>
}
Expand Down

0 comments on commit d9285f0

Please sign in to comment.