diff --git a/akka-remote/src/main/scala/serialization/SerializationProtocol.scala b/akka-remote/src/main/scala/serialization/SerializationProtocol.scala index 427c3ad721..421217e10b 100644 --- a/akka-remote/src/main/scala/serialization/SerializationProtocol.scala +++ b/akka-remote/src/main/scala/serialization/SerializationProtocol.scala @@ -14,9 +14,12 @@ import ActorTypeProtocol._ import se.scalablesolutions.akka.config.{AllForOneStrategy, OneForOneStrategy, FaultHandlingStrategy} import se.scalablesolutions.akka.config.ScalaConfig._ import se.scalablesolutions.akka.actor.{uuidFrom,newUuid} -import com.google.protobuf.ByteString import se.scalablesolutions.akka.actor._ +import scala.collection.immutable.Stack + +import com.google.protobuf.ByteString + /** * Type class definition for Actor Serialization */ @@ -139,8 +142,7 @@ object ActorSerialization { 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(_)) + if (!actorRef.hotswap.isEmpty) builder.setHotswapStack(ByteString.copyFrom(Serializer.Java.toBinary(actorRef.hotswap))) builder.build } @@ -166,15 +168,14 @@ object ActorSerialization { } else UndefinedLifeCycle val supervisor = - if (protocol.hasSupervisor) - Some(RemoteActorSerialization.fromProtobufToRemoteActorRef(protocol.getSupervisor, loader)) - else None + if (protocol.hasSupervisor) Some(RemoteActorSerialization.fromProtobufToRemoteActorRef(protocol.getSupervisor, loader)) + else None - val hotswap = - if (serializer.isDefined && protocol.hasHotswapStack) Some(serializer.get - .fromBinary(protocol.getHotswapStack.toByteArray, Some(classOf[PartialFunction[Any, Unit]])) - .asInstanceOf[PartialFunction[Any, Unit]]) - else None + val hotswap = + if (serializer.isDefined && protocol.hasHotswapStack) serializer.get + .fromBinary(protocol.getHotswapStack.toByteArray, Some(classOf[Stack[PartialFunction[Any, Unit]]])) + .asInstanceOf[Stack[PartialFunction[Any, Unit]]] + else Stack[PartialFunction[Any, Unit]]() val classLoader = loader.getOrElse(getClass.getClassLoader) diff --git a/akka-remote/src/test/scala/serialization/SerializableTypeClassActorSpec.scala b/akka-remote/src/test/scala/serialization/SerializableTypeClassActorSpec.scala index dda4f0a6d6..681826a251 100644 --- a/akka-remote/src/test/scala/serialization/SerializableTypeClassActorSpec.scala +++ b/akka-remote/src/test/scala/serialization/SerializableTypeClassActorSpec.scala @@ -19,7 +19,6 @@ class SerializableTypeClassActorSpec extends ShouldMatchers with BeforeAndAfterAll { - object BinaryFormatMyActor { implicit object MyActorFormat extends Format[MyActor] { def fromBinary(bytes: Array[Byte], act: MyActor) = { @@ -145,8 +144,48 @@ class SerializableTypeClassActorSpec extends actor3.mailboxSize should equal(0) (actor3 !! "hello-reply").getOrElse("_") should equal("world") } - } + it("should be able to serialize and de-serialize an Actor hotswapped with 'become'") { + import BinaryFormatMyActor._ + val actor1 = actorOf[MyActor].start + (actor1 !! "hello").getOrElse("_") should equal("world 1") + (actor1 !! "hello").getOrElse("_") should equal("world 2") + actor1 ! "swap" + (actor1 !! "hello").getOrElse("_") should equal("swapped") + + val bytes = toBinary(actor1) + val actor2 = fromBinary(bytes) + actor2.start + + (actor1 !! "hello").getOrElse("_") should equal("swapped") + + actor1 ! RevertHotSwap + (actor2 !! "hello").getOrElse("_") should equal("world 3") + } +/* + it("should be able to serialize and de-serialize an hotswapped actor") { + import BinaryFormatMyActor._ + + val actor1 = actorOf[MyActor].start + (actor1 !! "hello").getOrElse("_") should equal("world 1") + (actor1 !! "hello").getOrElse("_") should equal("world 2") + actor1 ! HotSwap { + case "hello" => + self.reply("swapped") + } + (actor1 !! "hello").getOrElse("_") should equal("swapped") + + val bytes = toBinary(actor1) + val actor2 = fromBinary(bytes) + actor2.start + + (actor1 !! "hello").getOrElse("_") should equal("swapped") + + actor1 ! RevertHotSwap + (actor2 !! "hello").getOrElse("_") should equal("world 3") + } +*/ + } describe("Custom serializable actors") { it("should serialize and de-serialize") { import BinaryFormatMyActorWithSerializableMessages._ @@ -182,13 +221,15 @@ class MyActorWithDualCounter extends Actor { } } -class MyActor extends Actor { +@serializable class MyActor extends Actor { var count = 0 def receive = { case "hello" => count = count + 1 self.reply("world " + count) + case "swap" => + become { case "hello" => self.reply("swapped") } } }