incorporate review comments

- add two missing @volatiles
- add quite some comments
- refactor provider.actorOf to always take a path for the child, not
  only a name
This commit is contained in:
Roland 2011-12-10 20:32:23 +01:00
parent d4a764cfd9
commit 09aadcb60d
4 changed files with 77 additions and 41 deletions

View file

@ -223,7 +223,7 @@ private[akka] class ActorCell(
final var childrenRefs: TreeMap[String, ChildRestartStats] = emptyChildrenRefs
private def _actorOf(props: Props, name: String): ActorRef = {
val actor = provider.actorOf(systemImpl, props, guardian, name, false)
val actor = provider.actorOf(systemImpl, props, self, self.path / name, false)
childrenRefs = childrenRefs.updated(name, ChildRestartStats(actor))
actor
}

View file

@ -80,7 +80,7 @@ trait ActorRefProvider {
* in case of remote supervision). If systemService is true, deployment is
* bypassed (local-only).
*/
def actorOf(system: ActorSystemImpl, props: Props, supervisor: InternalActorRef, name: String, systemService: Boolean = false): InternalActorRef
def actorOf(system: ActorSystemImpl, props: Props, supervisor: InternalActorRef, path: ActorPath, systemService: Boolean): InternalActorRef
/**
* Create actor reference for a specified local or remote path. If no such
@ -408,30 +408,32 @@ class LocalActorRefProvider(
}
}
/*
* Guardians can be asked by ActorSystem to create children, i.e. top-level
* actors. Therefore these need to answer to these requests, forwarding any
* exceptions which might have occurred.
*/
private class Guardian extends Actor {
def receive = {
case Terminated(_) context.self.stop()
case CreateChild(child, name) sender ! (try context.actorOf(child, name) catch {
case e: Exception e
})
case CreateRandomNameChild(child) sender ! (try context.actorOf(child) catch {
case e: Exception e
})
case CreateChild(child, name) sender ! (try context.actorOf(child, name) catch { case e: Exception e })
case CreateRandomNameChild(child) sender ! (try context.actorOf(child) catch { case e: Exception e })
case m deadLetters ! DeadLetter(m, sender, self)
}
}
/*
* Guardians can be asked by ActorSystem to create children, i.e. top-level
* actors. Therefore these need to answer to these requests, forwarding any
* exceptions which might have occurred.
*/
private class SystemGuardian extends Actor {
def receive = {
case Terminated(_)
eventStream.stopDefaultLoggers()
context.self.stop()
case CreateChild(child, name) sender ! (try context.actorOf(child, name) catch {
case e: Exception e
})
case CreateRandomNameChild(child) sender ! (try context.actorOf(child) catch {
case e: Exception e
})
case CreateChild(child, name) sender ! (try context.actorOf(child, name) catch { case e: Exception e })
case CreateRandomNameChild(child) sender ! (try context.actorOf(child) catch { case e: Exception e })
case m deadLetters ! DeadLetter(m, sender, self)
}
}
@ -463,10 +465,20 @@ class LocalActorRefProvider(
@volatile
private var extraNames: Map[String, InternalActorRef] = Map()
lazy val rootGuardian: InternalActorRef = new LocalActorRef(system, guardianProps, theOneWhoWalksTheBubblesOfSpaceTime, rootPath, true) {
/**
* Higher-level providers (or extensions) might want to register new synthetic
* top-level paths for doing special stuff. This is the way to do just that.
* Just be careful to complete all this before ActorSystem.start() finishes,
* or before you start your own auto-spawned actors.
*/
def registerExtraNames(_extras: Map[String, InternalActorRef]): Unit = extraNames ++= _extras
lazy val rootGuardian: InternalActorRef =
new LocalActorRef(system, guardianProps, theOneWhoWalksTheBubblesOfSpaceTime, rootPath, true) {
object Extra {
def unapply(s: String): Option[InternalActorRef] = extraNames.get(s)
}
override def getParent: InternalActorRef = this
override def getSingleChild(name: String): InternalActorRef = {
@ -478,9 +490,11 @@ class LocalActorRefProvider(
}
}
lazy val guardian: InternalActorRef = actorOf(system, guardianProps, rootGuardian, "user", true)
lazy val guardian: InternalActorRef =
actorOf(system, guardianProps, rootGuardian, rootPath / "user", true)
lazy val systemGuardian: InternalActorRef = actorOf(system, guardianProps.withCreator(new SystemGuardian), rootGuardian, "system", true)
lazy val systemGuardian: InternalActorRef =
actorOf(system, guardianProps.withCreator(new SystemGuardian), rootGuardian, rootPath / "system", true)
lazy val tempContainer = new VirtualPathContainer(tempNode, rootGuardian, log)
@ -494,8 +508,6 @@ class LocalActorRefProvider(
eventStream.startDefaultLoggers(_system)
}
def registerExtraNames(_extras: Map[String, InternalActorRef]): Unit = extraNames ++= _extras
def actorFor(ref: InternalActorRef, path: String): InternalActorRef = path match {
case RelativeActorPath(elems)
if (elems.isEmpty) deadLetters
@ -516,9 +528,7 @@ class LocalActorRefProvider(
case x x
}
def actorOf(system: ActorSystemImpl, props: Props, supervisor: InternalActorRef, name: String, systemService: Boolean): InternalActorRef = {
val path = supervisor.path / name
def actorOf(system: ActorSystemImpl, props: Props, supervisor: InternalActorRef, path: ActorPath, systemService: Boolean): InternalActorRef = {
props.routerConfig match {
case NoRouting new LocalActorRef(system, props, supervisor, path, systemService) // create a local actor
case routedActor new RoutedActorRef(system, props.withRouting(adaptFromDeploy(routedActor, path)), supervisor, path)

View file

@ -162,7 +162,7 @@ class RemoteSystemDaemon(remote: Remote, _path: ActorPath, _parent: InternalActo
val subpath = elems.drop(1)
val path = remote.remoteDaemon.path / subpath
val supervisor = remote.system.actorFor(message.getSupervisor).asInstanceOf[InternalActorRef]
val actor = new LocalActorRef(remote.system, Props(creator = actorFactory), supervisor, path, true)
val actor = remote.system.provider.actorOf(remote.system, Props(creator = actorFactory), supervisor, path, true)
addChild(subpath.mkString("/"), actor)
remote.system.deathWatch.subscribe(this, actor)
case _

View file

@ -56,8 +56,10 @@ class RemoteActorRefProvider(
private val local = new LocalActorRefProvider(systemName, settings, eventStream, scheduler, _deadLetters, rootPath, deployer)
@volatile
private var serialization: Serialization = _
@volatile
private var _remote: Remote = _
def remote = _remote
@ -69,10 +71,34 @@ class RemoteActorRefProvider(
terminationFuture.onComplete(_ remote.server.shutdown())
}
def actorOf(system: ActorSystemImpl, props: Props, supervisor: InternalActorRef, name: String, systemService: Boolean): InternalActorRef =
if (systemService) local.actorOf(system, props, supervisor, name, systemService)
def actorOf(system: ActorSystemImpl, props: Props, supervisor: InternalActorRef, path: ActorPath, systemService: Boolean): InternalActorRef =
if (systemService) local.actorOf(system, props, supervisor, path, systemService)
else {
val path = supervisor.path / name
/*
* This needs to deal with mangled paths, which are created by remote
* deployment, also in this method. The scheme is the following:
*
* Whenever a remote deployment is found, create a path on that remote
* address below remote, including the current systems identification
* as sys@host:port (typically; it will use whatever the remote
* transport uses). This means that on a path up an actor tree each node
* change introduces one layer or remote/sys@host:port/ within the URI.
*
* Example:
*
* akka://sys@home:1234/remote/sys@remote:6667/remote/sys@other:3333/user/a/b/c
*
* means that the logical parent originates from sys@other:3333 with
* one child (may be a or b) being deployed on sys@remote:6667 and
* finally either b or c being created on sys@home:1234, where
* this whole thing actually resides. Thus, the logical path is
* /user/a/b/c and the physical path contains all remote placement
* information.
*
* Deployments are always looked up using the logical path, which is the
* purpose of the lookupRemotes internal method.
*/
@scala.annotation.tailrec
def lookupRemotes(p: Iterable[String]): Option[DeploymentConfig.Deploy] = {
@ -94,14 +120,14 @@ class RemoteActorRefProvider(
deployment match {
case Some(DeploymentConfig.Deploy(_, _, _, _, RemoteDeploymentConfig.RemoteScope(address)))
if (address == rootPath.address) local.actorOf(system, props, supervisor, name)
if (address == rootPath.address) local.actorOf(system, props, supervisor, path, false)
else {
val rpath = RootActorPath(address) / "remote" / rootPath.address.hostPort / path.elements
useActorOnNode(rpath, props.creator, supervisor)
new RemoteActorRef(this, remote.server, rpath, supervisor, None)
}
case _ local.actorOf(system, props, supervisor, name, systemService)
case _ local.actorOf(system, props, supervisor, path, systemService)
}
}