-
Notifications
You must be signed in to change notification settings - Fork 29.3k
[SPARK-23253][Core][Shuffle]Only write shuffle temporary index file when there is not an existing one #20422
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
98ea6a7
6196770
87e6dc0
a96f6c4
246dbca
f3f3627
5677448
a3b85f1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,7 +17,7 @@ | |
|
|
||
| package org.apache.spark.shuffle.sort | ||
|
|
||
| import java.io.{File, FileInputStream, FileOutputStream} | ||
| import java.io._ | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: this change is not necessary |
||
|
|
||
| import org.mockito.{Mock, MockitoAnnotations} | ||
| import org.mockito.Answers.RETURNS_SMART_NULLS | ||
|
|
@@ -64,6 +64,9 @@ class IndexShuffleBlockResolverSuite extends SparkFunSuite with BeforeAndAfterEa | |
| } | ||
|
|
||
| test("commit shuffle files multiple times") { | ||
| val shuffleId = 1 | ||
| val mapId = 2 | ||
| val idxName = s"shuffle_${shuffleId}_${mapId}_0.index" | ||
| val resolver = new IndexShuffleBlockResolver(conf, blockManager) | ||
| val lengths = Array[Long](10, 0, 20) | ||
| val dataTmp = File.createTempFile("shuffle", null, tempDir) | ||
|
|
@@ -73,9 +76,13 @@ class IndexShuffleBlockResolverSuite extends SparkFunSuite with BeforeAndAfterEa | |
| } { | ||
| out.close() | ||
| } | ||
| resolver.writeIndexFileAndCommit(1, 2, lengths, dataTmp) | ||
| resolver.writeIndexFileAndCommit(shuffleId, mapId, lengths, dataTmp) | ||
|
|
||
| val dataFile = resolver.getDataFile(1, 2) | ||
| val indexFile = new File(tempDir.getAbsolutePath, idxName) | ||
| val dataFile = resolver.getDataFile(shuffleId, mapId) | ||
|
|
||
| assert(indexFile.exists()) | ||
| assert(indexFile.length() === (lengths.length + 1) * 8) | ||
| assert(dataFile.exists()) | ||
| assert(dataFile.length() === 30) | ||
| assert(!dataTmp.exists()) | ||
|
|
@@ -89,26 +96,39 @@ class IndexShuffleBlockResolverSuite extends SparkFunSuite with BeforeAndAfterEa | |
| } { | ||
| out2.close() | ||
| } | ||
| resolver.writeIndexFileAndCommit(1, 2, lengths2, dataTmp2) | ||
| resolver.writeIndexFileAndCommit(shuffleId, mapId, lengths2, dataTmp2) | ||
|
|
||
| assert(indexFile.length() === (lengths.length + 1) * 8) | ||
| assert(lengths2.toSeq === lengths.toSeq) | ||
| assert(dataFile.exists()) | ||
| assert(dataFile.length() === 30) | ||
| assert(!dataTmp2.exists()) | ||
|
|
||
| // The dataFile should be the previous one | ||
| val firstByte = new Array[Byte](1) | ||
| val in = new FileInputStream(dataFile) | ||
| val dataIn = new FileInputStream(dataFile) | ||
| Utils.tryWithSafeFinally { | ||
| in.read(firstByte) | ||
| dataIn.read(firstByte) | ||
| } { | ||
| in.close() | ||
| dataIn.close() | ||
| } | ||
| assert(firstByte(0) === 0) | ||
|
|
||
| // The index file should not change | ||
| val secondBytes = new Array[Byte](8) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: should have a better name, perhaps
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not sure whether we should change this, just my two cents. |
||
| val indexIn = new FileInputStream(indexFile) | ||
| Utils.tryWithSafeFinally { | ||
| indexIn.read(secondBytes) | ||
| indexIn.read(secondBytes) | ||
| } { | ||
| indexIn.close() | ||
| } | ||
| assert(secondBytes(7) === 10, "The index file should not change") | ||
|
|
||
| // remove data file | ||
| dataFile.delete() | ||
|
|
||
| val lengths3 = Array[Long](10, 10, 15) | ||
| val lengths3 = Array[Long](7, 10, 15, 3) | ||
| val dataTmp3 = File.createTempFile("shuffle", null, tempDir) | ||
| val out3 = new FileOutputStream(dataTmp3) | ||
| Utils.tryWithSafeFinally { | ||
|
|
@@ -117,20 +137,30 @@ class IndexShuffleBlockResolverSuite extends SparkFunSuite with BeforeAndAfterEa | |
| } { | ||
| out3.close() | ||
| } | ||
| resolver.writeIndexFileAndCommit(1, 2, lengths3, dataTmp3) | ||
| resolver.writeIndexFileAndCommit(shuffleId, mapId, lengths3, dataTmp3) | ||
| assert(indexFile.length() === (lengths3.length + 1) * 8) | ||
| assert(lengths3.toSeq != lengths.toSeq) | ||
| assert(dataFile.exists()) | ||
| assert(dataFile.length() === 35) | ||
| assert(!dataTmp2.exists()) | ||
| assert(!dataTmp3.exists()) | ||
|
|
||
| // The dataFile should be the previous one | ||
| val firstByte2 = new Array[Byte](1) | ||
| val in2 = new FileInputStream(dataFile) | ||
| // The dataFile should be the new one, since we deleted the dataFile from the first attempt | ||
| val dataIn2 = new FileInputStream(dataFile) | ||
| Utils.tryWithSafeFinally { | ||
| dataIn2.read(firstByte) | ||
| } { | ||
| dataIn2.close() | ||
| } | ||
| assert(firstByte(0) === 2) | ||
|
|
||
| // The index file should be updated, since we deleted the dataFile from the first attempt | ||
| val indexIn2 = new FileInputStream(indexFile) | ||
| Utils.tryWithSafeFinally { | ||
| in2.read(firstByte2) | ||
| indexIn2.read(secondBytes) | ||
| indexIn2.read(secondBytes) | ||
| } { | ||
| in2.close() | ||
| indexIn2.close() | ||
| } | ||
| assert(firstByte2(0) === 2) | ||
| assert(secondBytes(7) === 7, "The index file should be updated") | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
move this below the comment "This is the first successul attempt".
I'd also include a comment about why we write to a temporary file, even though we're always going to rename (because in case the task dies somehow, we'd prefer to not leave a half-written index file in the final location).