rework system initialization, remove remote address from LocalActorRef

- move all creation of ActorRefs into the ActorRefProvider (deadLetters,
  locker)
- rootPath does not contain remote transport address any longer in order
  to start the LocalActorRefProvider before the RemoteTransport; the
  transport address is inserted during serialization only, which enables
  us later to have more than one transport available for one actor
  system (maybe even needed for clustering)
- fix inheritance between DeadLetterActorRef and EmptyLocalActorRef
- document some start-up dependencies by reordering constructor code
- fix remote tests which used self.path for identifying remote actors
  (since that no longer includes the remote transport address)
This commit is contained in:
Roland 2012-01-27 12:14:28 +01:00
parent 52d6e5625d
commit c5fc153a10
21 changed files with 225 additions and 204 deletions

View file

@ -6,7 +6,7 @@ package akka.remote
import akka.actor._
import akka.dispatch._
import akka.event.{ DeathWatch, Logging }
import akka.event.{ DeathWatch, Logging, LoggingAdapter }
import akka.event.EventStream
import akka.config.ConfigurationException
import java.util.concurrent.{ TimeoutException }
@ -22,43 +22,40 @@ class RemoteActorRefProvider(
val systemName: String,
val settings: ActorSystem.Settings,
val eventStream: EventStream,
val scheduler: Scheduler,
_deadLetters: InternalActorRef) extends ActorRefProvider {
val scheduler: Scheduler) extends ActorRefProvider {
val remoteSettings = new RemoteSettings(settings.config, systemName)
val deployer = new RemoteDeployer(settings)
private val local = new LocalActorRefProvider(systemName, settings, eventStream, scheduler, deployer)
@volatile
private var _log = local.log
def log: LoggingAdapter = _log
def rootPath = local.rootPath
def locker = local.locker
def deadLetters = local.deadLetters
val deathWatch = new RemoteDeathWatch(local.deathWatch, this)
val failureDetector = new AccrualFailureDetector(remoteSettings.FailureDetectorThreshold, remoteSettings.FailureDetectorMaxSampleSize)
// these are only available after init()
def rootGuardian = local.rootGuardian
def guardian = local.guardian
def systemGuardian = local.systemGuardian
def terminationFuture = local.terminationFuture
def dispatcher = local.dispatcher
def registerTempActor(actorRef: InternalActorRef, path: ActorPath) = local.registerTempActor(actorRef, path)
def unregisterTempActor(path: ActorPath) = local.unregisterTempActor(path)
def tempPath() = local.tempPath()
def tempContainer = local.tempContainer
val deployer = new RemoteDeployer(settings)
val transport: RemoteTransport = {
val fqn = remoteSettings.RemoteTransport
// TODO check if this classloader is the right one
ReflectiveAccess.createInstance[RemoteTransport](
fqn,
Seq(classOf[RemoteSettings] -> remoteSettings),
getClass.getClassLoader) match {
case Left(problem) throw new RemoteTransportException("Could not load remote transport layer " + fqn, problem)
case Right(remote) remote
}
}
val log = Logging(eventStream, "RemoteActorRefProvider(" + transport.address + ")")
val rootPath: ActorPath = RootActorPath(transport.address)
private val local = new LocalActorRefProvider(systemName, settings, eventStream, scheduler, _deadLetters, rootPath, deployer)
val failureDetector = new AccrualFailureDetector(remoteSettings.FailureDetectorThreshold, remoteSettings.FailureDetectorMaxSampleSize)
@volatile
private var _transport: RemoteTransport = _
def transport: RemoteTransport = _transport
@volatile
private var _serialization: Serialization = _
@ -72,15 +69,35 @@ class RemoteActorRefProvider(
private var _networkEventStream: NetworkEventStream = _
def networkEventStream = _networkEventStream
val deathWatch = new RemoteDeathWatch(local.deathWatch, this)
def init(system: ActorSystemImpl) {
local.init(system)
_remoteDaemon = new RemoteSystemDaemon(system, transport.address, rootPath / "remote", rootGuardian, log)
_remoteDaemon = new RemoteSystemDaemon(system, rootPath / "remote", rootGuardian, log)
local.registerExtraNames(Map(("remote", remoteDaemon)))
_serialization = SerializationExtension(system)
transport.start(system, this)
_networkEventStream = new NetworkEventStream(system)
system.eventStream.subscribe(networkEventStream.sender, classOf[RemoteLifeCycleEvent])
_transport = {
val fqn = remoteSettings.RemoteTransport
// TODO check if this classloader is the right one; hint: this class was loaded by contextClassLoader if that was not null
ReflectiveAccess.createInstance[RemoteTransport](
fqn,
Seq(classOf[RemoteSettings] -> remoteSettings,
classOf[ActorSystemImpl] -> system,
classOf[RemoteActorRefProvider] -> this),
getClass.getClassLoader) match {
case Left(problem) throw new RemoteTransportException("Could not load remote transport layer " + fqn, problem)
case Right(remote) remote
}
}
_log = Logging(eventStream, "RemoteActorRefProvider(" + transport.address + ")")
// this enables reception of remote requests
_transport.start()
val remoteClientLifeCycleHandler = system.systemActorOf(Props(new Actor {
def receive = {
@ -90,12 +107,8 @@ class RemoteActorRefProvider(
}
}), "RemoteClientLifeCycleListener")
_networkEventStream = new NetworkEventStream(system)
system.eventStream.subscribe(networkEventStream.sender, classOf[RemoteLifeCycleEvent])
system.eventStream.subscribe(remoteClientLifeCycleHandler, classOf[RemoteLifeCycleEvent])
local.registerExtraNames(Map(("remote", remoteDaemon)))
terminationFuture.onComplete(_ transport.shutdown())
}
@ -149,7 +162,7 @@ class RemoteActorRefProvider(
case Some(Deploy(_, _, _, RemoteScope(addr)))
if (addr == rootPath.address) local.actorOf(system, props, supervisor, path, false, deployment)
else {
val rpath = RootActorPath(addr) / "remote" / rootPath.address.hostPort / path.elements
val rpath = RootActorPath(addr) / "remote" / transport.address.hostPort / path.elements
useActorOnNode(rpath, props.creator, supervisor)
new RemoteActorRef(this, transport, rpath, supervisor, None)
}
@ -159,14 +172,13 @@ class RemoteActorRefProvider(
}
}
def actorFor(path: ActorPath): InternalActorRef = path.root match {
case `rootPath` actorFor(rootGuardian, path.elements)
case _ new RemoteActorRef(this, transport, path, Nobody, None)
}
def actorFor(path: ActorPath): InternalActorRef =
if (path.address == rootPath.address || path.address == transport.address) actorFor(rootGuardian, path.elements)
else new RemoteActorRef(this, transport, path, Nobody, None)
def actorFor(ref: InternalActorRef, path: String): InternalActorRef = path match {
case ActorPathExtractor(address, elems)
if (address == rootPath.address) actorFor(rootGuardian, elems)
if (address == rootPath.address || address == transport.address) actorFor(rootGuardian, elems)
else new RemoteActorRef(this, transport, new RootActorPath(address) / elems, Nobody, None)
case _ local.actorFor(ref, path)
}
@ -227,7 +239,7 @@ private[akka] class RemoteActorRef private[akka] (
def restart(cause: Throwable): Unit = sendSystemMessage(Recreate(cause))
@throws(classOf[java.io.ObjectStreamException])
private def writeReplace(): AnyRef = SerializedActorRef(path.toString)
private def writeReplace(): AnyRef = SerializedActorRef(path)
}
class RemoteDeathWatch(val local: LocalDeathWatch, val provider: RemoteActorRefProvider) extends DeathWatch {