Improved protocol driver stack initialization sequence
This commit is contained in:
parent
8dc60cca4e
commit
ddcb2192eb
2 changed files with 35 additions and 35 deletions
|
|
@ -47,7 +47,8 @@ private[remote] class DefaultMessageDispatcher(private val system: ExtendedActor
|
||||||
recipient match {
|
recipient match {
|
||||||
|
|
||||||
case `remoteDaemon` ⇒
|
case `remoteDaemon` ⇒
|
||||||
if (UntrustedMode) log.debug("dropping daemon message in untrusted mode") else {
|
if (UntrustedMode) log.debug("dropping daemon message in untrusted mode")
|
||||||
|
else {
|
||||||
if (LogReceive) log.debug("received daemon message {}", msgLog)
|
if (LogReceive) log.debug("received daemon message {}", msgLog)
|
||||||
payload match {
|
payload match {
|
||||||
case m @ (_: DaemonMsg | _: Terminated) ⇒
|
case m @ (_: DaemonMsg | _: Terminated) ⇒
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import scala.language.postfixOps
|
||||||
import akka.actor.SupervisorStrategy._
|
import akka.actor.SupervisorStrategy._
|
||||||
import akka.actor._
|
import akka.actor._
|
||||||
import akka.event.{ Logging, LoggingAdapter }
|
import akka.event.{ Logging, LoggingAdapter }
|
||||||
import akka.pattern.gracefulStop
|
import akka.pattern.{ gracefulStop, pipe }
|
||||||
import akka.remote.EndpointManager.{ StartupFinished, ManagementCommand, Listen, Send }
|
import akka.remote.EndpointManager.{ StartupFinished, ManagementCommand, Listen, Send }
|
||||||
import akka.remote.transport.Transport.{ AssociationEventListener, InboundAssociation }
|
import akka.remote.transport.Transport.{ AssociationEventListener, InboundAssociation }
|
||||||
import akka.remote.transport._
|
import akka.remote.transport._
|
||||||
|
|
@ -125,8 +125,9 @@ private[remote] class Remoting(_system: ExtendedActorSystem, _provider: RemoteAc
|
||||||
// This is effectively a write-once variable similar to a lazy val. The reason for not using a lazy val is exception
|
// This is effectively a write-once variable similar to a lazy val. The reason for not using a lazy val is exception
|
||||||
// handling.
|
// handling.
|
||||||
@volatile var addresses: Set[Address] = _
|
@volatile var addresses: Set[Address] = _
|
||||||
// FIXME: Temporary workaround until next Pull Request as the means of configuration changed
|
// This variable has the same semantics as the addresses variable, in the sense it is written once, and emulates
|
||||||
override def defaultAddress: Address = addresses.head
|
// a lazy val
|
||||||
|
@volatile var defaultAddress: Address = _
|
||||||
|
|
||||||
private val settings = new RemotingSettings(provider.remoteSettings.config)
|
private val settings = new RemotingSettings(provider.remoteSettings.config)
|
||||||
|
|
||||||
|
|
@ -170,14 +171,17 @@ private[remote] class Remoting(_system: ExtendedActorSystem, _provider: RemoteAc
|
||||||
implicit val timeout = new Timeout(settings.StartupTimeout)
|
implicit val timeout = new Timeout(settings.StartupTimeout)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val addressesPromise: Promise[Set[(Transport, Address)]] = Promise()
|
val addressesPromise: Promise[Seq[(Transport, Address)]] = Promise()
|
||||||
manager ! Listen(addressesPromise)
|
manager ! Listen(addressesPromise)
|
||||||
|
|
||||||
val transports: Set[(Transport, Address)] = Await.result(addressesPromise.future, timeout.duration)
|
val transports: Seq[(Transport, Address)] = Await.result(addressesPromise.future, timeout.duration)
|
||||||
|
if (transports.isEmpty) throw new RemoteTransportException("No transport drivers were loaded.", null)
|
||||||
|
|
||||||
transportMapping = transports.groupBy { case (transport, _) ⇒ transport.schemeIdentifier }.mapValues {
|
transportMapping = transports.groupBy { case (transport, _) ⇒ transport.schemeIdentifier }.mapValues {
|
||||||
_.toSet
|
_.toSet
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defaultAddress = transports.head._2
|
||||||
addresses = transports.map { _._2 }.toSet
|
addresses = transports.map { _._2 }.toSet
|
||||||
|
|
||||||
manager ! StartupFinished
|
manager ! StartupFinished
|
||||||
|
|
@ -228,7 +232,7 @@ private[remote] class Remoting(_system: ExtendedActorSystem, _provider: RemoteAc
|
||||||
private[remote] object EndpointManager {
|
private[remote] object EndpointManager {
|
||||||
|
|
||||||
sealed trait RemotingCommand
|
sealed trait RemotingCommand
|
||||||
case class Listen(addressesPromise: Promise[Set[(Transport, Address)]]) extends RemotingCommand
|
case class Listen(addressesPromise: Promise[Seq[(Transport, Address)]]) extends RemotingCommand
|
||||||
case object StartupFinished extends RemotingCommand
|
case object StartupFinished extends RemotingCommand
|
||||||
|
|
||||||
case class Send(message: Any, senderOption: Option[ActorRef], recipient: RemoteActorRef) extends RemotingCommand {
|
case class Send(message: Any, senderOption: Option[ActorRef], recipient: RemoteActorRef) extends RemotingCommand {
|
||||||
|
|
@ -237,6 +241,9 @@ private[remote] object EndpointManager {
|
||||||
|
|
||||||
case class ManagementCommand(cmd: Any, statusPromise: Promise[Boolean]) extends RemotingCommand
|
case class ManagementCommand(cmd: Any, statusPromise: Promise[Boolean]) extends RemotingCommand
|
||||||
|
|
||||||
|
case class ListensResult(addressesPromise: Promise[Seq[(Transport, Address)]],
|
||||||
|
results: Seq[(Transport, Address, Promise[AssociationEventListener])])
|
||||||
|
|
||||||
sealed trait EndpointPolicy
|
sealed trait EndpointPolicy
|
||||||
case class Pass(endpoint: ActorRef) extends EndpointPolicy
|
case class Pass(endpoint: ActorRef) extends EndpointPolicy
|
||||||
case class Gated(timeOfFailure: Long) extends EndpointPolicy
|
case class Gated(timeOfFailure: Long) extends EndpointPolicy
|
||||||
|
|
@ -283,7 +290,6 @@ private[remote] object EndpointManager {
|
||||||
endpoint
|
endpoint
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Temporary hack to verify the bug
|
|
||||||
def isPassive(endpoint: ActorRef): Boolean = addressToPassive.contains(endpointToAddress(endpoint))
|
def isPassive(endpoint: ActorRef): Boolean = addressToPassive.contains(endpointToAddress(endpoint))
|
||||||
|
|
||||||
def markFailed(endpoint: ActorRef, timeOfFailure: Long): Unit = {
|
def markFailed(endpoint: ActorRef, timeOfFailure: Long): Unit = {
|
||||||
|
|
@ -351,12 +357,23 @@ private[remote] class EndpointManager(conf: Config, log: LoggingAdapter) extends
|
||||||
|
|
||||||
def receive = {
|
def receive = {
|
||||||
case Listen(addressesPromise) ⇒
|
case Listen(addressesPromise) ⇒
|
||||||
|
listens map { ListensResult(addressesPromise, _) } pipeTo self
|
||||||
|
|
||||||
try initializeTransports(addressesPromise) catch {
|
case ListensResult(addressesPromise, results) ⇒
|
||||||
case NonFatal(e) ⇒
|
transportMapping = results.groupBy {
|
||||||
addressesPromise.failure(e)
|
case (_, transportAddress, _) ⇒ transportAddress
|
||||||
context.stop(self)
|
} map {
|
||||||
|
case (a, t) if t.size > 1 ⇒
|
||||||
|
throw new RemoteTransportException(s"There are more than one transports listening on local address [$a]", null)
|
||||||
|
case (a, t) ⇒ a -> t.head._1
|
||||||
}
|
}
|
||||||
|
// Register to each transport as listener and collect mapping to addresses
|
||||||
|
val transportsAndAddresses = results map {
|
||||||
|
case (transport, address, promise) ⇒
|
||||||
|
promise.success(self)
|
||||||
|
transport -> address
|
||||||
|
}
|
||||||
|
addressesPromise.success(transportsAndAddresses)
|
||||||
|
|
||||||
case ManagementCommand(_, statusPromise) ⇒ statusPromise.success(false)
|
case ManagementCommand(_, statusPromise) ⇒ statusPromise.success(false)
|
||||||
|
|
||||||
|
|
@ -415,7 +432,7 @@ private[remote] class EndpointManager(conf: Config, log: LoggingAdapter) extends
|
||||||
case Prune ⇒ endpoints.prune(settings.RetryGateClosedFor)
|
case Prune ⇒ endpoints.prune(settings.RetryGateClosedFor)
|
||||||
}
|
}
|
||||||
|
|
||||||
private def initializeTransports(addressesPromise: Promise[Set[(Transport, Address)]]): Unit = {
|
private def listens: Future[Seq[(Transport, Address, Promise[AssociationEventListener])]] = {
|
||||||
val transports = for ((fqn, adapters, config) ← settings.Transports) yield {
|
val transports = for ((fqn, adapters, config) ← settings.Transports) yield {
|
||||||
|
|
||||||
val args = Seq(classOf[ExtendedActorSystem] -> context.system, classOf[Config] -> config)
|
val args = Seq(classOf[ExtendedActorSystem] -> context.system, classOf[Config] -> config)
|
||||||
|
|
@ -439,28 +456,10 @@ private[remote] class EndpointManager(conf: Config, log: LoggingAdapter) extends
|
||||||
new AkkaProtocolTransport(wrappedTransport, context.system, new AkkaProtocolSettings(conf), AkkaPduProtobufCodec)
|
new AkkaProtocolTransport(wrappedTransport, context.system, new AkkaProtocolSettings(conf), AkkaPduProtobufCodec)
|
||||||
}
|
}
|
||||||
|
|
||||||
val listens: Future[Seq[(Transport, (Address, Promise[AssociationEventListener]))]] = Future.sequence(
|
// Collect all transports, listen addresses and listener promises in one future
|
||||||
transports.map { transport ⇒ transport.listen map (transport -> _) })
|
Future.sequence(transports.map { transport ⇒
|
||||||
|
transport.listen map { case (address, listenerPromise) ⇒ (transport, address, listenerPromise) }
|
||||||
listens.onComplete {
|
})
|
||||||
case Success(results) ⇒
|
|
||||||
transportMapping = results.groupBy {
|
|
||||||
case (_, (transportAddress, _)) ⇒ transportAddress
|
|
||||||
} map {
|
|
||||||
case (a, t) if t.size > 1 ⇒
|
|
||||||
// FIXME: Throwing on the wrong thread
|
|
||||||
throw new RemoteTransportException(s"There are more than one transports listening on local address [$a]", null)
|
|
||||||
case (a, t) ⇒ a -> t.head._1
|
|
||||||
}
|
|
||||||
|
|
||||||
val transportsAndAddresses = (for ((transport, (address, promise)) ← results) yield {
|
|
||||||
promise.success(self)
|
|
||||||
transport -> address
|
|
||||||
}).toSet
|
|
||||||
addressesPromise.success(transportsAndAddresses)
|
|
||||||
|
|
||||||
case Failure(reason) ⇒ addressesPromise.failure(reason)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private def createEndpoint(remoteAddress: Address,
|
private def createEndpoint(remoteAddress: Address,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue