2010-08-28 16:48:27 +02:00
|
|
|
/**
|
|
|
|
|
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>
|
|
|
|
|
*/
|
|
|
|
|
|
2010-09-01 19:22:39 +02:00
|
|
|
package se.scalablesolutions.akka.serialization
|
2010-08-28 16:48:27 +02:00
|
|
|
|
|
|
|
|
import se.scalablesolutions.akka.stm.global._
|
|
|
|
|
import se.scalablesolutions.akka.stm.TransactionManagement._
|
|
|
|
|
import se.scalablesolutions.akka.stm.TransactionManagement
|
2010-09-18 17:21:12 +05:30
|
|
|
import se.scalablesolutions.akka.dispatch.MessageInvocation
|
2010-08-31 19:12:14 +02:00
|
|
|
import se.scalablesolutions.akka.remote.{RemoteServer, MessageSerializer}
|
2010-09-01 19:22:39 +02:00
|
|
|
import se.scalablesolutions.akka.remote.protocol.RemoteProtocol.{ActorType => ActorTypeProtocol, _}
|
|
|
|
|
import ActorTypeProtocol._
|
|
|
|
|
import se.scalablesolutions.akka.config.{AllForOneStrategy, OneForOneStrategy, FaultHandlingStrategy}
|
|
|
|
|
import se.scalablesolutions.akka.config.ScalaConfig._
|
2010-09-17 16:04:25 +02:00
|
|
|
import se.scalablesolutions.akka.actor.{uuidFrom,newUuid}
|
2010-08-28 16:48:27 +02:00
|
|
|
import com.google.protobuf.ByteString
|
2010-09-17 09:56:36 +02:00
|
|
|
import se.scalablesolutions.akka.actor._
|
2010-08-28 16:48:27 +02:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Type class definition for Actor Serialization
|
|
|
|
|
*/
|
|
|
|
|
trait FromBinary[T <: Actor] {
|
|
|
|
|
def fromBinary(bytes: Array[Byte], act: T): T
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
trait ToBinary[T <: Actor] {
|
|
|
|
|
def toBinary(t: T): Array[Byte]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// client needs to implement Format[] for the respective actor
|
|
|
|
|
trait Format[T <: Actor] extends FromBinary[T] with ToBinary[T]
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* A default implementation for a stateless actor
|
|
|
|
|
*
|
|
|
|
|
* Create a Format object with the client actor as the implementation of the type class
|
|
|
|
|
*
|
|
|
|
|
* <pre>
|
2010-09-17 09:56:36 +02:00
|
|
|
* object BinaryFormatMyStatelessActor {
|
2010-08-28 16:48:27 +02:00
|
|
|
* implicit object MyStatelessActorFormat extends StatelessActorFormat[MyStatelessActor]
|
|
|
|
|
* }
|
|
|
|
|
* </pre>
|
|
|
|
|
*/
|
|
|
|
|
trait StatelessActorFormat[T <: Actor] extends Format[T] {
|
|
|
|
|
def fromBinary(bytes: Array[Byte], act: T) = act
|
2010-09-17 09:56:36 +02:00
|
|
|
|
2010-08-28 16:48:27 +02:00
|
|
|
def toBinary(ac: T) = Array.empty[Byte]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* A default implementation of the type class for a Format that specifies a serializer
|
|
|
|
|
*
|
|
|
|
|
* Create a Format object with the client actor as the implementation of the type class and
|
|
|
|
|
* a serializer object
|
|
|
|
|
*
|
|
|
|
|
* <pre>
|
2010-09-17 09:56:36 +02:00
|
|
|
* object BinaryFormatMyJavaSerializableActor {
|
|
|
|
|
* implicit object MyJavaSerializableActorFormat extends SerializerBasedActorFormat[MyJavaSerializableActor] {
|
2010-08-28 16:48:27 +02:00
|
|
|
* val serializer = Serializer.Java
|
2010-09-17 09:56:36 +02:00
|
|
|
* }
|
2010-08-28 16:48:27 +02:00
|
|
|
* }
|
|
|
|
|
* </pre>
|
|
|
|
|
*/
|
|
|
|
|
trait SerializerBasedActorFormat[T <: Actor] extends Format[T] {
|
|
|
|
|
val serializer: Serializer
|
2010-09-17 09:56:36 +02:00
|
|
|
|
2010-08-28 16:48:27 +02:00
|
|
|
def fromBinary(bytes: Array[Byte], act: T) = serializer.fromBinary(bytes, Some(act.self.actorClass)).asInstanceOf[T]
|
2010-09-17 09:56:36 +02:00
|
|
|
|
2010-08-28 16:48:27 +02:00
|
|
|
def toBinary(ac: T) = serializer.toBinary(ac)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2010-09-06 14:03:49 +02:00
|
|
|
* Module for local actor serialization.
|
2010-08-28 16:48:27 +02:00
|
|
|
*/
|
|
|
|
|
object ActorSerialization {
|
|
|
|
|
def fromBinary[T <: Actor](bytes: Array[Byte])(implicit format: Format[T]): ActorRef =
|
|
|
|
|
fromBinaryToLocalActorRef(bytes, format)
|
|
|
|
|
|
2010-09-18 17:21:12 +05:30
|
|
|
def toBinary[T <: Actor](a: ActorRef, serializeMailBox: Boolean = true)(implicit format: Format[T]): Array[Byte] =
|
|
|
|
|
toSerializedActorRefProtocol(a, format, serializeMailBox).toByteArray
|
2010-08-28 16:48:27 +02:00
|
|
|
|
|
|
|
|
// wrapper for implicits to be used by Java
|
|
|
|
|
def fromBinaryJ[T <: Actor](bytes: Array[Byte], format: Format[T]): ActorRef =
|
|
|
|
|
fromBinary(bytes)(format)
|
|
|
|
|
|
|
|
|
|
// wrapper for implicits to be used by Java
|
2010-09-18 17:21:12 +05:30
|
|
|
def toBinaryJ[T <: Actor](a: ActorRef, format: Format[T], srlMailBox: Boolean = true): Array[Byte] =
|
|
|
|
|
toBinary(a, srlMailBox)(format)
|
2010-08-28 16:48:27 +02:00
|
|
|
|
2010-09-17 09:56:36 +02:00
|
|
|
private[akka] def toSerializedActorRefProtocol[T <: Actor](
|
2010-09-18 17:21:12 +05:30
|
|
|
actorRef: ActorRef, format: Format[T], serializeMailBox: Boolean = true): SerializedActorRefProtocol = {
|
2010-08-28 16:48:27 +02:00
|
|
|
val lifeCycleProtocol: Option[LifeCycleProtocol] = {
|
|
|
|
|
def setScope(builder: LifeCycleProtocol.Builder, scope: Scope) = scope match {
|
|
|
|
|
case Permanent => builder.setLifeCycle(LifeCycleType.PERMANENT)
|
|
|
|
|
case Temporary => builder.setLifeCycle(LifeCycleType.TEMPORARY)
|
|
|
|
|
}
|
|
|
|
|
val builder = LifeCycleProtocol.newBuilder
|
|
|
|
|
actorRef.lifeCycle match {
|
|
|
|
|
case Some(LifeCycle(scope)) =>
|
|
|
|
|
setScope(builder, scope)
|
|
|
|
|
Some(builder.build)
|
|
|
|
|
case None => None
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
val originalAddress = AddressProtocol.newBuilder
|
2010-09-17 09:56:36 +02:00
|
|
|
.setHostname(actorRef.homeAddress.getHostName)
|
|
|
|
|
.setPort(actorRef.homeAddress.getPort)
|
|
|
|
|
.build
|
2010-08-28 16:48:27 +02:00
|
|
|
|
|
|
|
|
val builder = SerializedActorRefProtocol.newBuilder
|
2010-09-17 16:04:25 +02:00
|
|
|
.setUuid(UuidProtocol.newBuilder.setHigh(actorRef.uuid.getTime).setLow(actorRef.uuid.getClockSeqAndNode).build)
|
2010-08-28 16:48:27 +02:00
|
|
|
.setId(actorRef.id)
|
|
|
|
|
.setActorClassname(actorRef.actorClass.getName)
|
|
|
|
|
.setOriginalAddress(originalAddress)
|
|
|
|
|
.setIsTransactor(actorRef.isTransactor)
|
|
|
|
|
.setTimeout(actorRef.timeout)
|
|
|
|
|
|
|
|
|
|
|
2010-09-18 17:21:12 +05:30
|
|
|
if (serializeMailBox == true) {
|
|
|
|
|
val messages =
|
|
|
|
|
actorRef.mailbox match {
|
|
|
|
|
case q: java.util.Queue[MessageInvocation] =>
|
|
|
|
|
val l = new scala.collection.mutable.ListBuffer[MessageInvocation]
|
|
|
|
|
val it = q.iterator
|
|
|
|
|
while (it.hasNext == true) l += it.next
|
|
|
|
|
l
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
val requestProtocols =
|
|
|
|
|
messages.map(m =>
|
|
|
|
|
RemoteActorSerialization.createRemoteRequestProtocolBuilder(
|
|
|
|
|
actorRef,
|
|
|
|
|
m.message,
|
|
|
|
|
false,
|
|
|
|
|
actorRef.getSender,
|
|
|
|
|
None,
|
|
|
|
|
ActorType.ScalaActor).build)
|
|
|
|
|
|
|
|
|
|
requestProtocols.foreach(rp => builder.addMessages(rp))
|
|
|
|
|
}
|
|
|
|
|
|
2010-08-28 16:48:27 +02:00
|
|
|
actorRef.receiveTimeout.foreach(builder.setReceiveTimeout(_))
|
|
|
|
|
builder.setActorInstance(ByteString.copyFrom(format.toBinary(actorRef.actor.asInstanceOf[T])))
|
|
|
|
|
lifeCycleProtocol.foreach(builder.setLifeCycle(_))
|
|
|
|
|
actorRef.supervisor.foreach(s => builder.setSupervisor(RemoteActorSerialization.toRemoteActorRefProtocol(s)))
|
|
|
|
|
// FIXME: how to serialize the hotswap PartialFunction ??
|
|
|
|
|
//hotswap.foreach(builder.setHotswapStack(_))
|
|
|
|
|
builder.build
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private def fromBinaryToLocalActorRef[T <: Actor](bytes: Array[Byte], format: Format[T]): ActorRef =
|
|
|
|
|
fromProtobufToLocalActorRef(SerializedActorRefProtocol.newBuilder.mergeFrom(bytes).build, format, None)
|
|
|
|
|
|
2010-09-17 09:56:36 +02:00
|
|
|
private[akka] def fromProtobufToLocalActorRef[T <: Actor](
|
|
|
|
|
protocol: SerializedActorRefProtocol, format: Format[T], loader: Option[ClassLoader]): ActorRef = {
|
2010-08-28 16:48:27 +02:00
|
|
|
Actor.log.debug("Deserializing SerializedActorRefProtocol to LocalActorRef:\n" + protocol)
|
|
|
|
|
|
|
|
|
|
val serializer =
|
2010-09-17 09:56:36 +02:00
|
|
|
if (format.isInstanceOf[SerializerBasedActorFormat[_]])
|
|
|
|
|
Some(format.asInstanceOf[SerializerBasedActorFormat[_]].serializer)
|
|
|
|
|
else None
|
2010-08-28 16:48:27 +02:00
|
|
|
|
|
|
|
|
val lifeCycle =
|
2010-09-17 09:56:36 +02:00
|
|
|
if (protocol.hasLifeCycle) {
|
|
|
|
|
val lifeCycleProtocol = protocol.getLifeCycle
|
|
|
|
|
Some(if (lifeCycleProtocol.getLifeCycle == LifeCycleType.PERMANENT) LifeCycle(Permanent)
|
|
|
|
|
else if (lifeCycleProtocol.getLifeCycle == LifeCycleType.TEMPORARY) LifeCycle(Temporary)
|
|
|
|
|
else throw new IllegalActorStateException("LifeCycle type is not valid: " + lifeCycleProtocol.getLifeCycle))
|
|
|
|
|
} else None
|
2010-08-28 16:48:27 +02:00
|
|
|
|
|
|
|
|
val supervisor =
|
2010-09-17 09:56:36 +02:00
|
|
|
if (protocol.hasSupervisor)
|
|
|
|
|
Some(RemoteActorSerialization.fromProtobufToRemoteActorRef(protocol.getSupervisor, loader))
|
|
|
|
|
else None
|
2010-08-28 16:48:27 +02:00
|
|
|
|
|
|
|
|
val hotswap =
|
2010-09-17 09:56:36 +02:00
|
|
|
if (serializer.isDefined && protocol.hasHotswapStack) Some(serializer.get
|
2010-08-28 16:48:27 +02:00
|
|
|
.fromBinary(protocol.getHotswapStack.toByteArray, Some(classOf[PartialFunction[Any, Unit]]))
|
|
|
|
|
.asInstanceOf[PartialFunction[Any, Unit]])
|
2010-09-17 09:56:36 +02:00
|
|
|
else None
|
2010-08-28 16:48:27 +02:00
|
|
|
|
|
|
|
|
val classLoader = loader.getOrElse(getClass.getClassLoader)
|
2010-08-28 19:27:42 +02:00
|
|
|
|
2010-08-28 16:48:27 +02:00
|
|
|
val factory = () => {
|
|
|
|
|
val actorClass = classLoader.loadClass(protocol.getActorClassname)
|
|
|
|
|
if (format.isInstanceOf[SerializerBasedActorFormat[_]])
|
|
|
|
|
format.asInstanceOf[SerializerBasedActorFormat[_]].serializer.fromBinary(
|
|
|
|
|
protocol.getActorInstance.toByteArray, Some(actorClass)).asInstanceOf[Actor]
|
|
|
|
|
else actorClass.newInstance.asInstanceOf[Actor]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
val ar = new LocalActorRef(
|
2010-09-17 16:04:25 +02:00
|
|
|
uuidFrom(protocol.getUuid.getHigh,protocol.getUuid.getLow),
|
2010-08-28 16:48:27 +02:00
|
|
|
protocol.getId,
|
|
|
|
|
protocol.getOriginalAddress.getHostname,
|
|
|
|
|
protocol.getOriginalAddress.getPort,
|
|
|
|
|
if (protocol.hasIsTransactor) protocol.getIsTransactor else false,
|
|
|
|
|
if (protocol.hasTimeout) protocol.getTimeout else Actor.TIMEOUT,
|
|
|
|
|
if (protocol.hasReceiveTimeout) Some(protocol.getReceiveTimeout) else None,
|
|
|
|
|
lifeCycle,
|
|
|
|
|
supervisor,
|
|
|
|
|
hotswap,
|
|
|
|
|
classLoader, // TODO: should we fall back to getClass.getClassLoader?
|
|
|
|
|
factory)
|
|
|
|
|
|
|
|
|
|
val messages = protocol.getMessagesList.toArray.toList.asInstanceOf[List[RemoteRequestProtocol]]
|
|
|
|
|
messages.foreach(message => ar ! MessageSerializer.deserialize(message.getMessage))
|
2010-08-28 19:27:42 +02:00
|
|
|
|
2010-08-28 16:48:27 +02:00
|
|
|
if (format.isInstanceOf[SerializerBasedActorFormat[_]] == false)
|
|
|
|
|
format.fromBinary(protocol.getActorInstance.toByteArray, ar.actor.asInstanceOf[T])
|
|
|
|
|
ar
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
object RemoteActorSerialization {
|
|
|
|
|
/**
|
|
|
|
|
* Deserializes a byte array (Array[Byte]) into an RemoteActorRef instance.
|
|
|
|
|
*/
|
|
|
|
|
def fromBinaryToRemoteActorRef(bytes: Array[Byte]): ActorRef =
|
|
|
|
|
fromProtobufToRemoteActorRef(RemoteActorRefProtocol.newBuilder.mergeFrom(bytes).build, None)
|
|
|
|
|
|
2010-09-17 09:56:36 +02:00
|
|
|
/**
|
|
|
|
|
* Deserializes a byte array (Array[Byte]) into an RemoteActorRef instance.
|
|
|
|
|
*/
|
2010-08-28 16:48:27 +02:00
|
|
|
def fromBinaryToRemoteActorRef(bytes: Array[Byte], loader: ClassLoader): ActorRef =
|
|
|
|
|
fromProtobufToRemoteActorRef(RemoteActorRefProtocol.newBuilder.mergeFrom(bytes).build, Some(loader))
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Deserializes a RemoteActorRefProtocol Protocol Buffers (protobuf) Message into an RemoteActorRef instance.
|
|
|
|
|
*/
|
|
|
|
|
private[akka] def fromProtobufToRemoteActorRef(protocol: RemoteActorRefProtocol, loader: Option[ClassLoader]): ActorRef = {
|
|
|
|
|
Actor.log.debug("Deserializing RemoteActorRefProtocol to RemoteActorRef:\n" + protocol)
|
|
|
|
|
RemoteActorRef(
|
2010-09-17 16:04:25 +02:00
|
|
|
protocol.getClassOrServiceName,
|
2010-08-28 16:48:27 +02:00
|
|
|
protocol.getActorClassname,
|
|
|
|
|
protocol.getHomeAddress.getHostname,
|
|
|
|
|
protocol.getHomeAddress.getPort,
|
|
|
|
|
protocol.getTimeout,
|
|
|
|
|
loader)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Serializes the ActorRef instance into a Protocol Buffers (protobuf) Message.
|
|
|
|
|
*/
|
|
|
|
|
def toRemoteActorRefProtocol(ar: ActorRef): RemoteActorRefProtocol = {
|
|
|
|
|
import ar._
|
|
|
|
|
val host = homeAddress.getHostName
|
|
|
|
|
val port = homeAddress.getPort
|
|
|
|
|
|
|
|
|
|
if (!registeredInRemoteNodeDuringSerialization) {
|
|
|
|
|
Actor.log.debug("Register serialized Actor [%s] as remote @ [%s:%s]", actorClass.getName, host, port)
|
|
|
|
|
RemoteServer.getOrCreateServer(homeAddress)
|
2010-09-21 16:00:47 +02:00
|
|
|
RemoteServer.registerActorByUuid(homeAddress, uuid.toString, ar)
|
2010-08-28 16:48:27 +02:00
|
|
|
registeredInRemoteNodeDuringSerialization = true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RemoteActorRefProtocol.newBuilder
|
2010-09-19 17:02:15 +02:00
|
|
|
.setClassOrServiceName(uuid.toString)
|
2010-08-28 16:48:27 +02:00
|
|
|
.setActorClassname(actorClass.getName)
|
|
|
|
|
.setHomeAddress(AddressProtocol.newBuilder.setHostname(host).setPort(port).build)
|
|
|
|
|
.setTimeout(timeout)
|
|
|
|
|
.build
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def createRemoteRequestProtocolBuilder(
|
2010-09-17 09:56:36 +02:00
|
|
|
actorRef: ActorRef,
|
|
|
|
|
message: Any,
|
|
|
|
|
isOneWay: Boolean,
|
|
|
|
|
senderOption: Option[ActorRef],
|
|
|
|
|
typedActorInfo: Option[Tuple2[String, String]],
|
|
|
|
|
actorType: ActorType):
|
|
|
|
|
RemoteRequestProtocol.Builder = {
|
2010-08-28 16:48:27 +02:00
|
|
|
import actorRef._
|
|
|
|
|
|
|
|
|
|
val actorInfoBuilder = ActorInfoProtocol.newBuilder
|
2010-09-17 16:04:25 +02:00
|
|
|
.setUuid(UuidProtocol.newBuilder.setHigh(uuid.getTime).setLow(uuid.getClockSeqAndNode).build)
|
2010-09-16 13:50:57 +02:00
|
|
|
.setId(actorRef.id)
|
2010-08-28 16:48:27 +02:00
|
|
|
.setTarget(actorClassName)
|
|
|
|
|
.setTimeout(timeout)
|
|
|
|
|
|
2010-09-17 09:56:36 +02:00
|
|
|
typedActorInfo.foreach {
|
|
|
|
|
typedActor =>
|
|
|
|
|
actorInfoBuilder.setTypedActorInfo(
|
|
|
|
|
TypedActorInfoProtocol.newBuilder
|
|
|
|
|
.setInterface(typedActor._1)
|
|
|
|
|
.setMethod(typedActor._2)
|
|
|
|
|
.build)
|
2010-08-28 16:48:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
actorType match {
|
|
|
|
|
case ActorType.ScalaActor => actorInfoBuilder.setActorType(SCALA_ACTOR)
|
|
|
|
|
case ActorType.TypedActor => actorInfoBuilder.setActorType(TYPED_ACTOR)
|
|
|
|
|
}
|
|
|
|
|
val actorInfo = actorInfoBuilder.build
|
|
|
|
|
|
|
|
|
|
val requestBuilder = RemoteRequestProtocol.newBuilder
|
2010-09-17 16:04:25 +02:00
|
|
|
.setUuid(UuidProtocol.newBuilder.setHigh(uuid.getTime).setLow(uuid.getClockSeqAndNode).build)
|
2010-08-28 16:48:27 +02:00
|
|
|
.setMessage(MessageSerializer.serialize(message))
|
|
|
|
|
.setActorInfo(actorInfo)
|
|
|
|
|
.setIsOneWay(isOneWay)
|
|
|
|
|
|
|
|
|
|
val id = registerSupervisorAsRemoteActor
|
2010-09-17 16:04:25 +02:00
|
|
|
if (id.isDefined) requestBuilder.setSupervisorUuid(UuidProtocol.newBuilder.setHigh(id.get.getTime).setLow(id.get.getClockSeqAndNode).build)
|
2010-08-28 16:48:27 +02:00
|
|
|
|
|
|
|
|
senderOption.foreach { sender =>
|
2010-09-17 16:04:25 +02:00
|
|
|
RemoteServer.getOrCreateServer(sender.homeAddress).register(sender.uuid.toString, sender)
|
2010-08-28 16:48:27 +02:00
|
|
|
requestBuilder.setSender(toRemoteActorRefProtocol(sender))
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
requestBuilder
|
|
|
|
|
}
|
2010-09-17 09:56:36 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Module for local typed actor serialization.
|
|
|
|
|
*/
|
|
|
|
|
object TypedActorSerialization {
|
|
|
|
|
|
|
|
|
|
def fromBinary[T <: Actor, U <: AnyRef](bytes: Array[Byte])(implicit format: Format[T]): U =
|
|
|
|
|
fromBinaryToLocalTypedActorRef(bytes, format)
|
|
|
|
|
|
|
|
|
|
def toBinary[T <: Actor](proxy: AnyRef)(implicit format: Format[T]): Array[Byte] = {
|
|
|
|
|
toSerializedTypedActorRefProtocol(proxy, format).toByteArray
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// wrapper for implicits to be used by Java
|
|
|
|
|
def fromBinaryJ[T <: Actor, U <: AnyRef](bytes: Array[Byte], format: Format[T]): U =
|
|
|
|
|
fromBinary(bytes)(format)
|
|
|
|
|
|
|
|
|
|
// wrapper for implicits to be used by Java
|
|
|
|
|
def toBinaryJ[T <: Actor](a: AnyRef, format: Format[T]): Array[Byte] =
|
|
|
|
|
toBinary(a)(format)
|
|
|
|
|
|
|
|
|
|
private def toSerializedTypedActorRefProtocol[T <: Actor](
|
|
|
|
|
proxy: AnyRef, format: Format[T]): SerializedTypedActorRefProtocol = {
|
|
|
|
|
|
|
|
|
|
val init = AspectInitRegistry.initFor(proxy)
|
|
|
|
|
if (init == null) throw new IllegalArgumentException("Proxy for typed actor could not be found in AspectInitRegistry.")
|
|
|
|
|
|
|
|
|
|
SerializedTypedActorRefProtocol.newBuilder
|
|
|
|
|
.setActorRef(ActorSerialization.toSerializedActorRefProtocol(init.actorRef, format))
|
|
|
|
|
.setInterfaceName(init.interfaceClass.getName)
|
|
|
|
|
.build
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private def fromBinaryToLocalTypedActorRef[T <: Actor, U <: AnyRef](bytes: Array[Byte], format: Format[T]): U =
|
|
|
|
|
fromProtobufToLocalTypedActorRef(SerializedTypedActorRefProtocol.newBuilder.mergeFrom(bytes).build, format, None)
|
|
|
|
|
|
|
|
|
|
private def fromProtobufToLocalTypedActorRef[T <: Actor, U <: AnyRef](
|
|
|
|
|
protocol: SerializedTypedActorRefProtocol, format: Format[T], loader: Option[ClassLoader]): U = {
|
|
|
|
|
Actor.log.debug("Deserializing SerializedTypedActorRefProtocol to LocalActorRef:\n" + protocol)
|
|
|
|
|
val actorRef = ActorSerialization.fromProtobufToLocalActorRef(protocol.getActorRef, format, loader)
|
|
|
|
|
val intfClass = toClass(loader, protocol.getInterfaceName)
|
|
|
|
|
TypedActor.newInstance(intfClass, actorRef).asInstanceOf[U]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private[akka] def toClass[U <: AnyRef](loader: Option[ClassLoader], name: String): Class[U] = {
|
|
|
|
|
val classLoader = loader.getOrElse(getClass.getClassLoader)
|
|
|
|
|
val clazz = classLoader.loadClass(name)
|
|
|
|
|
clazz.asInstanceOf[Class[U]]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Module for remote typed actor serialization.
|
|
|
|
|
*/
|
|
|
|
|
object RemoteTypedActorSerialization {
|
|
|
|
|
/**
|
|
|
|
|
* Deserializes a byte array (Array[Byte]) into an RemoteActorRef instance.
|
|
|
|
|
*/
|
|
|
|
|
def fromBinaryToRemoteTypedActorRef[T <: AnyRef](bytes: Array[Byte]): T =
|
|
|
|
|
fromProtobufToRemoteTypedActorRef(RemoteTypedActorRefProtocol.newBuilder.mergeFrom(bytes).build, None)
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Deserializes a byte array (Array[Byte]) into a AW RemoteActorRef proxy.
|
|
|
|
|
*/
|
|
|
|
|
def fromBinaryToRemoteTypedActorRef[T <: AnyRef](bytes: Array[Byte], loader: ClassLoader): T =
|
|
|
|
|
fromProtobufToRemoteTypedActorRef(RemoteTypedActorRefProtocol.newBuilder.mergeFrom(bytes).build, Some(loader))
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Serialize as AW RemoteActorRef proxy.
|
|
|
|
|
*/
|
|
|
|
|
def toBinary[T <: Actor](proxy: AnyRef): Array[Byte] = {
|
|
|
|
|
toRemoteTypedActorRefProtocol(proxy).toByteArray
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Deserializes a RemoteTypedActorRefProtocol Protocol Buffers (protobuf) Message into AW RemoteActorRef proxy.
|
|
|
|
|
*/
|
|
|
|
|
private[akka] def fromProtobufToRemoteTypedActorRef[T](protocol: RemoteTypedActorRefProtocol, loader: Option[ClassLoader]): T = {
|
|
|
|
|
Actor.log.debug("Deserializing RemoteTypedActorRefProtocol to AW RemoteActorRef proxy:\n" + protocol)
|
|
|
|
|
val actorRef = RemoteActorSerialization.fromProtobufToRemoteActorRef(protocol.getActorRef, loader)
|
|
|
|
|
val intfClass = TypedActorSerialization.toClass(loader, protocol.getInterfaceName)
|
|
|
|
|
TypedActor.createProxyForRemoteActorRef(intfClass, actorRef).asInstanceOf[T]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Serializes the AW TypedActor proxy into a Protocol Buffers (protobuf) Message.
|
|
|
|
|
*/
|
|
|
|
|
def toRemoteTypedActorRefProtocol(proxy: AnyRef): RemoteTypedActorRefProtocol = {
|
|
|
|
|
val init = AspectInitRegistry.initFor(proxy)
|
|
|
|
|
RemoteTypedActorRefProtocol.newBuilder
|
|
|
|
|
.setActorRef(RemoteActorSerialization.toRemoteActorRefProtocol(init.actorRef))
|
|
|
|
|
.setInterfaceName(init.interfaceClass.getName)
|
|
|
|
|
.build
|
|
|
|
|
}
|
|
|
|
|
|
2010-08-28 16:48:27 +02:00
|
|
|
}
|