Skip to content
Closed
Changes from 1 commit
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
40aefbe
[SPARK-5945] Added map to track reasons for stage failures and suppor…
Apr 22, 2015
f8744be
Fixed method scoping error
Apr 22, 2015
8fe31e0
Made StageFailure private to spark scheduler
Apr 22, 2015
e0f8b55
Made fail() method public
Apr 22, 2015
729b7ef
Added config option for stageFailure count and documentation
Apr 22, 2015
d5fa622
Moved failure tracking to Stage class. Added clear of failre count up…
Apr 24, 2015
0335b96
Removed stale documentation and fixed some erroneous spacing
Apr 24, 2015
2b91940
Added test case for stage abort after N failures
Apr 28, 2015
914b2cb
Nit
Apr 28, 2015
77555b9
Added test that also validates that the listenerBus sees the JobFaile…
Apr 29, 2015
1243b65
updated to fix last few items
Apr 30, 2015
9052e39
Removed extraneous assert
Apr 30, 2015
673fcb2
Fixed a couple minor issues. Removed unecessary asserT
Apr 30, 2015
e26ae6e
Fixed a couple minor issues. Removed unecessary asserT
Apr 30, 2015
75952ea
Fixed missing maxStageFailures
Apr 30, 2015
bc88aa1
Updated to add test cases for multiple task failures within a Stage. …
May 4, 2015
7ff8b21
Typo fix
May 4, 2015
560a381
Merge remote-tracking branch 'upstream/master' into SPARK-5945
May 4, 2015
76f226a
Resolved merge conflicts. Now simply count the nubmer stage failures …
Jul 23, 2015
fe647d0
Style
Jul 23, 2015
ddfe46c
restoring lost files
Jul 23, 2015
ee8d52e
Updated test suite to properly create task sets and force stage failures
Jul 24, 2015
4da3d5d
got rid of println
Jul 24, 2015
5e13342
Updated tests for stage failures.
Jul 27, 2015
34d69fa
Merge remote-tracking branch 'upstream/master' into SPARK-5945
Jul 27, 2015
e101ed7
Updated test for fetch failures. Added validation of successfully gen…
Jul 28, 2015
daad2e4
Added a test for multiple fetch failures inside a single stage
Jul 28, 2015
0c054d3
Added a test for multiple fetch failures inside a single stage
Jul 28, 2015
f23c31b
Added test to ensure that stage failure only triggers with successive…
Jul 28, 2015
9978575
Test updates. Some tests still failing, unsure why.
Jul 28, 2015
b66d74e
Added stage ID checks in most places and fixed naming for attempts to…
Jul 29, 2015
2e058ba
All tests passing. Still need to refactor multiple fetch failures per…
Jul 29, 2015
f79011b
Updated remaining test for sequential test failures to have three sta…
Jul 29, 2015
62532fa
Nit fixes
Jul 29, 2015
1c1cb72
Style
Jul 29, 2015
17e85de
Naming
Jul 29, 2015
cf94850
refactored tests to eliminate reused code
Aug 4, 2015
7c6f60f
Style
Aug 4, 2015
13af970
Nit fixes.
Aug 5, 2015
09929da
Style
Aug 5, 2015
eb15503
Style
Aug 5, 2015
01d6841
Nits
Aug 6, 2015
1dd4840
Fixed merge conflict
Aug 19, 2015
4da18a1
Style fix
Aug 19, 2015
5e4fe99
Merge remote-tracking branch 'upstream/master' into SPARK-5945
Sep 1, 2015
f928ff3
Updated PR description and minor nits
Sep 1, 2015
e22ce7c
Updated with feedback from PR
Sep 2, 2015
2bd4138
Style fix
Sep 2, 2015
1d44e0c
Test case updates and nit fixes
Sep 2, 2015
5bb1ae6
Added more comments to clarify tricky test case
Sep 2, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions core/src/main/scala/org/apache/spark/scheduler/DAGScheduler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,30 @@ class DAGScheduler(
// Stages that must be resubmitted due to fetch failures
private[scheduler] val failedStages = new HashSet[Stage]

// The maximum number of times to retry a stage before aborting
val maxStageFailures = 5

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you make this a conf? there is already spark.task.maxFailures, so how about spark.stage.maxFailures? Also it should get added to the docs


// To avoid cyclical stage failures (see SPARK-5945) we limit the number of times that a stage
// may be retried. However, it only makes sense to limit the number of times that a stage fails
// if it's failing for the same reason every time. Therefore, track why a stage fails as well as
// how many times it has failed.
case class StageFailure(failureReason : String) {
var count = 1
def fail() = { count += 1 }
def shouldAbort(): Boolean = { count >= maxStageFailures }

override def equals(other: Any): Boolean =
other match {
case that: StageFailure => that.failureReason.equals(this.failureReason)
case _ => false
}

override def hashCode: Int = failureReason.hashCode()
}

// Map to track failure reasons for a given stage (indexed by stage ID)
private[scheduler] val stageFailureReasons = new HashMap[Stage, HashSet[StageFailure]]

private[scheduler] val activeJobs = new HashSet[ActiveJob]

/**
Expand Down Expand Up @@ -460,6 +484,10 @@ class DAGScheduler(
logDebug("Removing stage %d from failed set.".format(stageId))
failedStages -= stage
}
if (stageFailureReasons.contains(stage)) {
logDebug("Removing stage %d from failure reasons set.".format(stageId))
stageFailureReasons -= stage
}
}
// data structures based on StageId
stageIdToStage -= stageId
Expand Down Expand Up @@ -940,6 +968,29 @@ class DAGScheduler(
}
}

/**
* Check whether we should abort the failedStage due to multiple failures for the same reason.
* This method updates the running count of failures for a particular stage and returns
* true if the number of failures for any single reason exceeds the allowable number
* of failures.
* @return An Option that contains the failure reason that caused the abort
*/
def shouldAbortStage(failedStage: Stage, failureReason: String): Option[String] = {
if (!stageFailureReasons.contains(failedStage))
stageFailureReasons.put(failedStage, new HashSet[StageFailure]())

val failures = stageFailureReasons.get(failedStage).get
val failure = StageFailure(failureReason)
failures.find(s => s.equals(failure)) match {
case Some(f) => f.fail()
case None => failures.add(failure)
}
failures.find(_.shouldAbort()) match {
case Some(f) => Some(f.failureReason)
case None => None
}
}

/**
* Responds to a task finishing. This is called inside the event loop so it assumes that it can
* modify the scheduler's internal state. Use taskEnded() to post a task end event from outside.
Expand Down Expand Up @@ -1083,8 +1134,13 @@ class DAGScheduler(
markStageAsFinished(failedStage, Some(failureMessage))
}

val shouldAbort = shouldAbortStage(failedStage, failureMessage)
if (disallowStageRetryForTest) {
abortStage(failedStage, "Fetch failure will not retry stage due to testing config")
} else if (shouldAbort.isDefined) {
abortStage(failedStage, s"Fetch failure - aborting stage. Stage ${failedStage.name} " +

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you remove the first sentence of this and also change "Failure reason" to say "Most recent failure reason:"

s"has failed the maximum allowable number of times: ${maxStageFailures}. " +
s"Failure reason: ${shouldAbort.get}")
} else if (failedStages.isEmpty) {
// Don't schedule an event to resubmit failed stages if failed isn't empty, because
// in that case the event will already have been scheduled.
Expand Down