Skip to content
Closed
Show file tree
Hide file tree
Changes from 6 commits
Commits
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
30 changes: 22 additions & 8 deletions core/src/main/scala/org/apache/spark/rpc/netty/Dispatcher.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import javax.annotation.concurrent.GuardedBy

import scala.collection.JavaConverters._
import scala.concurrent.Promise
import scala.util.control.NonFatal

import org.apache.spark.SparkException
import org.apache.spark.internal.Logging
Expand All @@ -44,13 +45,10 @@ private[netty] class Dispatcher(nettyEnv: NettyRpcEnv, numUsableCores: Int) exte
private val shutdownLatch = new CountDownLatch(1)
private lazy val sharedLoop = new SharedMessageLoop(nettyEnv.conf, this, numUsableCores)

private def getMessageLoop(name: String, endpoint: RpcEndpoint): MessageLoop = {
private def findMessageLoop(name: String, endpoint: RpcEndpoint): MessageLoop = {
endpoint match {
case e: IsolatedRpcEndpoint =>
new DedicatedMessageLoop(name, e, this)
case _ =>
sharedLoop.register(name, endpoint)
sharedLoop
case e: IsolatedRpcEndpoint => new DedicatedMessageLoop(name, e, this)
case _ => sharedLoop
}
}

Expand All @@ -68,11 +66,27 @@ private[netty] class Dispatcher(nettyEnv: NettyRpcEnv, numUsableCores: Int) exte
if (stopped) {
throw new IllegalStateException("RpcEnv has been stopped")
}
if (endpoints.putIfAbsent(name, getMessageLoop(name, endpoint)) != null) {
if (endpoints.containsKey(name)) {
throw new IllegalArgumentException(s"There is already an RpcEndpoint called $name")
}
val msgLoop = findMessageLoop(name, endpoint)
endpoints.put(name, msgLoop)
try {
endpointRefs.put(endpoint, endpointRef)

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.

Hmm. This is all correct but feels a bit overkill. Seems like a simpler version would be:

endpointRefs.put(endpoint, endpointRef)
try {
  endpoints.put(name, getMessageLoop(name, endpoint))
} catch {
  // cleanup endpointRefs
}

Yes, that uses the old getMessageLoop() (which could be inlined here for clarity), but that's ok as long as it's done after the containsKey check. Then you don't even need the changes to the other file.

@HeartSaVioR HeartSaVioR Jan 2, 2020

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Just to confirm, that's pretty much close with the patch before ac10f87 (that commit was to reflect review comment), with the additional changes; to use containsKey/put instead of putIfAbsent, and inline getMessageLoop (assignToMessageLoop before ac10f87 but name doesn't matter as we will inline). Could you confirm?

@vanzin vanzin Jan 2, 2020

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.

Hmm, I can't find a way to see the complete patch at a specific commit in the UI, so I'll say "maybe".

The goal is:

  • not modify "endpoints" when checking if the endpoint exists
  • update "endpointRefs" before registering the endpoint's message loop (calling register in the case of the shared loop, or creating the dedicated message loop)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks for confirming! Will make a change.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed.

msgLoop match {
case loop: DedicatedMessageLoop => loop.register()
case loop: SharedMessageLoop => loop.register(name, endpoint)
}
} catch {
case NonFatal(e) =>
endpoints.remove(name) match {
case loop: DedicatedMessageLoop => loop.stop()
case _ => // No-op
}
endpointRefs.remove(endpoint)
throw e
}
}
endpointRefs.put(endpoint, endpointRef)
endpointRef
}

Expand Down
12 changes: 7 additions & 5 deletions core/src/main/scala/org/apache/spark/rpc/netty/MessageLoop.scala
Original file line number Diff line number Diff line change
Expand Up @@ -170,12 +170,14 @@ private class DedicatedMessageLoop(
ThreadUtils.newDaemonSingleThreadExecutor(s"dispatcher-$name")
}

(1 to endpoint.threadCount()).foreach { _ =>
threadpool.submit(receiveLoopRunnable)
}
def register(): Unit = {
(1 to endpoint.threadCount()).foreach { _ =>
threadpool.submit(receiveLoopRunnable)
}

// Mark active to handle the OnStart message.
setActive(inbox)
// Mark active to handle the OnStart message.
setActive(inbox)
}

override def post(endpointName: String, message: InboxMessage): Unit = {
require(endpointName == name)
Expand Down