diff --git a/core/src/main/scala/org/apache/spark/deploy/history/HistoryServer.scala b/core/src/main/scala/org/apache/spark/deploy/history/HistoryServer.scala
index 754c8e9b6668..a3c639d47da6 100644
--- a/core/src/main/scala/org/apache/spark/deploy/history/HistoryServer.scala
+++ b/core/src/main/scala/org/apache/spark/deploy/history/HistoryServer.scala
@@ -82,31 +82,27 @@ class HistoryServer(
return
}
- val appKey =
- if (parts.length == 3) {
- s"${parts(1)}/${parts(2)}"
- } else {
- parts(1)
+ val appId = parts(1)
+ val attemptId = if (parts.length >= 3) Some(parts(2)) else None
+
+ // Since we may have applications with multiple attempts mixed with applications with a
+ // single attempt, we need to try both. Try the single-attempt route first, and if an
+ // error is raised, then try the multiple attempt route.
+ if (!loadAppUi(appId, None) && (!attemptId.isDefined || !loadAppUi(appId, attemptId))) {
+ val msg =
Application {appId} not found.
+ res.setStatus(HttpServletResponse.SC_NOT_FOUND)
+ UIUtils.basicSparkPage(msg, "Not Found").foreach { n =>
+ res.getWriter().write(n.toString)
}
+ return
+ }
// Note we don't use the UI retrieved from the cache; the cache loader above will register
// the app's UI, and all we need to do is redirect the user to the same URI that was
// requested, and the proper data should be served at that point.
- try {
- appCache.get(appKey)
- res.sendRedirect(res.encodeRedirectURL(req.getRequestURI()))
- } catch {
- case e: Exception => e.getCause() match {
- case nsee: NoSuchElementException =>
- val msg = Application {appKey} not found.
- res.setStatus(HttpServletResponse.SC_NOT_FOUND)
- UIUtils.basicSparkPage(msg, "Not Found").foreach(
- n => res.getWriter().write(n.toString))
-
- case cause: Exception => throw cause
- }
- }
+ res.sendRedirect(res.encodeRedirectURL(req.getRequestURI()))
}
+
// SPARK-5983 ensure TRACE is not supported
protected override def doTrace(req: HttpServletRequest, res: HttpServletResponse): Unit = {
res.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED)
@@ -169,6 +165,20 @@ class HistoryServer(
*/
def getProviderConfig(): Map[String, String] = provider.getConfig()
+ private def loadAppUi(appId: String, attemptId: Option[String]): Boolean = {
+ try {
+ appCache.get(appId + attemptId.map { id => s"/$id" }.getOrElse(""))
+ true
+ } catch {
+ case e: Exception => e.getCause() match {
+ case nsee: NoSuchElementException =>
+ false
+
+ case cause: Exception => throw cause
+ }
+ }
+ }
+
}
/**