-
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 3 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 | ||
|
|
@@ -123,7 +123,7 @@ class IndexShuffleBlockResolverSuite extends SparkFunSuite with BeforeAndAfterEa | |
| assert(dataFile.length() === 35) | ||
| assert(!dataTmp2.exists()) | ||
|
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 related to the change, but this should be |
||
|
|
||
| // The dataFile should be the previous one | ||
| // The dataFile should be the new one, since we deleted the dataFile from the first attempt | ||
| val firstByte2 = new Array[Byte](1) | ||
| val in2 = new FileInputStream(dataFile) | ||
| Utils.tryWithSafeFinally { | ||
|
|
@@ -133,4 +133,65 @@ class IndexShuffleBlockResolverSuite extends SparkFunSuite with BeforeAndAfterEa | |
| } | ||
| assert(firstByte2(0) === 2) | ||
| } | ||
|
|
||
| test("SPARK-23253: index files should be created properly") { | ||
|
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. thanks for adding this, but actually I'm not sure this is covering any cases in the previous test, is it? I was thinking of just adding something to read the actual index file, and make sure it had the right values to go with the update to the data file (or no updates in some cases). you may have added a couple more asserts than the original test -- if so, maybe they can just be added to the original?
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. +1 we can add check the index file in the original test case. |
||
| val shuffleId = 1 | ||
| val mapId = 2 | ||
| val idxName = s"shuffle_${shuffleId}_${mapId}_0.index" | ||
| val resolver = new IndexShuffleBlockResolver(conf, blockManager) | ||
|
|
||
| val lengths = (1 to 2).map(_ => 8L).toArray | ||
|
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. you could do |
||
| val dataTmp = File.createTempFile("shuffle", null, tempDir) | ||
| val out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(dataTmp))) | ||
| Utils.tryWithSafeFinally { | ||
| lengths.foreach(out.writeLong) | ||
| } { | ||
| out.close() | ||
| } | ||
| resolver.writeIndexFileAndCommit(shuffleId, mapId, lengths, dataTmp) | ||
|
|
||
| val indexFile = new File(tempDir.getAbsolutePath, idxName) | ||
| val dataFile = resolver.getDataFile(shuffleId, mapId) | ||
| val idxFile1Len = indexFile.length() | ||
|
|
||
| assert(indexFile.exists()) | ||
| assert(idxFile1Len === (lengths.length + 1) * 8) | ||
| assert(dataFile.exists()) | ||
| assert(dataFile.length() === 8 * lengths.length) | ||
| assert(!dataTmp.exists()) | ||
|
|
||
| // delete dataFile, index file will be replaced. | ||
| dataFile.delete() | ||
| assert(!dataFile.exists()) | ||
|
|
||
| val lengths2 = (1 to 4).map(_ => 8L).toArray | ||
| val dataTmp2 = File.createTempFile("shuffle", null, tempDir) | ||
| val out2 = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(dataTmp2))) | ||
| Utils.tryWithSafeFinally { | ||
| lengths2.foreach(out2.writeLong) | ||
| } { | ||
| out2.close() | ||
| } | ||
| resolver.writeIndexFileAndCommit(shuffleId, mapId, lengths2, dataTmp2) | ||
| val idxFile2Len = indexFile.length() | ||
|
|
||
| assert(indexFile.exists()) | ||
| assert(indexFile.length() === (lengths2.length + 1) * 8) | ||
| assert(idxFile1Len !== idxFile2Len, "index file should be updated.") | ||
|
|
||
| // all files are present and will be reused | ||
| val lengths3 = (1 to 6).map(_ => 8L).toArray | ||
| val dataTmp3 = File.createTempFile("shuffle", null, tempDir) | ||
| val out3 = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(dataTmp3))) | ||
| Utils.tryWithSafeFinally { | ||
| lengths3.foreach(out3.writeLong) | ||
| } { | ||
| out3.close() | ||
| } | ||
| resolver.writeIndexFileAndCommit(shuffleId, mapId, lengths2, dataTmp2) | ||
| val idxFile3Len = indexFile.length() | ||
|
|
||
| assert(indexFile.exists()) | ||
| assert(idxFile2Len === idxFile3Len, "index file should not change.") | ||
| } | ||
| } | ||
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).