Skip to content

Commit b29d8cd

Browse files
committed
Merge branch 'master' into SPARK-16861-refactor-pyspark-accumulator-api
2 parents 6169c3c + a79838b commit b29d8cd

File tree

61 files changed

+1197
-241
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+1197
-241
lines changed

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ It lists steps that are required before creating a PR. In particular, consider:
66

77
- Is the change important and ready enough to ask the community to spend time reviewing?
88
- Have you searched for existing, related JIRAs and pull requests?
9-
- Is this a new feature that can stand alone as a package on http://spark-packages.org ?
9+
- Is this a new feature that can stand alone as a [third party project](https://cwiki.apache.org/confluence/display/SPARK/Third+Party+Projects) ?
1010
- Is the change being proposed clearly explained and motivated?
1111

1212
When you contribute code, you affirm that the contribution is your original work and that you

R/create-docs.sh

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,13 @@
1717
# limitations under the License.
1818
#
1919

20-
# Script to create API docs for SparkR
21-
# This requires `devtools` and `knitr` to be installed on the machine.
20+
# Script to create API docs and vignettes for SparkR
21+
# This requires `devtools`, `knitr` and `rmarkdown` to be installed on the machine.
2222

2323
# After running this script the html docs can be found in
2424
# $SPARK_HOME/R/pkg/html
25+
# The vignettes can be found in
26+
# $SPARK_HOME/R/pkg/vignettes/sparkr_vignettes.html
2527

2628
set -o pipefail
2729
set -e
@@ -43,4 +45,9 @@ Rscript -e 'libDir <- "../../lib"; library(SparkR, lib.loc=libDir); library(knit
4345

4446
popd
4547

48+
# render creates SparkR vignettes
49+
Rscript -e 'library(rmarkdown); paths <- .libPaths(); .libPaths(c("lib", paths)); Sys.setenv(SPARK_HOME=tools::file_path_as_absolute("..")); render("pkg/vignettes/sparkr-vignettes.Rmd"); .libPaths(paths)'
50+
51+
find pkg/vignettes/. -not -name '.' -not -name '*.Rmd' -not -name '*.md' -not -name '*.pdf' -not -name '*.html' -delete
52+
4653
popd

R/pkg/R/sparkR.R

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ sparkR.stop <- function() {
100100
#' @param sparkEnvir Named list of environment variables to set on worker nodes
101101
#' @param sparkExecutorEnv Named list of environment variables to be used when launching executors
102102
#' @param sparkJars Character vector of jar files to pass to the worker nodes
103-
#' @param sparkPackages Character vector of packages from spark-packages.org
103+
#' @param sparkPackages Character vector of package coordinates
104104
#' @seealso \link{sparkR.session}
105105
#' @rdname sparkR.init-deprecated
106106
#' @export
@@ -327,7 +327,7 @@ sparkRHive.init <- function(jsc = NULL) {
327327
#' @param sparkHome Spark Home directory.
328328
#' @param sparkConfig named list of Spark configuration to set on worker nodes.
329329
#' @param sparkJars character vector of jar files to pass to the worker nodes.
330-
#' @param sparkPackages character vector of packages from spark-packages.org
330+
#' @param sparkPackages character vector of package coordinates
331331
#' @param enableHiveSupport enable support for Hive, fallback if not built with Hive support; once
332332
#' set, this cannot be turned off on an existing session
333333
#' @param ... named Spark properties passed to the method.

R/pkg/vignettes/sparkr-vignettes.Rmd

Lines changed: 861 additions & 0 deletions
Large diffs are not rendered by default.

core/src/main/scala/org/apache/spark/HeartbeatReceiver.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import org.apache.spark.util._
3232
* A heartbeat from executors to the driver. This is a shared message used by several internal
3333
* components to convey liveness or execution information for in-progress tasks. It will also
3434
* expire the hosts that have not heartbeated for more than spark.network.timeout.
35+
* spark.executor.heartbeatInterval should be significantly less than spark.network.timeout.
3536
*/
3637
private[spark] case class Heartbeat(
3738
executorId: String,

core/src/main/scala/org/apache/spark/storage/BlockManager.scala

Lines changed: 45 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ private[spark] class BlockManager(
217217
logInfo(s"Reporting ${blockInfoManager.size} blocks to the master.")
218218
for ((blockId, info) <- blockInfoManager.entries) {
219219
val status = getCurrentBlockStatus(blockId, info)
220-
if (!tryToReportBlockStatus(blockId, info, status)) {
220+
if (info.tellMaster && !tryToReportBlockStatus(blockId, status)) {
221221
logError(s"Failed to report $blockId to master; giving up.")
222222
return
223223
}
@@ -298,7 +298,7 @@ private[spark] class BlockManager(
298298

299299
/**
300300
* Get the BlockStatus for the block identified by the given ID, if it exists.
301-
* NOTE: This is mainly for testing, and it doesn't fetch information from external block store.
301+
* NOTE: This is mainly for testing.
302302
*/
303303
def getStatus(blockId: BlockId): Option[BlockStatus] = {
304304
blockInfoManager.get(blockId).map { info =>
@@ -333,10 +333,9 @@ private[spark] class BlockManager(
333333
*/
334334
private def reportBlockStatus(
335335
blockId: BlockId,
336-
info: BlockInfo,
337336
status: BlockStatus,
338337
droppedMemorySize: Long = 0L): Unit = {
339-
val needReregister = !tryToReportBlockStatus(blockId, info, status, droppedMemorySize)
338+
val needReregister = !tryToReportBlockStatus(blockId, status, droppedMemorySize)
340339
if (needReregister) {
341340
logInfo(s"Got told to re-register updating block $blockId")
342341
// Re-registering will report our new block for free.
@@ -352,17 +351,12 @@ private[spark] class BlockManager(
352351
*/
353352
private def tryToReportBlockStatus(
354353
blockId: BlockId,
355-
info: BlockInfo,
356354
status: BlockStatus,
357355
droppedMemorySize: Long = 0L): Boolean = {
358-
if (info.tellMaster) {
359-
val storageLevel = status.storageLevel
360-
val inMemSize = Math.max(status.memSize, droppedMemorySize)
361-
val onDiskSize = status.diskSize
362-
master.updateBlockInfo(blockManagerId, blockId, storageLevel, inMemSize, onDiskSize)
363-
} else {
364-
true
365-
}
356+
val storageLevel = status.storageLevel
357+
val inMemSize = Math.max(status.memSize, droppedMemorySize)
358+
val onDiskSize = status.diskSize
359+
master.updateBlockInfo(blockManagerId, blockId, storageLevel, inMemSize, onDiskSize)
366360
}
367361

368362
/**
@@ -374,7 +368,7 @@ private[spark] class BlockManager(
374368
info.synchronized {
375369
info.level match {
376370
case null =>
377-
BlockStatus(StorageLevel.NONE, memSize = 0L, diskSize = 0L)
371+
BlockStatus.empty
378372
case level =>
379373
val inMem = level.useMemory && memoryStore.contains(blockId)
380374
val onDisk = level.useDisk && diskStore.contains(blockId)
@@ -565,8 +559,9 @@ private[spark] class BlockManager(
565559
// Give up trying anymore locations. Either we've tried all of the original locations,
566560
// or we've refreshed the list of locations from the master, and have still
567561
// hit failures after trying locations from the refreshed list.
568-
throw new BlockFetchException(s"Failed to fetch block after" +
569-
s" ${totalFailureCount} fetch failures. Most recent failure cause:", e)
562+
logWarning(s"Failed to fetch block after $totalFailureCount fetch failures. " +
563+
s"Most recent failure cause:", e)
564+
return None
570565
}
571566

572567
logWarning(s"Failed to fetch remote block $blockId " +
@@ -807,12 +802,10 @@ private[spark] class BlockManager(
807802
// Now that the block is in either the memory or disk store,
808803
// tell the master about it.
809804
info.size = size
810-
if (tellMaster) {
811-
reportBlockStatus(blockId, info, putBlockStatus)
812-
}
813-
Option(TaskContext.get()).foreach { c =>
814-
c.taskMetrics().incUpdatedBlockStatuses(blockId -> putBlockStatus)
805+
if (tellMaster && info.tellMaster) {
806+
reportBlockStatus(blockId, putBlockStatus)
815807
}
808+
addUpdatedBlockStatusToTaskMetrics(blockId, putBlockStatus)
816809
}
817810
logDebug("Put block %s locally took %s".format(blockId, Utils.getUsedTimeMs(startTimeMs)))
818811
if (level.replication > 1) {
@@ -961,15 +954,12 @@ private[spark] class BlockManager(
961954
val putBlockStatus = getCurrentBlockStatus(blockId, info)
962955
val blockWasSuccessfullyStored = putBlockStatus.storageLevel.isValid
963956
if (blockWasSuccessfullyStored) {
964-
// Now that the block is in either the memory, externalBlockStore, or disk store,
965-
// tell the master about it.
957+
// Now that the block is in either the memory or disk store, tell the master about it.
966958
info.size = size
967-
if (tellMaster) {
968-
reportBlockStatus(blockId, info, putBlockStatus)
969-
}
970-
Option(TaskContext.get()).foreach { c =>
971-
c.taskMetrics().incUpdatedBlockStatuses(blockId -> putBlockStatus)
959+
if (tellMaster && info.tellMaster) {
960+
reportBlockStatus(blockId, putBlockStatus)
972961
}
962+
addUpdatedBlockStatusToTaskMetrics(blockId, putBlockStatus)
973963
logDebug("Put block %s locally took %s".format(blockId, Utils.getUsedTimeMs(startTimeMs)))
974964
if (level.replication > 1) {
975965
val remoteStartTime = System.currentTimeMillis
@@ -1271,12 +1261,10 @@ private[spark] class BlockManager(
12711261

12721262
val status = getCurrentBlockStatus(blockId, info)
12731263
if (info.tellMaster) {
1274-
reportBlockStatus(blockId, info, status, droppedMemorySize)
1264+
reportBlockStatus(blockId, status, droppedMemorySize)
12751265
}
12761266
if (blockIsUpdated) {
1277-
Option(TaskContext.get()).foreach { c =>
1278-
c.taskMetrics().incUpdatedBlockStatuses(blockId -> status)
1279-
}
1267+
addUpdatedBlockStatusToTaskMetrics(blockId, status)
12801268
}
12811269
status.storageLevel
12821270
}
@@ -1316,21 +1304,31 @@ private[spark] class BlockManager(
13161304
// The block has already been removed; do nothing.
13171305
logWarning(s"Asked to remove block $blockId, which does not exist")
13181306
case Some(info) =>
1319-
// Removals are idempotent in disk store and memory store. At worst, we get a warning.
1320-
val removedFromMemory = memoryStore.remove(blockId)
1321-
val removedFromDisk = diskStore.remove(blockId)
1322-
if (!removedFromMemory && !removedFromDisk) {
1323-
logWarning(s"Block $blockId could not be removed as it was not found in either " +
1324-
"the disk, memory, or external block store")
1325-
}
1326-
blockInfoManager.removeBlock(blockId)
1327-
val removeBlockStatus = getCurrentBlockStatus(blockId, info)
1328-
if (tellMaster && info.tellMaster) {
1329-
reportBlockStatus(blockId, info, removeBlockStatus)
1330-
}
1331-
Option(TaskContext.get()).foreach { c =>
1332-
c.taskMetrics().incUpdatedBlockStatuses(blockId -> removeBlockStatus)
1333-
}
1307+
removeBlockInternal(blockId, tellMaster = tellMaster && info.tellMaster)
1308+
addUpdatedBlockStatusToTaskMetrics(blockId, BlockStatus.empty)
1309+
}
1310+
}
1311+
1312+
/**
1313+
* Internal version of [[removeBlock()]] which assumes that the caller already holds a write
1314+
* lock on the block.
1315+
*/
1316+
private def removeBlockInternal(blockId: BlockId, tellMaster: Boolean): Unit = {
1317+
// Removals are idempotent in disk store and memory store. At worst, we get a warning.
1318+
val removedFromMemory = memoryStore.remove(blockId)
1319+
val removedFromDisk = diskStore.remove(blockId)
1320+
if (!removedFromMemory && !removedFromDisk) {
1321+
logWarning(s"Block $blockId could not be removed as it was not found on disk or in memory")
1322+
}
1323+
blockInfoManager.removeBlock(blockId)
1324+
if (tellMaster) {
1325+
reportBlockStatus(blockId, BlockStatus.empty)
1326+
}
1327+
}
1328+
1329+
private def addUpdatedBlockStatusToTaskMetrics(blockId: BlockId, status: BlockStatus): Unit = {
1330+
Option(TaskContext.get()).foreach { c =>
1331+
c.taskMetrics().incUpdatedBlockStatuses(blockId -> status)
13341332
}
13351333
}
13361334

core/src/main/scala/org/apache/spark/storage/memory/MemoryStore.scala

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -169,12 +169,12 @@ private[spark] class MemoryStore(
169169
* temporary unroll memory used during the materialization is "transferred" to storage memory,
170170
* so we won't acquire more memory than is actually needed to store the block.
171171
*
172-
* @return in case of success, the estimated the estimated size of the stored data. In case of
173-
* failure, return an iterator containing the values of the block. The returned iterator
174-
* will be backed by the combination of the partially-unrolled block and the remaining
175-
* elements of the original input iterator. The caller must either fully consume this
176-
* iterator or call `close()` on it in order to free the storage memory consumed by the
177-
* partially-unrolled block.
172+
* @return in case of success, the estimated size of the stored data. In case of failure, return
173+
* an iterator containing the values of the block. The returned iterator will be backed
174+
* by the combination of the partially-unrolled block and the remaining elements of the
175+
* original input iterator. The caller must either fully consume this iterator or call
176+
* `close()` on it in order to free the storage memory consumed by the partially-unrolled
177+
* block.
178178
*/
179179
private[storage] def putIteratorAsValues[T](
180180
blockId: BlockId,
@@ -298,9 +298,9 @@ private[spark] class MemoryStore(
298298
* temporary unroll memory used during the materialization is "transferred" to storage memory,
299299
* so we won't acquire more memory than is actually needed to store the block.
300300
*
301-
* @return in case of success, the estimated the estimated size of the stored data. In case of
302-
* failure, return a handle which allows the caller to either finish the serialization
303-
* by spilling to disk or to deserialize the partially-serialized block and reconstruct
301+
* @return in case of success, the estimated size of the stored data. In case of failure,
302+
* return a handle which allows the caller to either finish the serialization by
303+
* spilling to disk or to deserialize the partially-serialized block and reconstruct
304304
* the original input iterator. The caller must either fully consume this result
305305
* iterator or call `discard()` on it in order to free the storage memory consumed by the
306306
* partially-unrolled block.

core/src/test/scala/org/apache/spark/storage/BlockManagerSuite.scala

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -513,10 +513,8 @@ class BlockManagerSuite extends SparkFunSuite with Matchers with BeforeAndAfterE
513513
assert(store.getRemoteBytes("list1").isDefined, "list1Get expected to be fetched")
514514
store3.stop()
515515
store3 = null
516-
// exception throw because there is no locations
517-
intercept[BlockFetchException] {
518-
store.getRemoteBytes("list1")
519-
}
516+
// Should return None instead of throwing an exception:
517+
assert(store.getRemoteBytes("list1").isEmpty)
520518
}
521519

522520
test("SPARK-14252: getOrElseUpdate should still read from remote storage") {
@@ -1186,9 +1184,7 @@ class BlockManagerSuite extends SparkFunSuite with Matchers with BeforeAndAfterE
11861184
new MockBlockTransferService(conf.getInt("spark.block.failures.beforeLocationRefresh", 5))
11871185
store = makeBlockManager(8000, "executor1", transferService = Option(mockBlockTransferService))
11881186
store.putSingle("item", 999L, StorageLevel.MEMORY_ONLY, tellMaster = true)
1189-
intercept[BlockFetchException] {
1190-
store.getRemoteBytes("item")
1191-
}
1187+
assert(store.getRemoteBytes("item").isEmpty)
11921188
}
11931189

11941190
test("SPARK-13328: refresh block locations (fetch should succeed after location refresh)") {

docs/_layouts/global.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@
114114
<li class="divider"></li>
115115
<li><a href="building-spark.html">Building Spark</a></li>
116116
<li><a href="https://cwiki.apache.org/confluence/display/SPARK/Contributing+to+Spark">Contributing to Spark</a></li>
117-
<li><a href="https://cwiki.apache.org/confluence/display/SPARK/Supplemental+Spark+Projects">Supplemental Projects</a></li>
117+
<li><a href="https://cwiki.apache.org/confluence/display/SPARK/Third+Party+Projects">Third Party Projects</a></li>
118118
</ul>
119119
</li>
120120
</ul>

docs/configuration.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -987,7 +987,8 @@ Apart from these, the following properties are also available, and may be useful
987987
<td>10s</td>
988988
<td>Interval between each executor's heartbeats to the driver. Heartbeats let
989989
the driver know that the executor is still alive and update it with metrics for in-progress
990-
tasks.</td>
990+
tasks. spark.executor.heartbeatInterval should be significantly less than
991+
spark.network.timeout</td>
991992
</tr>
992993
<tr>
993994
<td><code>spark.files.fetchTimeout</code></td>

0 commit comments

Comments
 (0)