From 6dd017d6c19e4975a257fad6cc5ec2150635ab80 Mon Sep 17 00:00:00 2001 From: Patrik Nordwall Date: Tue, 15 May 2012 09:40:13 +0200 Subject: [PATCH 01/21] Replace Java serialization of DaemonMsg by protobuf. See #1755 * Serializers for DaemonMsgCreate and DaemonMsgWatch * Protobuf for DaemonMsgCreateProtocol, PropsProtocol, DeployProtocol, DaemonMsgWatchProtocol * Removed unused MailboxProtocol.proto * Fixed wrong serializeActorRef in DurableMessageSerialization --- .../src/main/protocol/MailboxProtocol.proto | 30 - .../akka/actor/mailbox/DurableMailbox.scala | 10 +- .../main/java/akka/remote/RemoteProtocol.java | 2588 +++++++++++++++-- .../src/main/protocol/RemoteProtocol.proto | 39 +- akka-remote/src/main/resources/reference.conf | 4 + .../DaemonMsgCreateSerializer.scala | 139 + .../DaemonMsgWatchSerializer.scala | 41 + .../serialization/ProtobufSerializer.scala | 16 + .../DaemonMsgCreateSerializerSpec.scala | 104 + .../DaemonMsgWatchSerializerSpec.scala | 49 + 10 files changed, 2724 insertions(+), 296 deletions(-) delete mode 100644 akka-durable-mailboxes/akka-mailboxes-common/src/main/protocol/MailboxProtocol.proto create mode 100644 akka-remote/src/main/scala/akka/serialization/DaemonMsgCreateSerializer.scala create mode 100644 akka-remote/src/main/scala/akka/serialization/DaemonMsgWatchSerializer.scala create mode 100644 akka-remote/src/test/scala/akka/serialization/DaemonMsgCreateSerializerSpec.scala create mode 100644 akka-remote/src/test/scala/akka/serialization/DaemonMsgWatchSerializerSpec.scala diff --git a/akka-durable-mailboxes/akka-mailboxes-common/src/main/protocol/MailboxProtocol.proto b/akka-durable-mailboxes/akka-mailboxes-common/src/main/protocol/MailboxProtocol.proto deleted file mode 100644 index 96fab2bf95..0000000000 --- a/akka-durable-mailboxes/akka-mailboxes-common/src/main/protocol/MailboxProtocol.proto +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright (C) 2009-2012 Typesafe Inc. - */ - -option java_package = "akka.actor.mailbox"; -option optimize_for = SPEED; - -/****************************************** - Compile with: - cd ./akka-durable-mailboxes/akka-mailboxes-common/src/main/protocol - protoc MailboxProtocol.proto --java_out ../java -*******************************************/ - -/** - * Defines the durable mailbox message. - */ -message DurableMailboxMessageProtocol { - required string ownerAddress = 1; - optional string senderAddress = 2; - optional UuidProtocol futureUuid = 3; - required bytes message = 4; -} - -/** - * Defines a UUID. - */ -message UuidProtocol { - required uint64 high = 1; - required uint64 low = 2; -} diff --git a/akka-durable-mailboxes/akka-mailboxes-common/src/main/scala/akka/actor/mailbox/DurableMailbox.scala b/akka-durable-mailboxes/akka-mailboxes-common/src/main/scala/akka/actor/mailbox/DurableMailbox.scala index 41ec6d7307..db7b137bf0 100644 --- a/akka-durable-mailboxes/akka-mailboxes-common/src/main/scala/akka/actor/mailbox/DurableMailbox.scala +++ b/akka-durable-mailboxes/akka-mailboxes-common/src/main/scala/akka/actor/mailbox/DurableMailbox.scala @@ -9,6 +9,7 @@ import akka.remote.MessageSerializer import akka.remote.RemoteProtocol.{ ActorRefProtocol, RemoteMessageProtocol } import com.typesafe.config.Config import akka.actor.ActorSystem +import akka.serialization.Serialization private[akka] object DurableExecutableMailboxConfig { val Name = "[\\.\\/\\$\\s]".r @@ -26,9 +27,10 @@ abstract class DurableMessageQueue(val owner: ActorContext) extends MessageQueue trait DurableMessageSerialization { this: DurableMessageQueue ⇒ - def serialize(durableMessage: Envelope): Array[Byte] = { + import akka.serialization.ProtobufSerializer.serializeActorRef + import akka.serialization.ProtobufSerializer.deserializeActorRef - def serializeActorRef(ref: ActorRef): ActorRefProtocol = ActorRefProtocol.newBuilder.setPath(ref.path.toString).build + def serialize(durableMessage: Envelope): Array[Byte] = { val message = MessageSerializer.serialize(system, durableMessage.message.asInstanceOf[AnyRef]) val builder = RemoteMessageProtocol.newBuilder @@ -41,11 +43,9 @@ trait DurableMessageSerialization { this: DurableMessageQueue ⇒ def deserialize(bytes: Array[Byte]): Envelope = { - def deserializeActorRef(refProtocol: ActorRefProtocol): ActorRef = system.actorFor(refProtocol.getPath) - val durableMessage = RemoteMessageProtocol.parseFrom(bytes) val message = MessageSerializer.deserialize(system, durableMessage.getMessage) - val sender = deserializeActorRef(durableMessage.getSender) + val sender = deserializeActorRef(system, durableMessage.getSender) new Envelope(message, sender)(system) } diff --git a/akka-remote/src/main/java/akka/remote/RemoteProtocol.java b/akka-remote/src/main/java/akka/remote/RemoteProtocol.java index 21074a44c0..e340a807cf 100644 --- a/akka-remote/src/main/java/akka/remote/RemoteProtocol.java +++ b/akka-remote/src/main/java/akka/remote/RemoteProtocol.java @@ -309,7 +309,7 @@ public final class RemoteProtocol { maybeForceBuilderInitialization(); } - private Builder(com.google.protobuf.GeneratedMessage.BuilderParent parent) { + private Builder(BuilderParent parent) { super(parent); maybeForceBuilderInitialization(); } @@ -981,7 +981,7 @@ public final class RemoteProtocol { maybeForceBuilderInitialization(); } - private Builder(com.google.protobuf.GeneratedMessage.BuilderParent parent) { + private Builder(BuilderParent parent) { super(parent); maybeForceBuilderInitialization(); } @@ -1977,7 +1977,7 @@ public final class RemoteProtocol { maybeForceBuilderInitialization(); } - private Builder(com.google.protobuf.GeneratedMessage.BuilderParent parent) { + private Builder(BuilderParent parent) { super(parent); maybeForceBuilderInitialization(); } @@ -2527,7 +2527,7 @@ public final class RemoteProtocol { maybeForceBuilderInitialization(); } - private Builder(com.google.protobuf.GeneratedMessage.BuilderParent parent) { + private Builder(BuilderParent parent) { super(parent); maybeForceBuilderInitialization(); } @@ -2936,7 +2936,7 @@ public final class RemoteProtocol { maybeForceBuilderInitialization(); } - private Builder(com.google.protobuf.GeneratedMessage.BuilderParent parent) { + private Builder(BuilderParent parent) { super(parent); maybeForceBuilderInitialization(); } @@ -3410,7 +3410,7 @@ public final class RemoteProtocol { maybeForceBuilderInitialization(); } - private Builder(com.google.protobuf.GeneratedMessage.BuilderParent parent) { + private Builder(BuilderParent parent) { super(parent); maybeForceBuilderInitialization(); } @@ -3909,7 +3909,7 @@ public final class RemoteProtocol { maybeForceBuilderInitialization(); } - private Builder(com.google.protobuf.GeneratedMessage.BuilderParent parent) { + private Builder(BuilderParent parent) { super(parent); maybeForceBuilderInitialization(); } @@ -4172,115 +4172,166 @@ public final class RemoteProtocol { // @@protoc_insertion_point(class_scope:AddressProtocol) } - public interface DurableMailboxMessageProtocolOrBuilder + public interface DaemonMsgCreateProtocolOrBuilder extends com.google.protobuf.MessageOrBuilder { - // required .ActorRefProtocol recipient = 1; - boolean hasRecipient(); - akka.remote.RemoteProtocol.ActorRefProtocol getRecipient(); - akka.remote.RemoteProtocol.ActorRefProtocolOrBuilder getRecipientOrBuilder(); + // required .PropsProtocol props = 1; + boolean hasProps(); + akka.remote.RemoteProtocol.PropsProtocol getProps(); + akka.remote.RemoteProtocol.PropsProtocolOrBuilder getPropsOrBuilder(); - // optional .ActorRefProtocol sender = 2; - boolean hasSender(); - akka.remote.RemoteProtocol.ActorRefProtocol getSender(); - akka.remote.RemoteProtocol.ActorRefProtocolOrBuilder getSenderOrBuilder(); + // required .DeployProtocol deploy = 2; + boolean hasDeploy(); + akka.remote.RemoteProtocol.DeployProtocol getDeploy(); + akka.remote.RemoteProtocol.DeployProtocolOrBuilder getDeployOrBuilder(); - // required bytes message = 3; - boolean hasMessage(); - com.google.protobuf.ByteString getMessage(); + // required string path = 3; + boolean hasPath(); + String getPath(); + + // required .ActorRefProtocol supervisor = 4; + boolean hasSupervisor(); + akka.remote.RemoteProtocol.ActorRefProtocol getSupervisor(); + akka.remote.RemoteProtocol.ActorRefProtocolOrBuilder getSupervisorOrBuilder(); } - public static final class DurableMailboxMessageProtocol extends + public static final class DaemonMsgCreateProtocol extends com.google.protobuf.GeneratedMessage - implements DurableMailboxMessageProtocolOrBuilder { - // Use DurableMailboxMessageProtocol.newBuilder() to construct. - private DurableMailboxMessageProtocol(Builder builder) { + implements DaemonMsgCreateProtocolOrBuilder { + // Use DaemonMsgCreateProtocol.newBuilder() to construct. + private DaemonMsgCreateProtocol(Builder builder) { super(builder); } - private DurableMailboxMessageProtocol(boolean noInit) {} + private DaemonMsgCreateProtocol(boolean noInit) {} - private static final DurableMailboxMessageProtocol defaultInstance; - public static DurableMailboxMessageProtocol getDefaultInstance() { + private static final DaemonMsgCreateProtocol defaultInstance; + public static DaemonMsgCreateProtocol getDefaultInstance() { return defaultInstance; } - public DurableMailboxMessageProtocol getDefaultInstanceForType() { + public DaemonMsgCreateProtocol getDefaultInstanceForType() { return defaultInstance; } public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return akka.remote.RemoteProtocol.internal_static_DurableMailboxMessageProtocol_descriptor; + return akka.remote.RemoteProtocol.internal_static_DaemonMsgCreateProtocol_descriptor; } protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return akka.remote.RemoteProtocol.internal_static_DurableMailboxMessageProtocol_fieldAccessorTable; + return akka.remote.RemoteProtocol.internal_static_DaemonMsgCreateProtocol_fieldAccessorTable; } private int bitField0_; - // required .ActorRefProtocol recipient = 1; - public static final int RECIPIENT_FIELD_NUMBER = 1; - private akka.remote.RemoteProtocol.ActorRefProtocol recipient_; - public boolean hasRecipient() { + // required .PropsProtocol props = 1; + public static final int PROPS_FIELD_NUMBER = 1; + private akka.remote.RemoteProtocol.PropsProtocol props_; + public boolean hasProps() { return ((bitField0_ & 0x00000001) == 0x00000001); } - public akka.remote.RemoteProtocol.ActorRefProtocol getRecipient() { - return recipient_; + public akka.remote.RemoteProtocol.PropsProtocol getProps() { + return props_; } - public akka.remote.RemoteProtocol.ActorRefProtocolOrBuilder getRecipientOrBuilder() { - return recipient_; + public akka.remote.RemoteProtocol.PropsProtocolOrBuilder getPropsOrBuilder() { + return props_; } - // optional .ActorRefProtocol sender = 2; - public static final int SENDER_FIELD_NUMBER = 2; - private akka.remote.RemoteProtocol.ActorRefProtocol sender_; - public boolean hasSender() { + // required .DeployProtocol deploy = 2; + public static final int DEPLOY_FIELD_NUMBER = 2; + private akka.remote.RemoteProtocol.DeployProtocol deploy_; + public boolean hasDeploy() { return ((bitField0_ & 0x00000002) == 0x00000002); } - public akka.remote.RemoteProtocol.ActorRefProtocol getSender() { - return sender_; + public akka.remote.RemoteProtocol.DeployProtocol getDeploy() { + return deploy_; } - public akka.remote.RemoteProtocol.ActorRefProtocolOrBuilder getSenderOrBuilder() { - return sender_; + public akka.remote.RemoteProtocol.DeployProtocolOrBuilder getDeployOrBuilder() { + return deploy_; } - // required bytes message = 3; - public static final int MESSAGE_FIELD_NUMBER = 3; - private com.google.protobuf.ByteString message_; - public boolean hasMessage() { + // required string path = 3; + public static final int PATH_FIELD_NUMBER = 3; + private java.lang.Object path_; + public boolean hasPath() { return ((bitField0_ & 0x00000004) == 0x00000004); } - public com.google.protobuf.ByteString getMessage() { - return message_; + public String getPath() { + java.lang.Object ref = path_; + if (ref instanceof String) { + return (String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + if (com.google.protobuf.Internal.isValidUtf8(bs)) { + path_ = s; + } + return s; + } + } + private com.google.protobuf.ByteString getPathBytes() { + java.lang.Object ref = path_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8((String) ref); + path_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + // required .ActorRefProtocol supervisor = 4; + public static final int SUPERVISOR_FIELD_NUMBER = 4; + private akka.remote.RemoteProtocol.ActorRefProtocol supervisor_; + public boolean hasSupervisor() { + return ((bitField0_ & 0x00000008) == 0x00000008); + } + public akka.remote.RemoteProtocol.ActorRefProtocol getSupervisor() { + return supervisor_; + } + public akka.remote.RemoteProtocol.ActorRefProtocolOrBuilder getSupervisorOrBuilder() { + return supervisor_; } private void initFields() { - recipient_ = akka.remote.RemoteProtocol.ActorRefProtocol.getDefaultInstance(); - sender_ = akka.remote.RemoteProtocol.ActorRefProtocol.getDefaultInstance(); - message_ = com.google.protobuf.ByteString.EMPTY; + props_ = akka.remote.RemoteProtocol.PropsProtocol.getDefaultInstance(); + deploy_ = akka.remote.RemoteProtocol.DeployProtocol.getDefaultInstance(); + path_ = ""; + supervisor_ = akka.remote.RemoteProtocol.ActorRefProtocol.getDefaultInstance(); } private byte memoizedIsInitialized = -1; public final boolean isInitialized() { byte isInitialized = memoizedIsInitialized; if (isInitialized != -1) return isInitialized == 1; - if (!hasRecipient()) { + if (!hasProps()) { memoizedIsInitialized = 0; return false; } - if (!hasMessage()) { + if (!hasDeploy()) { memoizedIsInitialized = 0; return false; } - if (!getRecipient().isInitialized()) { + if (!hasPath()) { memoizedIsInitialized = 0; return false; } - if (hasSender()) { - if (!getSender().isInitialized()) { - memoizedIsInitialized = 0; - return false; - } + if (!hasSupervisor()) { + memoizedIsInitialized = 0; + return false; + } + if (!getProps().isInitialized()) { + memoizedIsInitialized = 0; + return false; + } + if (!getDeploy().isInitialized()) { + memoizedIsInitialized = 0; + return false; + } + if (!getSupervisor().isInitialized()) { + memoizedIsInitialized = 0; + return false; } memoizedIsInitialized = 1; return true; @@ -4290,13 +4341,16 @@ public final class RemoteProtocol { throws java.io.IOException { getSerializedSize(); if (((bitField0_ & 0x00000001) == 0x00000001)) { - output.writeMessage(1, recipient_); + output.writeMessage(1, props_); } if (((bitField0_ & 0x00000002) == 0x00000002)) { - output.writeMessage(2, sender_); + output.writeMessage(2, deploy_); } if (((bitField0_ & 0x00000004) == 0x00000004)) { - output.writeBytes(3, message_); + output.writeBytes(3, getPathBytes()); + } + if (((bitField0_ & 0x00000008) == 0x00000008)) { + output.writeMessage(4, supervisor_); } getUnknownFields().writeTo(output); } @@ -4309,15 +4363,19 @@ public final class RemoteProtocol { size = 0; if (((bitField0_ & 0x00000001) == 0x00000001)) { size += com.google.protobuf.CodedOutputStream - .computeMessageSize(1, recipient_); + .computeMessageSize(1, props_); } if (((bitField0_ & 0x00000002) == 0x00000002)) { size += com.google.protobuf.CodedOutputStream - .computeMessageSize(2, sender_); + .computeMessageSize(2, deploy_); } if (((bitField0_ & 0x00000004) == 0x00000004)) { size += com.google.protobuf.CodedOutputStream - .computeBytesSize(3, message_); + .computeBytesSize(3, getPathBytes()); + } + if (((bitField0_ & 0x00000008) == 0x00000008)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(4, supervisor_); } size += getUnknownFields().getSerializedSize(); memoizedSerializedSize = size; @@ -4331,41 +4389,41 @@ public final class RemoteProtocol { return super.writeReplace(); } - public static akka.remote.RemoteProtocol.DurableMailboxMessageProtocol parseFrom( + public static akka.remote.RemoteProtocol.DaemonMsgCreateProtocol parseFrom( com.google.protobuf.ByteString data) throws com.google.protobuf.InvalidProtocolBufferException { return newBuilder().mergeFrom(data).buildParsed(); } - public static akka.remote.RemoteProtocol.DurableMailboxMessageProtocol parseFrom( + public static akka.remote.RemoteProtocol.DaemonMsgCreateProtocol parseFrom( com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return newBuilder().mergeFrom(data, extensionRegistry) .buildParsed(); } - public static akka.remote.RemoteProtocol.DurableMailboxMessageProtocol parseFrom(byte[] data) + public static akka.remote.RemoteProtocol.DaemonMsgCreateProtocol parseFrom(byte[] data) throws com.google.protobuf.InvalidProtocolBufferException { return newBuilder().mergeFrom(data).buildParsed(); } - public static akka.remote.RemoteProtocol.DurableMailboxMessageProtocol parseFrom( + public static akka.remote.RemoteProtocol.DaemonMsgCreateProtocol parseFrom( byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return newBuilder().mergeFrom(data, extensionRegistry) .buildParsed(); } - public static akka.remote.RemoteProtocol.DurableMailboxMessageProtocol parseFrom(java.io.InputStream input) + public static akka.remote.RemoteProtocol.DaemonMsgCreateProtocol parseFrom(java.io.InputStream input) throws java.io.IOException { return newBuilder().mergeFrom(input).buildParsed(); } - public static akka.remote.RemoteProtocol.DurableMailboxMessageProtocol parseFrom( + public static akka.remote.RemoteProtocol.DaemonMsgCreateProtocol parseFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return newBuilder().mergeFrom(input, extensionRegistry) .buildParsed(); } - public static akka.remote.RemoteProtocol.DurableMailboxMessageProtocol parseDelimitedFrom(java.io.InputStream input) + public static akka.remote.RemoteProtocol.DaemonMsgCreateProtocol parseDelimitedFrom(java.io.InputStream input) throws java.io.IOException { Builder builder = newBuilder(); if (builder.mergeDelimitedFrom(input)) { @@ -4374,7 +4432,7 @@ public final class RemoteProtocol { return null; } } - public static akka.remote.RemoteProtocol.DurableMailboxMessageProtocol parseDelimitedFrom( + public static akka.remote.RemoteProtocol.DaemonMsgCreateProtocol parseDelimitedFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { @@ -4385,12 +4443,12 @@ public final class RemoteProtocol { return null; } } - public static akka.remote.RemoteProtocol.DurableMailboxMessageProtocol parseFrom( + public static akka.remote.RemoteProtocol.DaemonMsgCreateProtocol parseFrom( com.google.protobuf.CodedInputStream input) throws java.io.IOException { return newBuilder().mergeFrom(input).buildParsed(); } - public static akka.remote.RemoteProtocol.DurableMailboxMessageProtocol parseFrom( + public static akka.remote.RemoteProtocol.DaemonMsgCreateProtocol parseFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { @@ -4400,7 +4458,7 @@ public final class RemoteProtocol { public static Builder newBuilder() { return Builder.create(); } public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder(akka.remote.RemoteProtocol.DurableMailboxMessageProtocol prototype) { + public static Builder newBuilder(akka.remote.RemoteProtocol.DaemonMsgCreateProtocol prototype) { return newBuilder().mergeFrom(prototype); } public Builder toBuilder() { return newBuilder(this); } @@ -4413,30 +4471,31 @@ public final class RemoteProtocol { } public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder - implements akka.remote.RemoteProtocol.DurableMailboxMessageProtocolOrBuilder { + implements akka.remote.RemoteProtocol.DaemonMsgCreateProtocolOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return akka.remote.RemoteProtocol.internal_static_DurableMailboxMessageProtocol_descriptor; + return akka.remote.RemoteProtocol.internal_static_DaemonMsgCreateProtocol_descriptor; } protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { - return akka.remote.RemoteProtocol.internal_static_DurableMailboxMessageProtocol_fieldAccessorTable; + return akka.remote.RemoteProtocol.internal_static_DaemonMsgCreateProtocol_fieldAccessorTable; } - // Construct using akka.remote.RemoteProtocol.DurableMailboxMessageProtocol.newBuilder() + // Construct using akka.remote.RemoteProtocol.DaemonMsgCreateProtocol.newBuilder() private Builder() { maybeForceBuilderInitialization(); } - private Builder(com.google.protobuf.GeneratedMessage.BuilderParent parent) { + private Builder(BuilderParent parent) { super(parent); maybeForceBuilderInitialization(); } private void maybeForceBuilderInitialization() { if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { - getRecipientFieldBuilder(); - getSenderFieldBuilder(); + getPropsFieldBuilder(); + getDeployFieldBuilder(); + getSupervisorFieldBuilder(); } } private static Builder create() { @@ -4445,20 +4504,26 @@ public final class RemoteProtocol { public Builder clear() { super.clear(); - if (recipientBuilder_ == null) { - recipient_ = akka.remote.RemoteProtocol.ActorRefProtocol.getDefaultInstance(); + if (propsBuilder_ == null) { + props_ = akka.remote.RemoteProtocol.PropsProtocol.getDefaultInstance(); } else { - recipientBuilder_.clear(); + propsBuilder_.clear(); } bitField0_ = (bitField0_ & ~0x00000001); - if (senderBuilder_ == null) { - sender_ = akka.remote.RemoteProtocol.ActorRefProtocol.getDefaultInstance(); + if (deployBuilder_ == null) { + deploy_ = akka.remote.RemoteProtocol.DeployProtocol.getDefaultInstance(); } else { - senderBuilder_.clear(); + deployBuilder_.clear(); } bitField0_ = (bitField0_ & ~0x00000002); - message_ = com.google.protobuf.ByteString.EMPTY; + path_ = ""; bitField0_ = (bitField0_ & ~0x00000004); + if (supervisorBuilder_ == null) { + supervisor_ = akka.remote.RemoteProtocol.ActorRefProtocol.getDefaultInstance(); + } else { + supervisorBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000008); return this; } @@ -4468,24 +4533,24 @@ public final class RemoteProtocol { public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return akka.remote.RemoteProtocol.DurableMailboxMessageProtocol.getDescriptor(); + return akka.remote.RemoteProtocol.DaemonMsgCreateProtocol.getDescriptor(); } - public akka.remote.RemoteProtocol.DurableMailboxMessageProtocol getDefaultInstanceForType() { - return akka.remote.RemoteProtocol.DurableMailboxMessageProtocol.getDefaultInstance(); + public akka.remote.RemoteProtocol.DaemonMsgCreateProtocol getDefaultInstanceForType() { + return akka.remote.RemoteProtocol.DaemonMsgCreateProtocol.getDefaultInstance(); } - public akka.remote.RemoteProtocol.DurableMailboxMessageProtocol build() { - akka.remote.RemoteProtocol.DurableMailboxMessageProtocol result = buildPartial(); + public akka.remote.RemoteProtocol.DaemonMsgCreateProtocol build() { + akka.remote.RemoteProtocol.DaemonMsgCreateProtocol result = buildPartial(); if (!result.isInitialized()) { throw newUninitializedMessageException(result); } return result; } - private akka.remote.RemoteProtocol.DurableMailboxMessageProtocol buildParsed() + private akka.remote.RemoteProtocol.DaemonMsgCreateProtocol buildParsed() throws com.google.protobuf.InvalidProtocolBufferException { - akka.remote.RemoteProtocol.DurableMailboxMessageProtocol result = buildPartial(); + akka.remote.RemoteProtocol.DaemonMsgCreateProtocol result = buildPartial(); if (!result.isInitialized()) { throw newUninitializedMessageException( result).asInvalidProtocolBufferException(); @@ -4493,78 +4558,2071 @@ public final class RemoteProtocol { return result; } - public akka.remote.RemoteProtocol.DurableMailboxMessageProtocol buildPartial() { - akka.remote.RemoteProtocol.DurableMailboxMessageProtocol result = new akka.remote.RemoteProtocol.DurableMailboxMessageProtocol(this); + public akka.remote.RemoteProtocol.DaemonMsgCreateProtocol buildPartial() { + akka.remote.RemoteProtocol.DaemonMsgCreateProtocol result = new akka.remote.RemoteProtocol.DaemonMsgCreateProtocol(this); int from_bitField0_ = bitField0_; int to_bitField0_ = 0; if (((from_bitField0_ & 0x00000001) == 0x00000001)) { to_bitField0_ |= 0x00000001; } - if (recipientBuilder_ == null) { - result.recipient_ = recipient_; + if (propsBuilder_ == null) { + result.props_ = props_; } else { - result.recipient_ = recipientBuilder_.build(); + result.props_ = propsBuilder_.build(); } if (((from_bitField0_ & 0x00000002) == 0x00000002)) { to_bitField0_ |= 0x00000002; } - if (senderBuilder_ == null) { - result.sender_ = sender_; + if (deployBuilder_ == null) { + result.deploy_ = deploy_; } else { - result.sender_ = senderBuilder_.build(); + result.deploy_ = deployBuilder_.build(); } if (((from_bitField0_ & 0x00000004) == 0x00000004)) { to_bitField0_ |= 0x00000004; } - result.message_ = message_; + result.path_ = path_; + if (((from_bitField0_ & 0x00000008) == 0x00000008)) { + to_bitField0_ |= 0x00000008; + } + if (supervisorBuilder_ == null) { + result.supervisor_ = supervisor_; + } else { + result.supervisor_ = supervisorBuilder_.build(); + } result.bitField0_ = to_bitField0_; onBuilt(); return result; } public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof akka.remote.RemoteProtocol.DurableMailboxMessageProtocol) { - return mergeFrom((akka.remote.RemoteProtocol.DurableMailboxMessageProtocol)other); + if (other instanceof akka.remote.RemoteProtocol.DaemonMsgCreateProtocol) { + return mergeFrom((akka.remote.RemoteProtocol.DaemonMsgCreateProtocol)other); } else { super.mergeFrom(other); return this; } } - public Builder mergeFrom(akka.remote.RemoteProtocol.DurableMailboxMessageProtocol other) { - if (other == akka.remote.RemoteProtocol.DurableMailboxMessageProtocol.getDefaultInstance()) return this; - if (other.hasRecipient()) { - mergeRecipient(other.getRecipient()); + public Builder mergeFrom(akka.remote.RemoteProtocol.DaemonMsgCreateProtocol other) { + if (other == akka.remote.RemoteProtocol.DaemonMsgCreateProtocol.getDefaultInstance()) return this; + if (other.hasProps()) { + mergeProps(other.getProps()); } - if (other.hasSender()) { - mergeSender(other.getSender()); + if (other.hasDeploy()) { + mergeDeploy(other.getDeploy()); } - if (other.hasMessage()) { - setMessage(other.getMessage()); + if (other.hasPath()) { + setPath(other.getPath()); + } + if (other.hasSupervisor()) { + mergeSupervisor(other.getSupervisor()); } this.mergeUnknownFields(other.getUnknownFields()); return this; } public final boolean isInitialized() { - if (!hasRecipient()) { + if (!hasProps()) { return false; } - if (!hasMessage()) { + if (!hasDeploy()) { return false; } - if (!getRecipient().isInitialized()) { + if (!hasPath()) { return false; } - if (hasSender()) { - if (!getSender().isInitialized()) { - - return false; + if (!hasSupervisor()) { + + return false; + } + if (!getProps().isInitialized()) { + + return false; + } + if (!getDeploy().isInitialized()) { + + return false; + } + if (!getSupervisor().isInitialized()) { + + return false; + } + return true; + } + + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + onChanged(); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + onChanged(); + return this; + } + break; + } + case 10: { + akka.remote.RemoteProtocol.PropsProtocol.Builder subBuilder = akka.remote.RemoteProtocol.PropsProtocol.newBuilder(); + if (hasProps()) { + subBuilder.mergeFrom(getProps()); + } + input.readMessage(subBuilder, extensionRegistry); + setProps(subBuilder.buildPartial()); + break; + } + case 18: { + akka.remote.RemoteProtocol.DeployProtocol.Builder subBuilder = akka.remote.RemoteProtocol.DeployProtocol.newBuilder(); + if (hasDeploy()) { + subBuilder.mergeFrom(getDeploy()); + } + input.readMessage(subBuilder, extensionRegistry); + setDeploy(subBuilder.buildPartial()); + break; + } + case 26: { + bitField0_ |= 0x00000004; + path_ = input.readBytes(); + break; + } + case 34: { + akka.remote.RemoteProtocol.ActorRefProtocol.Builder subBuilder = akka.remote.RemoteProtocol.ActorRefProtocol.newBuilder(); + if (hasSupervisor()) { + subBuilder.mergeFrom(getSupervisor()); + } + input.readMessage(subBuilder, extensionRegistry); + setSupervisor(subBuilder.buildPartial()); + break; + } } } + } + + private int bitField0_; + + // required .PropsProtocol props = 1; + private akka.remote.RemoteProtocol.PropsProtocol props_ = akka.remote.RemoteProtocol.PropsProtocol.getDefaultInstance(); + private com.google.protobuf.SingleFieldBuilder< + akka.remote.RemoteProtocol.PropsProtocol, akka.remote.RemoteProtocol.PropsProtocol.Builder, akka.remote.RemoteProtocol.PropsProtocolOrBuilder> propsBuilder_; + public boolean hasProps() { + return ((bitField0_ & 0x00000001) == 0x00000001); + } + public akka.remote.RemoteProtocol.PropsProtocol getProps() { + if (propsBuilder_ == null) { + return props_; + } else { + return propsBuilder_.getMessage(); + } + } + public Builder setProps(akka.remote.RemoteProtocol.PropsProtocol value) { + if (propsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + props_ = value; + onChanged(); + } else { + propsBuilder_.setMessage(value); + } + bitField0_ |= 0x00000001; + return this; + } + public Builder setProps( + akka.remote.RemoteProtocol.PropsProtocol.Builder builderForValue) { + if (propsBuilder_ == null) { + props_ = builderForValue.build(); + onChanged(); + } else { + propsBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000001; + return this; + } + public Builder mergeProps(akka.remote.RemoteProtocol.PropsProtocol value) { + if (propsBuilder_ == null) { + if (((bitField0_ & 0x00000001) == 0x00000001) && + props_ != akka.remote.RemoteProtocol.PropsProtocol.getDefaultInstance()) { + props_ = + akka.remote.RemoteProtocol.PropsProtocol.newBuilder(props_).mergeFrom(value).buildPartial(); + } else { + props_ = value; + } + onChanged(); + } else { + propsBuilder_.mergeFrom(value); + } + bitField0_ |= 0x00000001; + return this; + } + public Builder clearProps() { + if (propsBuilder_ == null) { + props_ = akka.remote.RemoteProtocol.PropsProtocol.getDefaultInstance(); + onChanged(); + } else { + propsBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000001); + return this; + } + public akka.remote.RemoteProtocol.PropsProtocol.Builder getPropsBuilder() { + bitField0_ |= 0x00000001; + onChanged(); + return getPropsFieldBuilder().getBuilder(); + } + public akka.remote.RemoteProtocol.PropsProtocolOrBuilder getPropsOrBuilder() { + if (propsBuilder_ != null) { + return propsBuilder_.getMessageOrBuilder(); + } else { + return props_; + } + } + private com.google.protobuf.SingleFieldBuilder< + akka.remote.RemoteProtocol.PropsProtocol, akka.remote.RemoteProtocol.PropsProtocol.Builder, akka.remote.RemoteProtocol.PropsProtocolOrBuilder> + getPropsFieldBuilder() { + if (propsBuilder_ == null) { + propsBuilder_ = new com.google.protobuf.SingleFieldBuilder< + akka.remote.RemoteProtocol.PropsProtocol, akka.remote.RemoteProtocol.PropsProtocol.Builder, akka.remote.RemoteProtocol.PropsProtocolOrBuilder>( + props_, + getParentForChildren(), + isClean()); + props_ = null; + } + return propsBuilder_; + } + + // required .DeployProtocol deploy = 2; + private akka.remote.RemoteProtocol.DeployProtocol deploy_ = akka.remote.RemoteProtocol.DeployProtocol.getDefaultInstance(); + private com.google.protobuf.SingleFieldBuilder< + akka.remote.RemoteProtocol.DeployProtocol, akka.remote.RemoteProtocol.DeployProtocol.Builder, akka.remote.RemoteProtocol.DeployProtocolOrBuilder> deployBuilder_; + public boolean hasDeploy() { + return ((bitField0_ & 0x00000002) == 0x00000002); + } + public akka.remote.RemoteProtocol.DeployProtocol getDeploy() { + if (deployBuilder_ == null) { + return deploy_; + } else { + return deployBuilder_.getMessage(); + } + } + public Builder setDeploy(akka.remote.RemoteProtocol.DeployProtocol value) { + if (deployBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + deploy_ = value; + onChanged(); + } else { + deployBuilder_.setMessage(value); + } + bitField0_ |= 0x00000002; + return this; + } + public Builder setDeploy( + akka.remote.RemoteProtocol.DeployProtocol.Builder builderForValue) { + if (deployBuilder_ == null) { + deploy_ = builderForValue.build(); + onChanged(); + } else { + deployBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000002; + return this; + } + public Builder mergeDeploy(akka.remote.RemoteProtocol.DeployProtocol value) { + if (deployBuilder_ == null) { + if (((bitField0_ & 0x00000002) == 0x00000002) && + deploy_ != akka.remote.RemoteProtocol.DeployProtocol.getDefaultInstance()) { + deploy_ = + akka.remote.RemoteProtocol.DeployProtocol.newBuilder(deploy_).mergeFrom(value).buildPartial(); + } else { + deploy_ = value; + } + onChanged(); + } else { + deployBuilder_.mergeFrom(value); + } + bitField0_ |= 0x00000002; + return this; + } + public Builder clearDeploy() { + if (deployBuilder_ == null) { + deploy_ = akka.remote.RemoteProtocol.DeployProtocol.getDefaultInstance(); + onChanged(); + } else { + deployBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000002); + return this; + } + public akka.remote.RemoteProtocol.DeployProtocol.Builder getDeployBuilder() { + bitField0_ |= 0x00000002; + onChanged(); + return getDeployFieldBuilder().getBuilder(); + } + public akka.remote.RemoteProtocol.DeployProtocolOrBuilder getDeployOrBuilder() { + if (deployBuilder_ != null) { + return deployBuilder_.getMessageOrBuilder(); + } else { + return deploy_; + } + } + private com.google.protobuf.SingleFieldBuilder< + akka.remote.RemoteProtocol.DeployProtocol, akka.remote.RemoteProtocol.DeployProtocol.Builder, akka.remote.RemoteProtocol.DeployProtocolOrBuilder> + getDeployFieldBuilder() { + if (deployBuilder_ == null) { + deployBuilder_ = new com.google.protobuf.SingleFieldBuilder< + akka.remote.RemoteProtocol.DeployProtocol, akka.remote.RemoteProtocol.DeployProtocol.Builder, akka.remote.RemoteProtocol.DeployProtocolOrBuilder>( + deploy_, + getParentForChildren(), + isClean()); + deploy_ = null; + } + return deployBuilder_; + } + + // required string path = 3; + private java.lang.Object path_ = ""; + public boolean hasPath() { + return ((bitField0_ & 0x00000004) == 0x00000004); + } + public String getPath() { + java.lang.Object ref = path_; + if (!(ref instanceof String)) { + String s = ((com.google.protobuf.ByteString) ref).toStringUtf8(); + path_ = s; + return s; + } else { + return (String) ref; + } + } + public Builder setPath(String value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000004; + path_ = value; + onChanged(); + return this; + } + public Builder clearPath() { + bitField0_ = (bitField0_ & ~0x00000004); + path_ = getDefaultInstance().getPath(); + onChanged(); + return this; + } + void setPath(com.google.protobuf.ByteString value) { + bitField0_ |= 0x00000004; + path_ = value; + onChanged(); + } + + // required .ActorRefProtocol supervisor = 4; + private akka.remote.RemoteProtocol.ActorRefProtocol supervisor_ = akka.remote.RemoteProtocol.ActorRefProtocol.getDefaultInstance(); + private com.google.protobuf.SingleFieldBuilder< + akka.remote.RemoteProtocol.ActorRefProtocol, akka.remote.RemoteProtocol.ActorRefProtocol.Builder, akka.remote.RemoteProtocol.ActorRefProtocolOrBuilder> supervisorBuilder_; + public boolean hasSupervisor() { + return ((bitField0_ & 0x00000008) == 0x00000008); + } + public akka.remote.RemoteProtocol.ActorRefProtocol getSupervisor() { + if (supervisorBuilder_ == null) { + return supervisor_; + } else { + return supervisorBuilder_.getMessage(); + } + } + public Builder setSupervisor(akka.remote.RemoteProtocol.ActorRefProtocol value) { + if (supervisorBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + supervisor_ = value; + onChanged(); + } else { + supervisorBuilder_.setMessage(value); + } + bitField0_ |= 0x00000008; + return this; + } + public Builder setSupervisor( + akka.remote.RemoteProtocol.ActorRefProtocol.Builder builderForValue) { + if (supervisorBuilder_ == null) { + supervisor_ = builderForValue.build(); + onChanged(); + } else { + supervisorBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000008; + return this; + } + public Builder mergeSupervisor(akka.remote.RemoteProtocol.ActorRefProtocol value) { + if (supervisorBuilder_ == null) { + if (((bitField0_ & 0x00000008) == 0x00000008) && + supervisor_ != akka.remote.RemoteProtocol.ActorRefProtocol.getDefaultInstance()) { + supervisor_ = + akka.remote.RemoteProtocol.ActorRefProtocol.newBuilder(supervisor_).mergeFrom(value).buildPartial(); + } else { + supervisor_ = value; + } + onChanged(); + } else { + supervisorBuilder_.mergeFrom(value); + } + bitField0_ |= 0x00000008; + return this; + } + public Builder clearSupervisor() { + if (supervisorBuilder_ == null) { + supervisor_ = akka.remote.RemoteProtocol.ActorRefProtocol.getDefaultInstance(); + onChanged(); + } else { + supervisorBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000008); + return this; + } + public akka.remote.RemoteProtocol.ActorRefProtocol.Builder getSupervisorBuilder() { + bitField0_ |= 0x00000008; + onChanged(); + return getSupervisorFieldBuilder().getBuilder(); + } + public akka.remote.RemoteProtocol.ActorRefProtocolOrBuilder getSupervisorOrBuilder() { + if (supervisorBuilder_ != null) { + return supervisorBuilder_.getMessageOrBuilder(); + } else { + return supervisor_; + } + } + private com.google.protobuf.SingleFieldBuilder< + akka.remote.RemoteProtocol.ActorRefProtocol, akka.remote.RemoteProtocol.ActorRefProtocol.Builder, akka.remote.RemoteProtocol.ActorRefProtocolOrBuilder> + getSupervisorFieldBuilder() { + if (supervisorBuilder_ == null) { + supervisorBuilder_ = new com.google.protobuf.SingleFieldBuilder< + akka.remote.RemoteProtocol.ActorRefProtocol, akka.remote.RemoteProtocol.ActorRefProtocol.Builder, akka.remote.RemoteProtocol.ActorRefProtocolOrBuilder>( + supervisor_, + getParentForChildren(), + isClean()); + supervisor_ = null; + } + return supervisorBuilder_; + } + + // @@protoc_insertion_point(builder_scope:DaemonMsgCreateProtocol) + } + + static { + defaultInstance = new DaemonMsgCreateProtocol(true); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:DaemonMsgCreateProtocol) + } + + public interface PropsProtocolOrBuilder + extends com.google.protobuf.MessageOrBuilder { + + // required bytes creator = 1; + boolean hasCreator(); + com.google.protobuf.ByteString getCreator(); + + // required string dispatcher = 2; + boolean hasDispatcher(); + String getDispatcher(); + + // required .DeployProtocol deploy = 3; + boolean hasDeploy(); + akka.remote.RemoteProtocol.DeployProtocol getDeploy(); + akka.remote.RemoteProtocol.DeployProtocolOrBuilder getDeployOrBuilder(); + + // optional bytes routerConfig = 4; + boolean hasRouterConfig(); + com.google.protobuf.ByteString getRouterConfig(); + } + public static final class PropsProtocol extends + com.google.protobuf.GeneratedMessage + implements PropsProtocolOrBuilder { + // Use PropsProtocol.newBuilder() to construct. + private PropsProtocol(Builder builder) { + super(builder); + } + private PropsProtocol(boolean noInit) {} + + private static final PropsProtocol defaultInstance; + public static PropsProtocol getDefaultInstance() { + return defaultInstance; + } + + public PropsProtocol getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return akka.remote.RemoteProtocol.internal_static_PropsProtocol_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return akka.remote.RemoteProtocol.internal_static_PropsProtocol_fieldAccessorTable; + } + + private int bitField0_; + // required bytes creator = 1; + public static final int CREATOR_FIELD_NUMBER = 1; + private com.google.protobuf.ByteString creator_; + public boolean hasCreator() { + return ((bitField0_ & 0x00000001) == 0x00000001); + } + public com.google.protobuf.ByteString getCreator() { + return creator_; + } + + // required string dispatcher = 2; + public static final int DISPATCHER_FIELD_NUMBER = 2; + private java.lang.Object dispatcher_; + public boolean hasDispatcher() { + return ((bitField0_ & 0x00000002) == 0x00000002); + } + public String getDispatcher() { + java.lang.Object ref = dispatcher_; + if (ref instanceof String) { + return (String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + if (com.google.protobuf.Internal.isValidUtf8(bs)) { + dispatcher_ = s; + } + return s; + } + } + private com.google.protobuf.ByteString getDispatcherBytes() { + java.lang.Object ref = dispatcher_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8((String) ref); + dispatcher_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + // required .DeployProtocol deploy = 3; + public static final int DEPLOY_FIELD_NUMBER = 3; + private akka.remote.RemoteProtocol.DeployProtocol deploy_; + public boolean hasDeploy() { + return ((bitField0_ & 0x00000004) == 0x00000004); + } + public akka.remote.RemoteProtocol.DeployProtocol getDeploy() { + return deploy_; + } + public akka.remote.RemoteProtocol.DeployProtocolOrBuilder getDeployOrBuilder() { + return deploy_; + } + + // optional bytes routerConfig = 4; + public static final int ROUTERCONFIG_FIELD_NUMBER = 4; + private com.google.protobuf.ByteString routerConfig_; + public boolean hasRouterConfig() { + return ((bitField0_ & 0x00000008) == 0x00000008); + } + public com.google.protobuf.ByteString getRouterConfig() { + return routerConfig_; + } + + private void initFields() { + creator_ = com.google.protobuf.ByteString.EMPTY; + dispatcher_ = ""; + deploy_ = akka.remote.RemoteProtocol.DeployProtocol.getDefaultInstance(); + routerConfig_ = com.google.protobuf.ByteString.EMPTY; + } + private byte memoizedIsInitialized = -1; + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized != -1) return isInitialized == 1; + + if (!hasCreator()) { + memoizedIsInitialized = 0; + return false; + } + if (!hasDispatcher()) { + memoizedIsInitialized = 0; + return false; + } + if (!hasDeploy()) { + memoizedIsInitialized = 0; + return false; + } + if (!getDeploy().isInitialized()) { + memoizedIsInitialized = 0; + return false; + } + memoizedIsInitialized = 1; + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (((bitField0_ & 0x00000001) == 0x00000001)) { + output.writeBytes(1, creator_); + } + if (((bitField0_ & 0x00000002) == 0x00000002)) { + output.writeBytes(2, getDispatcherBytes()); + } + if (((bitField0_ & 0x00000004) == 0x00000004)) { + output.writeMessage(3, deploy_); + } + if (((bitField0_ & 0x00000008) == 0x00000008)) { + output.writeBytes(4, routerConfig_); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (((bitField0_ & 0x00000001) == 0x00000001)) { + size += com.google.protobuf.CodedOutputStream + .computeBytesSize(1, creator_); + } + if (((bitField0_ & 0x00000002) == 0x00000002)) { + size += com.google.protobuf.CodedOutputStream + .computeBytesSize(2, getDispatcherBytes()); + } + if (((bitField0_ & 0x00000004) == 0x00000004)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(3, deploy_); + } + if (((bitField0_ & 0x00000008) == 0x00000008)) { + size += com.google.protobuf.CodedOutputStream + .computeBytesSize(4, routerConfig_); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + private static final long serialVersionUID = 0L; + @java.lang.Override + protected java.lang.Object writeReplace() + throws java.io.ObjectStreamException { + return super.writeReplace(); + } + + public static akka.remote.RemoteProtocol.PropsProtocol parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static akka.remote.RemoteProtocol.PropsProtocol parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static akka.remote.RemoteProtocol.PropsProtocol parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static akka.remote.RemoteProtocol.PropsProtocol parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static akka.remote.RemoteProtocol.PropsProtocol parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static akka.remote.RemoteProtocol.PropsProtocol parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static akka.remote.RemoteProtocol.PropsProtocol parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static akka.remote.RemoteProtocol.PropsProtocol parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static akka.remote.RemoteProtocol.PropsProtocol parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static akka.remote.RemoteProtocol.PropsProtocol parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(akka.remote.RemoteProtocol.PropsProtocol prototype) { + return newBuilder().mergeFrom(prototype); + } + public Builder toBuilder() { return newBuilder(this); } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder + implements akka.remote.RemoteProtocol.PropsProtocolOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return akka.remote.RemoteProtocol.internal_static_PropsProtocol_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return akka.remote.RemoteProtocol.internal_static_PropsProtocol_fieldAccessorTable; + } + + // Construct using akka.remote.RemoteProtocol.PropsProtocol.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder(BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { + getDeployFieldBuilder(); + } + } + private static Builder create() { + return new Builder(); + } + + public Builder clear() { + super.clear(); + creator_ = com.google.protobuf.ByteString.EMPTY; + bitField0_ = (bitField0_ & ~0x00000001); + dispatcher_ = ""; + bitField0_ = (bitField0_ & ~0x00000002); + if (deployBuilder_ == null) { + deploy_ = akka.remote.RemoteProtocol.DeployProtocol.getDefaultInstance(); + } else { + deployBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000004); + routerConfig_ = com.google.protobuf.ByteString.EMPTY; + bitField0_ = (bitField0_ & ~0x00000008); + return this; + } + + public Builder clone() { + return create().mergeFrom(buildPartial()); + } + + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return akka.remote.RemoteProtocol.PropsProtocol.getDescriptor(); + } + + public akka.remote.RemoteProtocol.PropsProtocol getDefaultInstanceForType() { + return akka.remote.RemoteProtocol.PropsProtocol.getDefaultInstance(); + } + + public akka.remote.RemoteProtocol.PropsProtocol build() { + akka.remote.RemoteProtocol.PropsProtocol result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + private akka.remote.RemoteProtocol.PropsProtocol buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + akka.remote.RemoteProtocol.PropsProtocol result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return result; + } + + public akka.remote.RemoteProtocol.PropsProtocol buildPartial() { + akka.remote.RemoteProtocol.PropsProtocol result = new akka.remote.RemoteProtocol.PropsProtocol(this); + int from_bitField0_ = bitField0_; + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000001) == 0x00000001)) { + to_bitField0_ |= 0x00000001; + } + result.creator_ = creator_; + if (((from_bitField0_ & 0x00000002) == 0x00000002)) { + to_bitField0_ |= 0x00000002; + } + result.dispatcher_ = dispatcher_; + if (((from_bitField0_ & 0x00000004) == 0x00000004)) { + to_bitField0_ |= 0x00000004; + } + if (deployBuilder_ == null) { + result.deploy_ = deploy_; + } else { + result.deploy_ = deployBuilder_.build(); + } + if (((from_bitField0_ & 0x00000008) == 0x00000008)) { + to_bitField0_ |= 0x00000008; + } + result.routerConfig_ = routerConfig_; + result.bitField0_ = to_bitField0_; + onBuilt(); + return result; + } + + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof akka.remote.RemoteProtocol.PropsProtocol) { + return mergeFrom((akka.remote.RemoteProtocol.PropsProtocol)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(akka.remote.RemoteProtocol.PropsProtocol other) { + if (other == akka.remote.RemoteProtocol.PropsProtocol.getDefaultInstance()) return this; + if (other.hasCreator()) { + setCreator(other.getCreator()); + } + if (other.hasDispatcher()) { + setDispatcher(other.getDispatcher()); + } + if (other.hasDeploy()) { + mergeDeploy(other.getDeploy()); + } + if (other.hasRouterConfig()) { + setRouterConfig(other.getRouterConfig()); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + public final boolean isInitialized() { + if (!hasCreator()) { + + return false; + } + if (!hasDispatcher()) { + + return false; + } + if (!hasDeploy()) { + + return false; + } + if (!getDeploy().isInitialized()) { + + return false; + } + return true; + } + + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + onChanged(); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + onChanged(); + return this; + } + break; + } + case 10: { + bitField0_ |= 0x00000001; + creator_ = input.readBytes(); + break; + } + case 18: { + bitField0_ |= 0x00000002; + dispatcher_ = input.readBytes(); + break; + } + case 26: { + akka.remote.RemoteProtocol.DeployProtocol.Builder subBuilder = akka.remote.RemoteProtocol.DeployProtocol.newBuilder(); + if (hasDeploy()) { + subBuilder.mergeFrom(getDeploy()); + } + input.readMessage(subBuilder, extensionRegistry); + setDeploy(subBuilder.buildPartial()); + break; + } + case 34: { + bitField0_ |= 0x00000008; + routerConfig_ = input.readBytes(); + break; + } + } + } + } + + private int bitField0_; + + // required bytes creator = 1; + private com.google.protobuf.ByteString creator_ = com.google.protobuf.ByteString.EMPTY; + public boolean hasCreator() { + return ((bitField0_ & 0x00000001) == 0x00000001); + } + public com.google.protobuf.ByteString getCreator() { + return creator_; + } + public Builder setCreator(com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000001; + creator_ = value; + onChanged(); + return this; + } + public Builder clearCreator() { + bitField0_ = (bitField0_ & ~0x00000001); + creator_ = getDefaultInstance().getCreator(); + onChanged(); + return this; + } + + // required string dispatcher = 2; + private java.lang.Object dispatcher_ = ""; + public boolean hasDispatcher() { + return ((bitField0_ & 0x00000002) == 0x00000002); + } + public String getDispatcher() { + java.lang.Object ref = dispatcher_; + if (!(ref instanceof String)) { + String s = ((com.google.protobuf.ByteString) ref).toStringUtf8(); + dispatcher_ = s; + return s; + } else { + return (String) ref; + } + } + public Builder setDispatcher(String value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000002; + dispatcher_ = value; + onChanged(); + return this; + } + public Builder clearDispatcher() { + bitField0_ = (bitField0_ & ~0x00000002); + dispatcher_ = getDefaultInstance().getDispatcher(); + onChanged(); + return this; + } + void setDispatcher(com.google.protobuf.ByteString value) { + bitField0_ |= 0x00000002; + dispatcher_ = value; + onChanged(); + } + + // required .DeployProtocol deploy = 3; + private akka.remote.RemoteProtocol.DeployProtocol deploy_ = akka.remote.RemoteProtocol.DeployProtocol.getDefaultInstance(); + private com.google.protobuf.SingleFieldBuilder< + akka.remote.RemoteProtocol.DeployProtocol, akka.remote.RemoteProtocol.DeployProtocol.Builder, akka.remote.RemoteProtocol.DeployProtocolOrBuilder> deployBuilder_; + public boolean hasDeploy() { + return ((bitField0_ & 0x00000004) == 0x00000004); + } + public akka.remote.RemoteProtocol.DeployProtocol getDeploy() { + if (deployBuilder_ == null) { + return deploy_; + } else { + return deployBuilder_.getMessage(); + } + } + public Builder setDeploy(akka.remote.RemoteProtocol.DeployProtocol value) { + if (deployBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + deploy_ = value; + onChanged(); + } else { + deployBuilder_.setMessage(value); + } + bitField0_ |= 0x00000004; + return this; + } + public Builder setDeploy( + akka.remote.RemoteProtocol.DeployProtocol.Builder builderForValue) { + if (deployBuilder_ == null) { + deploy_ = builderForValue.build(); + onChanged(); + } else { + deployBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000004; + return this; + } + public Builder mergeDeploy(akka.remote.RemoteProtocol.DeployProtocol value) { + if (deployBuilder_ == null) { + if (((bitField0_ & 0x00000004) == 0x00000004) && + deploy_ != akka.remote.RemoteProtocol.DeployProtocol.getDefaultInstance()) { + deploy_ = + akka.remote.RemoteProtocol.DeployProtocol.newBuilder(deploy_).mergeFrom(value).buildPartial(); + } else { + deploy_ = value; + } + onChanged(); + } else { + deployBuilder_.mergeFrom(value); + } + bitField0_ |= 0x00000004; + return this; + } + public Builder clearDeploy() { + if (deployBuilder_ == null) { + deploy_ = akka.remote.RemoteProtocol.DeployProtocol.getDefaultInstance(); + onChanged(); + } else { + deployBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000004); + return this; + } + public akka.remote.RemoteProtocol.DeployProtocol.Builder getDeployBuilder() { + bitField0_ |= 0x00000004; + onChanged(); + return getDeployFieldBuilder().getBuilder(); + } + public akka.remote.RemoteProtocol.DeployProtocolOrBuilder getDeployOrBuilder() { + if (deployBuilder_ != null) { + return deployBuilder_.getMessageOrBuilder(); + } else { + return deploy_; + } + } + private com.google.protobuf.SingleFieldBuilder< + akka.remote.RemoteProtocol.DeployProtocol, akka.remote.RemoteProtocol.DeployProtocol.Builder, akka.remote.RemoteProtocol.DeployProtocolOrBuilder> + getDeployFieldBuilder() { + if (deployBuilder_ == null) { + deployBuilder_ = new com.google.protobuf.SingleFieldBuilder< + akka.remote.RemoteProtocol.DeployProtocol, akka.remote.RemoteProtocol.DeployProtocol.Builder, akka.remote.RemoteProtocol.DeployProtocolOrBuilder>( + deploy_, + getParentForChildren(), + isClean()); + deploy_ = null; + } + return deployBuilder_; + } + + // optional bytes routerConfig = 4; + private com.google.protobuf.ByteString routerConfig_ = com.google.protobuf.ByteString.EMPTY; + public boolean hasRouterConfig() { + return ((bitField0_ & 0x00000008) == 0x00000008); + } + public com.google.protobuf.ByteString getRouterConfig() { + return routerConfig_; + } + public Builder setRouterConfig(com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000008; + routerConfig_ = value; + onChanged(); + return this; + } + public Builder clearRouterConfig() { + bitField0_ = (bitField0_ & ~0x00000008); + routerConfig_ = getDefaultInstance().getRouterConfig(); + onChanged(); + return this; + } + + // @@protoc_insertion_point(builder_scope:PropsProtocol) + } + + static { + defaultInstance = new PropsProtocol(true); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:PropsProtocol) + } + + public interface DeployProtocolOrBuilder + extends com.google.protobuf.MessageOrBuilder { + + // required string path = 1; + boolean hasPath(); + String getPath(); + + // optional bytes config = 2; + boolean hasConfig(); + com.google.protobuf.ByteString getConfig(); + + // optional bytes routerConfig = 3; + boolean hasRouterConfig(); + com.google.protobuf.ByteString getRouterConfig(); + + // optional bytes scope = 4; + boolean hasScope(); + com.google.protobuf.ByteString getScope(); + } + public static final class DeployProtocol extends + com.google.protobuf.GeneratedMessage + implements DeployProtocolOrBuilder { + // Use DeployProtocol.newBuilder() to construct. + private DeployProtocol(Builder builder) { + super(builder); + } + private DeployProtocol(boolean noInit) {} + + private static final DeployProtocol defaultInstance; + public static DeployProtocol getDefaultInstance() { + return defaultInstance; + } + + public DeployProtocol getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return akka.remote.RemoteProtocol.internal_static_DeployProtocol_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return akka.remote.RemoteProtocol.internal_static_DeployProtocol_fieldAccessorTable; + } + + private int bitField0_; + // required string path = 1; + public static final int PATH_FIELD_NUMBER = 1; + private java.lang.Object path_; + public boolean hasPath() { + return ((bitField0_ & 0x00000001) == 0x00000001); + } + public String getPath() { + java.lang.Object ref = path_; + if (ref instanceof String) { + return (String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + if (com.google.protobuf.Internal.isValidUtf8(bs)) { + path_ = s; + } + return s; + } + } + private com.google.protobuf.ByteString getPathBytes() { + java.lang.Object ref = path_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8((String) ref); + path_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + // optional bytes config = 2; + public static final int CONFIG_FIELD_NUMBER = 2; + private com.google.protobuf.ByteString config_; + public boolean hasConfig() { + return ((bitField0_ & 0x00000002) == 0x00000002); + } + public com.google.protobuf.ByteString getConfig() { + return config_; + } + + // optional bytes routerConfig = 3; + public static final int ROUTERCONFIG_FIELD_NUMBER = 3; + private com.google.protobuf.ByteString routerConfig_; + public boolean hasRouterConfig() { + return ((bitField0_ & 0x00000004) == 0x00000004); + } + public com.google.protobuf.ByteString getRouterConfig() { + return routerConfig_; + } + + // optional bytes scope = 4; + public static final int SCOPE_FIELD_NUMBER = 4; + private com.google.protobuf.ByteString scope_; + public boolean hasScope() { + return ((bitField0_ & 0x00000008) == 0x00000008); + } + public com.google.protobuf.ByteString getScope() { + return scope_; + } + + private void initFields() { + path_ = ""; + config_ = com.google.protobuf.ByteString.EMPTY; + routerConfig_ = com.google.protobuf.ByteString.EMPTY; + scope_ = com.google.protobuf.ByteString.EMPTY; + } + private byte memoizedIsInitialized = -1; + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized != -1) return isInitialized == 1; + + if (!hasPath()) { + memoizedIsInitialized = 0; + return false; + } + memoizedIsInitialized = 1; + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (((bitField0_ & 0x00000001) == 0x00000001)) { + output.writeBytes(1, getPathBytes()); + } + if (((bitField0_ & 0x00000002) == 0x00000002)) { + output.writeBytes(2, config_); + } + if (((bitField0_ & 0x00000004) == 0x00000004)) { + output.writeBytes(3, routerConfig_); + } + if (((bitField0_ & 0x00000008) == 0x00000008)) { + output.writeBytes(4, scope_); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (((bitField0_ & 0x00000001) == 0x00000001)) { + size += com.google.protobuf.CodedOutputStream + .computeBytesSize(1, getPathBytes()); + } + if (((bitField0_ & 0x00000002) == 0x00000002)) { + size += com.google.protobuf.CodedOutputStream + .computeBytesSize(2, config_); + } + if (((bitField0_ & 0x00000004) == 0x00000004)) { + size += com.google.protobuf.CodedOutputStream + .computeBytesSize(3, routerConfig_); + } + if (((bitField0_ & 0x00000008) == 0x00000008)) { + size += com.google.protobuf.CodedOutputStream + .computeBytesSize(4, scope_); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + private static final long serialVersionUID = 0L; + @java.lang.Override + protected java.lang.Object writeReplace() + throws java.io.ObjectStreamException { + return super.writeReplace(); + } + + public static akka.remote.RemoteProtocol.DeployProtocol parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static akka.remote.RemoteProtocol.DeployProtocol parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static akka.remote.RemoteProtocol.DeployProtocol parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static akka.remote.RemoteProtocol.DeployProtocol parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static akka.remote.RemoteProtocol.DeployProtocol parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static akka.remote.RemoteProtocol.DeployProtocol parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static akka.remote.RemoteProtocol.DeployProtocol parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static akka.remote.RemoteProtocol.DeployProtocol parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static akka.remote.RemoteProtocol.DeployProtocol parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static akka.remote.RemoteProtocol.DeployProtocol parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(akka.remote.RemoteProtocol.DeployProtocol prototype) { + return newBuilder().mergeFrom(prototype); + } + public Builder toBuilder() { return newBuilder(this); } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder + implements akka.remote.RemoteProtocol.DeployProtocolOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return akka.remote.RemoteProtocol.internal_static_DeployProtocol_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return akka.remote.RemoteProtocol.internal_static_DeployProtocol_fieldAccessorTable; + } + + // Construct using akka.remote.RemoteProtocol.DeployProtocol.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder(BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { + } + } + private static Builder create() { + return new Builder(); + } + + public Builder clear() { + super.clear(); + path_ = ""; + bitField0_ = (bitField0_ & ~0x00000001); + config_ = com.google.protobuf.ByteString.EMPTY; + bitField0_ = (bitField0_ & ~0x00000002); + routerConfig_ = com.google.protobuf.ByteString.EMPTY; + bitField0_ = (bitField0_ & ~0x00000004); + scope_ = com.google.protobuf.ByteString.EMPTY; + bitField0_ = (bitField0_ & ~0x00000008); + return this; + } + + public Builder clone() { + return create().mergeFrom(buildPartial()); + } + + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return akka.remote.RemoteProtocol.DeployProtocol.getDescriptor(); + } + + public akka.remote.RemoteProtocol.DeployProtocol getDefaultInstanceForType() { + return akka.remote.RemoteProtocol.DeployProtocol.getDefaultInstance(); + } + + public akka.remote.RemoteProtocol.DeployProtocol build() { + akka.remote.RemoteProtocol.DeployProtocol result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + private akka.remote.RemoteProtocol.DeployProtocol buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + akka.remote.RemoteProtocol.DeployProtocol result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return result; + } + + public akka.remote.RemoteProtocol.DeployProtocol buildPartial() { + akka.remote.RemoteProtocol.DeployProtocol result = new akka.remote.RemoteProtocol.DeployProtocol(this); + int from_bitField0_ = bitField0_; + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000001) == 0x00000001)) { + to_bitField0_ |= 0x00000001; + } + result.path_ = path_; + if (((from_bitField0_ & 0x00000002) == 0x00000002)) { + to_bitField0_ |= 0x00000002; + } + result.config_ = config_; + if (((from_bitField0_ & 0x00000004) == 0x00000004)) { + to_bitField0_ |= 0x00000004; + } + result.routerConfig_ = routerConfig_; + if (((from_bitField0_ & 0x00000008) == 0x00000008)) { + to_bitField0_ |= 0x00000008; + } + result.scope_ = scope_; + result.bitField0_ = to_bitField0_; + onBuilt(); + return result; + } + + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof akka.remote.RemoteProtocol.DeployProtocol) { + return mergeFrom((akka.remote.RemoteProtocol.DeployProtocol)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(akka.remote.RemoteProtocol.DeployProtocol other) { + if (other == akka.remote.RemoteProtocol.DeployProtocol.getDefaultInstance()) return this; + if (other.hasPath()) { + setPath(other.getPath()); + } + if (other.hasConfig()) { + setConfig(other.getConfig()); + } + if (other.hasRouterConfig()) { + setRouterConfig(other.getRouterConfig()); + } + if (other.hasScope()) { + setScope(other.getScope()); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + public final boolean isInitialized() { + if (!hasPath()) { + + return false; + } + return true; + } + + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + onChanged(); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + onChanged(); + return this; + } + break; + } + case 10: { + bitField0_ |= 0x00000001; + path_ = input.readBytes(); + break; + } + case 18: { + bitField0_ |= 0x00000002; + config_ = input.readBytes(); + break; + } + case 26: { + bitField0_ |= 0x00000004; + routerConfig_ = input.readBytes(); + break; + } + case 34: { + bitField0_ |= 0x00000008; + scope_ = input.readBytes(); + break; + } + } + } + } + + private int bitField0_; + + // required string path = 1; + private java.lang.Object path_ = ""; + public boolean hasPath() { + return ((bitField0_ & 0x00000001) == 0x00000001); + } + public String getPath() { + java.lang.Object ref = path_; + if (!(ref instanceof String)) { + String s = ((com.google.protobuf.ByteString) ref).toStringUtf8(); + path_ = s; + return s; + } else { + return (String) ref; + } + } + public Builder setPath(String value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000001; + path_ = value; + onChanged(); + return this; + } + public Builder clearPath() { + bitField0_ = (bitField0_ & ~0x00000001); + path_ = getDefaultInstance().getPath(); + onChanged(); + return this; + } + void setPath(com.google.protobuf.ByteString value) { + bitField0_ |= 0x00000001; + path_ = value; + onChanged(); + } + + // optional bytes config = 2; + private com.google.protobuf.ByteString config_ = com.google.protobuf.ByteString.EMPTY; + public boolean hasConfig() { + return ((bitField0_ & 0x00000002) == 0x00000002); + } + public com.google.protobuf.ByteString getConfig() { + return config_; + } + public Builder setConfig(com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000002; + config_ = value; + onChanged(); + return this; + } + public Builder clearConfig() { + bitField0_ = (bitField0_ & ~0x00000002); + config_ = getDefaultInstance().getConfig(); + onChanged(); + return this; + } + + // optional bytes routerConfig = 3; + private com.google.protobuf.ByteString routerConfig_ = com.google.protobuf.ByteString.EMPTY; + public boolean hasRouterConfig() { + return ((bitField0_ & 0x00000004) == 0x00000004); + } + public com.google.protobuf.ByteString getRouterConfig() { + return routerConfig_; + } + public Builder setRouterConfig(com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000004; + routerConfig_ = value; + onChanged(); + return this; + } + public Builder clearRouterConfig() { + bitField0_ = (bitField0_ & ~0x00000004); + routerConfig_ = getDefaultInstance().getRouterConfig(); + onChanged(); + return this; + } + + // optional bytes scope = 4; + private com.google.protobuf.ByteString scope_ = com.google.protobuf.ByteString.EMPTY; + public boolean hasScope() { + return ((bitField0_ & 0x00000008) == 0x00000008); + } + public com.google.protobuf.ByteString getScope() { + return scope_; + } + public Builder setScope(com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000008; + scope_ = value; + onChanged(); + return this; + } + public Builder clearScope() { + bitField0_ = (bitField0_ & ~0x00000008); + scope_ = getDefaultInstance().getScope(); + onChanged(); + return this; + } + + // @@protoc_insertion_point(builder_scope:DeployProtocol) + } + + static { + defaultInstance = new DeployProtocol(true); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:DeployProtocol) + } + + public interface DaemonMsgWatchProtocolOrBuilder + extends com.google.protobuf.MessageOrBuilder { + + // required .ActorRefProtocol watcher = 1; + boolean hasWatcher(); + akka.remote.RemoteProtocol.ActorRefProtocol getWatcher(); + akka.remote.RemoteProtocol.ActorRefProtocolOrBuilder getWatcherOrBuilder(); + + // required .ActorRefProtocol watched = 2; + boolean hasWatched(); + akka.remote.RemoteProtocol.ActorRefProtocol getWatched(); + akka.remote.RemoteProtocol.ActorRefProtocolOrBuilder getWatchedOrBuilder(); + } + public static final class DaemonMsgWatchProtocol extends + com.google.protobuf.GeneratedMessage + implements DaemonMsgWatchProtocolOrBuilder { + // Use DaemonMsgWatchProtocol.newBuilder() to construct. + private DaemonMsgWatchProtocol(Builder builder) { + super(builder); + } + private DaemonMsgWatchProtocol(boolean noInit) {} + + private static final DaemonMsgWatchProtocol defaultInstance; + public static DaemonMsgWatchProtocol getDefaultInstance() { + return defaultInstance; + } + + public DaemonMsgWatchProtocol getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return akka.remote.RemoteProtocol.internal_static_DaemonMsgWatchProtocol_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return akka.remote.RemoteProtocol.internal_static_DaemonMsgWatchProtocol_fieldAccessorTable; + } + + private int bitField0_; + // required .ActorRefProtocol watcher = 1; + public static final int WATCHER_FIELD_NUMBER = 1; + private akka.remote.RemoteProtocol.ActorRefProtocol watcher_; + public boolean hasWatcher() { + return ((bitField0_ & 0x00000001) == 0x00000001); + } + public akka.remote.RemoteProtocol.ActorRefProtocol getWatcher() { + return watcher_; + } + public akka.remote.RemoteProtocol.ActorRefProtocolOrBuilder getWatcherOrBuilder() { + return watcher_; + } + + // required .ActorRefProtocol watched = 2; + public static final int WATCHED_FIELD_NUMBER = 2; + private akka.remote.RemoteProtocol.ActorRefProtocol watched_; + public boolean hasWatched() { + return ((bitField0_ & 0x00000002) == 0x00000002); + } + public akka.remote.RemoteProtocol.ActorRefProtocol getWatched() { + return watched_; + } + public akka.remote.RemoteProtocol.ActorRefProtocolOrBuilder getWatchedOrBuilder() { + return watched_; + } + + private void initFields() { + watcher_ = akka.remote.RemoteProtocol.ActorRefProtocol.getDefaultInstance(); + watched_ = akka.remote.RemoteProtocol.ActorRefProtocol.getDefaultInstance(); + } + private byte memoizedIsInitialized = -1; + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized != -1) return isInitialized == 1; + + if (!hasWatcher()) { + memoizedIsInitialized = 0; + return false; + } + if (!hasWatched()) { + memoizedIsInitialized = 0; + return false; + } + if (!getWatcher().isInitialized()) { + memoizedIsInitialized = 0; + return false; + } + if (!getWatched().isInitialized()) { + memoizedIsInitialized = 0; + return false; + } + memoizedIsInitialized = 1; + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (((bitField0_ & 0x00000001) == 0x00000001)) { + output.writeMessage(1, watcher_); + } + if (((bitField0_ & 0x00000002) == 0x00000002)) { + output.writeMessage(2, watched_); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (((bitField0_ & 0x00000001) == 0x00000001)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(1, watcher_); + } + if (((bitField0_ & 0x00000002) == 0x00000002)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(2, watched_); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + private static final long serialVersionUID = 0L; + @java.lang.Override + protected java.lang.Object writeReplace() + throws java.io.ObjectStreamException { + return super.writeReplace(); + } + + public static akka.remote.RemoteProtocol.DaemonMsgWatchProtocol parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static akka.remote.RemoteProtocol.DaemonMsgWatchProtocol parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static akka.remote.RemoteProtocol.DaemonMsgWatchProtocol parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static akka.remote.RemoteProtocol.DaemonMsgWatchProtocol parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static akka.remote.RemoteProtocol.DaemonMsgWatchProtocol parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static akka.remote.RemoteProtocol.DaemonMsgWatchProtocol parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static akka.remote.RemoteProtocol.DaemonMsgWatchProtocol parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static akka.remote.RemoteProtocol.DaemonMsgWatchProtocol parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static akka.remote.RemoteProtocol.DaemonMsgWatchProtocol parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static akka.remote.RemoteProtocol.DaemonMsgWatchProtocol parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(akka.remote.RemoteProtocol.DaemonMsgWatchProtocol prototype) { + return newBuilder().mergeFrom(prototype); + } + public Builder toBuilder() { return newBuilder(this); } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder + implements akka.remote.RemoteProtocol.DaemonMsgWatchProtocolOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return akka.remote.RemoteProtocol.internal_static_DaemonMsgWatchProtocol_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return akka.remote.RemoteProtocol.internal_static_DaemonMsgWatchProtocol_fieldAccessorTable; + } + + // Construct using akka.remote.RemoteProtocol.DaemonMsgWatchProtocol.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder(BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { + getWatcherFieldBuilder(); + getWatchedFieldBuilder(); + } + } + private static Builder create() { + return new Builder(); + } + + public Builder clear() { + super.clear(); + if (watcherBuilder_ == null) { + watcher_ = akka.remote.RemoteProtocol.ActorRefProtocol.getDefaultInstance(); + } else { + watcherBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000001); + if (watchedBuilder_ == null) { + watched_ = akka.remote.RemoteProtocol.ActorRefProtocol.getDefaultInstance(); + } else { + watchedBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000002); + return this; + } + + public Builder clone() { + return create().mergeFrom(buildPartial()); + } + + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return akka.remote.RemoteProtocol.DaemonMsgWatchProtocol.getDescriptor(); + } + + public akka.remote.RemoteProtocol.DaemonMsgWatchProtocol getDefaultInstanceForType() { + return akka.remote.RemoteProtocol.DaemonMsgWatchProtocol.getDefaultInstance(); + } + + public akka.remote.RemoteProtocol.DaemonMsgWatchProtocol build() { + akka.remote.RemoteProtocol.DaemonMsgWatchProtocol result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + private akka.remote.RemoteProtocol.DaemonMsgWatchProtocol buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + akka.remote.RemoteProtocol.DaemonMsgWatchProtocol result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return result; + } + + public akka.remote.RemoteProtocol.DaemonMsgWatchProtocol buildPartial() { + akka.remote.RemoteProtocol.DaemonMsgWatchProtocol result = new akka.remote.RemoteProtocol.DaemonMsgWatchProtocol(this); + int from_bitField0_ = bitField0_; + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000001) == 0x00000001)) { + to_bitField0_ |= 0x00000001; + } + if (watcherBuilder_ == null) { + result.watcher_ = watcher_; + } else { + result.watcher_ = watcherBuilder_.build(); + } + if (((from_bitField0_ & 0x00000002) == 0x00000002)) { + to_bitField0_ |= 0x00000002; + } + if (watchedBuilder_ == null) { + result.watched_ = watched_; + } else { + result.watched_ = watchedBuilder_.build(); + } + result.bitField0_ = to_bitField0_; + onBuilt(); + return result; + } + + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof akka.remote.RemoteProtocol.DaemonMsgWatchProtocol) { + return mergeFrom((akka.remote.RemoteProtocol.DaemonMsgWatchProtocol)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(akka.remote.RemoteProtocol.DaemonMsgWatchProtocol other) { + if (other == akka.remote.RemoteProtocol.DaemonMsgWatchProtocol.getDefaultInstance()) return this; + if (other.hasWatcher()) { + mergeWatcher(other.getWatcher()); + } + if (other.hasWatched()) { + mergeWatched(other.getWatched()); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + public final boolean isInitialized() { + if (!hasWatcher()) { + + return false; + } + if (!hasWatched()) { + + return false; + } + if (!getWatcher().isInitialized()) { + + return false; + } + if (!getWatched().isInitialized()) { + + return false; + } return true; } @@ -4593,25 +6651,20 @@ public final class RemoteProtocol { } case 10: { akka.remote.RemoteProtocol.ActorRefProtocol.Builder subBuilder = akka.remote.RemoteProtocol.ActorRefProtocol.newBuilder(); - if (hasRecipient()) { - subBuilder.mergeFrom(getRecipient()); + if (hasWatcher()) { + subBuilder.mergeFrom(getWatcher()); } input.readMessage(subBuilder, extensionRegistry); - setRecipient(subBuilder.buildPartial()); + setWatcher(subBuilder.buildPartial()); break; } case 18: { akka.remote.RemoteProtocol.ActorRefProtocol.Builder subBuilder = akka.remote.RemoteProtocol.ActorRefProtocol.newBuilder(); - if (hasSender()) { - subBuilder.mergeFrom(getSender()); + if (hasWatched()) { + subBuilder.mergeFrom(getWatched()); } input.readMessage(subBuilder, extensionRegistry); - setSender(subBuilder.buildPartial()); - break; - } - case 26: { - bitField0_ |= 0x00000004; - message_ = input.readBytes(); + setWatched(subBuilder.buildPartial()); break; } } @@ -4620,219 +6673,195 @@ public final class RemoteProtocol { private int bitField0_; - // required .ActorRefProtocol recipient = 1; - private akka.remote.RemoteProtocol.ActorRefProtocol recipient_ = akka.remote.RemoteProtocol.ActorRefProtocol.getDefaultInstance(); + // required .ActorRefProtocol watcher = 1; + private akka.remote.RemoteProtocol.ActorRefProtocol watcher_ = akka.remote.RemoteProtocol.ActorRefProtocol.getDefaultInstance(); private com.google.protobuf.SingleFieldBuilder< - akka.remote.RemoteProtocol.ActorRefProtocol, akka.remote.RemoteProtocol.ActorRefProtocol.Builder, akka.remote.RemoteProtocol.ActorRefProtocolOrBuilder> recipientBuilder_; - public boolean hasRecipient() { + akka.remote.RemoteProtocol.ActorRefProtocol, akka.remote.RemoteProtocol.ActorRefProtocol.Builder, akka.remote.RemoteProtocol.ActorRefProtocolOrBuilder> watcherBuilder_; + public boolean hasWatcher() { return ((bitField0_ & 0x00000001) == 0x00000001); } - public akka.remote.RemoteProtocol.ActorRefProtocol getRecipient() { - if (recipientBuilder_ == null) { - return recipient_; + public akka.remote.RemoteProtocol.ActorRefProtocol getWatcher() { + if (watcherBuilder_ == null) { + return watcher_; } else { - return recipientBuilder_.getMessage(); + return watcherBuilder_.getMessage(); } } - public Builder setRecipient(akka.remote.RemoteProtocol.ActorRefProtocol value) { - if (recipientBuilder_ == null) { + public Builder setWatcher(akka.remote.RemoteProtocol.ActorRefProtocol value) { + if (watcherBuilder_ == null) { if (value == null) { throw new NullPointerException(); } - recipient_ = value; + watcher_ = value; onChanged(); } else { - recipientBuilder_.setMessage(value); + watcherBuilder_.setMessage(value); } bitField0_ |= 0x00000001; return this; } - public Builder setRecipient( + public Builder setWatcher( akka.remote.RemoteProtocol.ActorRefProtocol.Builder builderForValue) { - if (recipientBuilder_ == null) { - recipient_ = builderForValue.build(); + if (watcherBuilder_ == null) { + watcher_ = builderForValue.build(); onChanged(); } else { - recipientBuilder_.setMessage(builderForValue.build()); + watcherBuilder_.setMessage(builderForValue.build()); } bitField0_ |= 0x00000001; return this; } - public Builder mergeRecipient(akka.remote.RemoteProtocol.ActorRefProtocol value) { - if (recipientBuilder_ == null) { + public Builder mergeWatcher(akka.remote.RemoteProtocol.ActorRefProtocol value) { + if (watcherBuilder_ == null) { if (((bitField0_ & 0x00000001) == 0x00000001) && - recipient_ != akka.remote.RemoteProtocol.ActorRefProtocol.getDefaultInstance()) { - recipient_ = - akka.remote.RemoteProtocol.ActorRefProtocol.newBuilder(recipient_).mergeFrom(value).buildPartial(); + watcher_ != akka.remote.RemoteProtocol.ActorRefProtocol.getDefaultInstance()) { + watcher_ = + akka.remote.RemoteProtocol.ActorRefProtocol.newBuilder(watcher_).mergeFrom(value).buildPartial(); } else { - recipient_ = value; + watcher_ = value; } onChanged(); } else { - recipientBuilder_.mergeFrom(value); + watcherBuilder_.mergeFrom(value); } bitField0_ |= 0x00000001; return this; } - public Builder clearRecipient() { - if (recipientBuilder_ == null) { - recipient_ = akka.remote.RemoteProtocol.ActorRefProtocol.getDefaultInstance(); + public Builder clearWatcher() { + if (watcherBuilder_ == null) { + watcher_ = akka.remote.RemoteProtocol.ActorRefProtocol.getDefaultInstance(); onChanged(); } else { - recipientBuilder_.clear(); + watcherBuilder_.clear(); } bitField0_ = (bitField0_ & ~0x00000001); return this; } - public akka.remote.RemoteProtocol.ActorRefProtocol.Builder getRecipientBuilder() { + public akka.remote.RemoteProtocol.ActorRefProtocol.Builder getWatcherBuilder() { bitField0_ |= 0x00000001; onChanged(); - return getRecipientFieldBuilder().getBuilder(); + return getWatcherFieldBuilder().getBuilder(); } - public akka.remote.RemoteProtocol.ActorRefProtocolOrBuilder getRecipientOrBuilder() { - if (recipientBuilder_ != null) { - return recipientBuilder_.getMessageOrBuilder(); + public akka.remote.RemoteProtocol.ActorRefProtocolOrBuilder getWatcherOrBuilder() { + if (watcherBuilder_ != null) { + return watcherBuilder_.getMessageOrBuilder(); } else { - return recipient_; + return watcher_; } } private com.google.protobuf.SingleFieldBuilder< akka.remote.RemoteProtocol.ActorRefProtocol, akka.remote.RemoteProtocol.ActorRefProtocol.Builder, akka.remote.RemoteProtocol.ActorRefProtocolOrBuilder> - getRecipientFieldBuilder() { - if (recipientBuilder_ == null) { - recipientBuilder_ = new com.google.protobuf.SingleFieldBuilder< + getWatcherFieldBuilder() { + if (watcherBuilder_ == null) { + watcherBuilder_ = new com.google.protobuf.SingleFieldBuilder< akka.remote.RemoteProtocol.ActorRefProtocol, akka.remote.RemoteProtocol.ActorRefProtocol.Builder, akka.remote.RemoteProtocol.ActorRefProtocolOrBuilder>( - recipient_, + watcher_, getParentForChildren(), isClean()); - recipient_ = null; + watcher_ = null; } - return recipientBuilder_; + return watcherBuilder_; } - // optional .ActorRefProtocol sender = 2; - private akka.remote.RemoteProtocol.ActorRefProtocol sender_ = akka.remote.RemoteProtocol.ActorRefProtocol.getDefaultInstance(); + // required .ActorRefProtocol watched = 2; + private akka.remote.RemoteProtocol.ActorRefProtocol watched_ = akka.remote.RemoteProtocol.ActorRefProtocol.getDefaultInstance(); private com.google.protobuf.SingleFieldBuilder< - akka.remote.RemoteProtocol.ActorRefProtocol, akka.remote.RemoteProtocol.ActorRefProtocol.Builder, akka.remote.RemoteProtocol.ActorRefProtocolOrBuilder> senderBuilder_; - public boolean hasSender() { + akka.remote.RemoteProtocol.ActorRefProtocol, akka.remote.RemoteProtocol.ActorRefProtocol.Builder, akka.remote.RemoteProtocol.ActorRefProtocolOrBuilder> watchedBuilder_; + public boolean hasWatched() { return ((bitField0_ & 0x00000002) == 0x00000002); } - public akka.remote.RemoteProtocol.ActorRefProtocol getSender() { - if (senderBuilder_ == null) { - return sender_; + public akka.remote.RemoteProtocol.ActorRefProtocol getWatched() { + if (watchedBuilder_ == null) { + return watched_; } else { - return senderBuilder_.getMessage(); + return watchedBuilder_.getMessage(); } } - public Builder setSender(akka.remote.RemoteProtocol.ActorRefProtocol value) { - if (senderBuilder_ == null) { + public Builder setWatched(akka.remote.RemoteProtocol.ActorRefProtocol value) { + if (watchedBuilder_ == null) { if (value == null) { throw new NullPointerException(); } - sender_ = value; + watched_ = value; onChanged(); } else { - senderBuilder_.setMessage(value); + watchedBuilder_.setMessage(value); } bitField0_ |= 0x00000002; return this; } - public Builder setSender( + public Builder setWatched( akka.remote.RemoteProtocol.ActorRefProtocol.Builder builderForValue) { - if (senderBuilder_ == null) { - sender_ = builderForValue.build(); + if (watchedBuilder_ == null) { + watched_ = builderForValue.build(); onChanged(); } else { - senderBuilder_.setMessage(builderForValue.build()); + watchedBuilder_.setMessage(builderForValue.build()); } bitField0_ |= 0x00000002; return this; } - public Builder mergeSender(akka.remote.RemoteProtocol.ActorRefProtocol value) { - if (senderBuilder_ == null) { + public Builder mergeWatched(akka.remote.RemoteProtocol.ActorRefProtocol value) { + if (watchedBuilder_ == null) { if (((bitField0_ & 0x00000002) == 0x00000002) && - sender_ != akka.remote.RemoteProtocol.ActorRefProtocol.getDefaultInstance()) { - sender_ = - akka.remote.RemoteProtocol.ActorRefProtocol.newBuilder(sender_).mergeFrom(value).buildPartial(); + watched_ != akka.remote.RemoteProtocol.ActorRefProtocol.getDefaultInstance()) { + watched_ = + akka.remote.RemoteProtocol.ActorRefProtocol.newBuilder(watched_).mergeFrom(value).buildPartial(); } else { - sender_ = value; + watched_ = value; } onChanged(); } else { - senderBuilder_.mergeFrom(value); + watchedBuilder_.mergeFrom(value); } bitField0_ |= 0x00000002; return this; } - public Builder clearSender() { - if (senderBuilder_ == null) { - sender_ = akka.remote.RemoteProtocol.ActorRefProtocol.getDefaultInstance(); + public Builder clearWatched() { + if (watchedBuilder_ == null) { + watched_ = akka.remote.RemoteProtocol.ActorRefProtocol.getDefaultInstance(); onChanged(); } else { - senderBuilder_.clear(); + watchedBuilder_.clear(); } bitField0_ = (bitField0_ & ~0x00000002); return this; } - public akka.remote.RemoteProtocol.ActorRefProtocol.Builder getSenderBuilder() { + public akka.remote.RemoteProtocol.ActorRefProtocol.Builder getWatchedBuilder() { bitField0_ |= 0x00000002; onChanged(); - return getSenderFieldBuilder().getBuilder(); + return getWatchedFieldBuilder().getBuilder(); } - public akka.remote.RemoteProtocol.ActorRefProtocolOrBuilder getSenderOrBuilder() { - if (senderBuilder_ != null) { - return senderBuilder_.getMessageOrBuilder(); + public akka.remote.RemoteProtocol.ActorRefProtocolOrBuilder getWatchedOrBuilder() { + if (watchedBuilder_ != null) { + return watchedBuilder_.getMessageOrBuilder(); } else { - return sender_; + return watched_; } } private com.google.protobuf.SingleFieldBuilder< akka.remote.RemoteProtocol.ActorRefProtocol, akka.remote.RemoteProtocol.ActorRefProtocol.Builder, akka.remote.RemoteProtocol.ActorRefProtocolOrBuilder> - getSenderFieldBuilder() { - if (senderBuilder_ == null) { - senderBuilder_ = new com.google.protobuf.SingleFieldBuilder< + getWatchedFieldBuilder() { + if (watchedBuilder_ == null) { + watchedBuilder_ = new com.google.protobuf.SingleFieldBuilder< akka.remote.RemoteProtocol.ActorRefProtocol, akka.remote.RemoteProtocol.ActorRefProtocol.Builder, akka.remote.RemoteProtocol.ActorRefProtocolOrBuilder>( - sender_, + watched_, getParentForChildren(), isClean()); - sender_ = null; + watched_ = null; } - return senderBuilder_; + return watchedBuilder_; } - // required bytes message = 3; - private com.google.protobuf.ByteString message_ = com.google.protobuf.ByteString.EMPTY; - public boolean hasMessage() { - return ((bitField0_ & 0x00000004) == 0x00000004); - } - public com.google.protobuf.ByteString getMessage() { - return message_; - } - public Builder setMessage(com.google.protobuf.ByteString value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000004; - message_ = value; - onChanged(); - return this; - } - public Builder clearMessage() { - bitField0_ = (bitField0_ & ~0x00000004); - message_ = getDefaultInstance().getMessage(); - onChanged(); - return this; - } - - // @@protoc_insertion_point(builder_scope:DurableMailboxMessageProtocol) + // @@protoc_insertion_point(builder_scope:DaemonMsgWatchProtocol) } static { - defaultInstance = new DurableMailboxMessageProtocol(true); + defaultInstance = new DaemonMsgWatchProtocol(true); defaultInstance.initFields(); } - // @@protoc_insertion_point(class_scope:DurableMailboxMessageProtocol) + // @@protoc_insertion_point(class_scope:DaemonMsgWatchProtocol) } private static com.google.protobuf.Descriptors.Descriptor @@ -4871,10 +6900,25 @@ public final class RemoteProtocol { com.google.protobuf.GeneratedMessage.FieldAccessorTable internal_static_AddressProtocol_fieldAccessorTable; private static com.google.protobuf.Descriptors.Descriptor - internal_static_DurableMailboxMessageProtocol_descriptor; + internal_static_DaemonMsgCreateProtocol_descriptor; private static com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_DurableMailboxMessageProtocol_fieldAccessorTable; + internal_static_DaemonMsgCreateProtocol_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_PropsProtocol_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_PropsProtocol_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_DeployProtocol_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_DeployProtocol_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_DaemonMsgWatchProtocol_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_DaemonMsgWatchProtocol_fieldAccessorTable; public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { @@ -4900,12 +6944,20 @@ public final class RemoteProtocol { "anifest\030\003 \001(\014\"3\n\025MetadataEntryProtocol\022\013" + "\n\003key\030\001 \002(\t\022\r\n\005value\030\002 \002(\014\"A\n\017AddressPro" + "tocol\022\016\n\006system\030\001 \002(\t\022\020\n\010hostname\030\002 \002(\t\022" + - "\014\n\004port\030\003 \002(\r\"y\n\035DurableMailboxMessagePr" + - "otocol\022$\n\trecipient\030\001 \002(\0132\021.ActorRefProt" + - "ocol\022!\n\006sender\030\002 \001(\0132\021.ActorRefProtocol\022" + - "\017\n\007message\030\003 \002(\014*7\n\013CommandType\022\013\n\007CONNE", - "CT\020\001\022\014\n\010SHUTDOWN\020\002\022\r\n\tHEARTBEAT\020\003B\017\n\013akk" + - "a.remoteH\001" + "\014\n\004port\030\003 \002(\r\"\216\001\n\027DaemonMsgCreateProtoco" + + "l\022\035\n\005props\030\001 \002(\0132\016.PropsProtocol\022\037\n\006depl" + + "oy\030\002 \002(\0132\017.DeployProtocol\022\014\n\004path\030\003 \002(\t\022" + + "%\n\nsupervisor\030\004 \002(\0132\021.ActorRefProtocol\"k", + "\n\rPropsProtocol\022\017\n\007creator\030\001 \002(\014\022\022\n\ndisp" + + "atcher\030\002 \002(\t\022\037\n\006deploy\030\003 \002(\0132\017.DeployPro" + + "tocol\022\024\n\014routerConfig\030\004 \001(\014\"S\n\016DeployPro" + + "tocol\022\014\n\004path\030\001 \002(\t\022\016\n\006config\030\002 \001(\014\022\024\n\014r" + + "outerConfig\030\003 \001(\014\022\r\n\005scope\030\004 \001(\014\"`\n\026Daem" + + "onMsgWatchProtocol\022\"\n\007watcher\030\001 \002(\0132\021.Ac" + + "torRefProtocol\022\"\n\007watched\030\002 \002(\0132\021.ActorR" + + "efProtocol*7\n\013CommandType\022\013\n\007CONNECT\020\001\022\014" + + "\n\010SHUTDOWN\020\002\022\r\n\tHEARTBEAT\020\003B\017\n\013akka.remo" + + "teH\001" }; com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() { @@ -4968,14 +7020,38 @@ public final class RemoteProtocol { new java.lang.String[] { "System", "Hostname", "Port", }, akka.remote.RemoteProtocol.AddressProtocol.class, akka.remote.RemoteProtocol.AddressProtocol.Builder.class); - internal_static_DurableMailboxMessageProtocol_descriptor = + internal_static_DaemonMsgCreateProtocol_descriptor = getDescriptor().getMessageTypes().get(7); - internal_static_DurableMailboxMessageProtocol_fieldAccessorTable = new + internal_static_DaemonMsgCreateProtocol_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_DurableMailboxMessageProtocol_descriptor, - new java.lang.String[] { "Recipient", "Sender", "Message", }, - akka.remote.RemoteProtocol.DurableMailboxMessageProtocol.class, - akka.remote.RemoteProtocol.DurableMailboxMessageProtocol.Builder.class); + internal_static_DaemonMsgCreateProtocol_descriptor, + new java.lang.String[] { "Props", "Deploy", "Path", "Supervisor", }, + akka.remote.RemoteProtocol.DaemonMsgCreateProtocol.class, + akka.remote.RemoteProtocol.DaemonMsgCreateProtocol.Builder.class); + internal_static_PropsProtocol_descriptor = + getDescriptor().getMessageTypes().get(8); + internal_static_PropsProtocol_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_PropsProtocol_descriptor, + new java.lang.String[] { "Creator", "Dispatcher", "Deploy", "RouterConfig", }, + akka.remote.RemoteProtocol.PropsProtocol.class, + akka.remote.RemoteProtocol.PropsProtocol.Builder.class); + internal_static_DeployProtocol_descriptor = + getDescriptor().getMessageTypes().get(9); + internal_static_DeployProtocol_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_DeployProtocol_descriptor, + new java.lang.String[] { "Path", "Config", "RouterConfig", "Scope", }, + akka.remote.RemoteProtocol.DeployProtocol.class, + akka.remote.RemoteProtocol.DeployProtocol.Builder.class); + internal_static_DaemonMsgWatchProtocol_descriptor = + getDescriptor().getMessageTypes().get(10); + internal_static_DaemonMsgWatchProtocol_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_DaemonMsgWatchProtocol_descriptor, + new java.lang.String[] { "Watcher", "Watched", }, + akka.remote.RemoteProtocol.DaemonMsgWatchProtocol.class, + akka.remote.RemoteProtocol.DaemonMsgWatchProtocol.Builder.class); return null; } }; diff --git a/akka-remote/src/main/protocol/RemoteProtocol.proto b/akka-remote/src/main/protocol/RemoteProtocol.proto index 730c3a5883..7ae11d9cb7 100644 --- a/akka-remote/src/main/protocol/RemoteProtocol.proto +++ b/akka-remote/src/main/protocol/RemoteProtocol.proto @@ -79,10 +79,39 @@ message AddressProtocol { } /** - * Defines the durable mailbox message. + * Defines akka.remote.DaemonMsgCreate */ -message DurableMailboxMessageProtocol { - required ActorRefProtocol recipient= 1; - optional ActorRefProtocol sender = 2; - required bytes message = 3; +message DaemonMsgCreateProtocol { + required PropsProtocol props = 1; + required DeployProtocol deploy = 2; + required string path = 3; + required ActorRefProtocol supervisor = 4; +} + +/** + * Serialization of akka.actor.Props + */ +message PropsProtocol { + required bytes creator = 1; + required string dispatcher = 2; + required DeployProtocol deploy = 3; + optional bytes routerConfig = 4; +} + +/** + * Serialization of akka.actor.Deploy + */ +message DeployProtocol { + required string path = 1; + optional bytes config = 2; + optional bytes routerConfig = 3; + optional bytes scope = 4; +} + +/** + * Serialization of akka.remote.DaemonMsgWatch + */ +message DaemonMsgWatchProtocol { + required ActorRefProtocol watcher = 1; + required ActorRefProtocol watched = 2; } diff --git a/akka-remote/src/main/resources/reference.conf b/akka-remote/src/main/resources/reference.conf index 4512ea3a98..11a4da0711 100644 --- a/akka-remote/src/main/resources/reference.conf +++ b/akka-remote/src/main/resources/reference.conf @@ -14,6 +14,8 @@ akka { serializers { proto = "akka.serialization.ProtobufSerializer" + daemon-create = "akka.serialization.DaemonMsgCreateSerializer" + daemon-watch = "akka.serialization.DaemonMsgWatchSerializer" } @@ -21,6 +23,8 @@ akka { # Since com.google.protobuf.Message does not extend Serializable but GeneratedMessage # does, need to use the more specific one here in order to avoid ambiguity "com.google.protobuf.GeneratedMessage" = proto + "akka.remote.DaemonMsgCreate" = daemon-create + "akka.remote.DaemonMsgWatch" = daemon-watch } deployment { diff --git a/akka-remote/src/main/scala/akka/serialization/DaemonMsgCreateSerializer.scala b/akka-remote/src/main/scala/akka/serialization/DaemonMsgCreateSerializer.scala new file mode 100644 index 0000000000..cc7e3b3851 --- /dev/null +++ b/akka-remote/src/main/scala/akka/serialization/DaemonMsgCreateSerializer.scala @@ -0,0 +1,139 @@ +/** + * Copyright (C) 2009-2012 Typesafe Inc. + */ + +package akka.serialization + +import java.io.Serializable + +import com.google.protobuf.ByteString +import com.typesafe.config.Config +import com.typesafe.config.ConfigFactory + +import akka.actor.Actor +import akka.actor.ActorRef +import akka.actor.Deploy +import akka.actor.ExtendedActorSystem +import akka.actor.NoScopeGiven +import akka.actor.Props +import akka.actor.Scope +import akka.remote.DaemonMsgCreate +import akka.remote.RemoteProtocol.ActorRefProtocol +import akka.remote.RemoteProtocol.DaemonMsgCreateProtocol +import akka.remote.RemoteProtocol.DeployProtocol +import akka.remote.RemoteProtocol.PropsProtocol +import akka.routing.NoRouter +import akka.routing.RouterConfig + +/** + * Serializes akka's internal DaemonMsgCreate using protobuf + * for the core structure of DaemonMsgCreate, Props and Deploy. + * Serialization of contained RouterConfig, Config, Scope, and creator (scala.Function0) + * is done with configured serializer for those classes, by default java.io.Serializable. + */ +class DaemonMsgCreateSerializer(val system: ExtendedActorSystem) extends Serializer { + import ProtobufSerializer.serializeActorRef + import ProtobufSerializer.deserializeActorRef + + def includeManifest: Boolean = true + def identifier = 3 + lazy val serialization = SerializationExtension(system) + + def toBinary(obj: AnyRef): Array[Byte] = obj match { + case DaemonMsgCreate(props, deploy, path, supervisor) ⇒ + + def deployProto(d: Deploy): DeployProtocol = { + val builder = DeployProtocol.newBuilder.setPath(d.path) + if (d.config != ConfigFactory.empty) + builder.setConfig(serialize(d.config)) + if (d.routerConfig != NoRouter) + builder.setRouterConfig(serialize(d.routerConfig)) + if (d.scope != NoScopeGiven) + builder.setScope(serialize(d.scope)) + builder.build + } + + def propsProto = { + val builder = PropsProtocol.newBuilder. + setCreator(serialize(props.creator)). + setDispatcher(props.dispatcher). + setDeploy(deployProto(props.deploy)) + if (props.routerConfig != NoRouter) + builder.setRouterConfig(serialize(props.routerConfig)) + builder.build + } + + DaemonMsgCreateProtocol.newBuilder. + setProps(propsProto). + setDeploy(deployProto(deploy)). + setPath(path). + setSupervisor(serializeActorRef(supervisor)). + build.toByteArray + + case _ ⇒ + throw new IllegalArgumentException( + "Can't serialize a non-DaemonMsgCreate message using DaemonMsgCreateSerializer [%s]".format(obj)) + } + + def fromBinary(bytes: Array[Byte], clazz: Option[Class[_]]): AnyRef = { + val proto = DaemonMsgCreateProtocol.parseFrom(bytes) + + def deploy(protoDeploy: DeployProtocol) = { + val config = + if (protoDeploy.hasConfig) deserialize(protoDeploy.getConfig, classOf[Config]) + else ConfigFactory.empty + val routerConfig = + if (protoDeploy.hasRouterConfig) deserialize(protoDeploy.getRouterConfig, classOf[RouterConfig]) + else NoRouter + val scope = + if (protoDeploy.hasScope) deserialize(protoDeploy.getScope, classOf[Scope]) + else NoScopeGiven + Deploy(protoDeploy.getPath, config, routerConfig, scope) + } + + def props = { + val routerConfig = + if (proto.getProps.hasRouterConfig) deserialize(proto.getProps.getRouterConfig, classOf[RouterConfig]) + else NoRouter + Props( + creator = deserialize(proto.getProps.getCreator, classOf[() ⇒ Actor]), + dispatcher = proto.getProps.getDispatcher, + routerConfig = routerConfig, + deploy = deploy(proto.getProps.getDeploy)) + } + + DaemonMsgCreate( + props = props, + deploy = deploy(proto.getDeploy), + path = proto.getPath, + supervisor = deserializeActorRef(system, proto.getSupervisor)) + } + + protected def serialize(any: AnyRef): ByteString = + serialization.serialize(any) match { + case Right(bytes) ⇒ ByteString.copyFrom(bytes) + case Left(e) ⇒ throw e + } + + protected def deserialize[T: ClassManifest](data: ByteString, clazz: Class[T]): T = { + val bytes = data.toByteArray + serialization.deserialize(bytes, clazz) match { + case Right(x) if classManifest[T].erasure.isInstance(x) ⇒ x.asInstanceOf[T] + case Right(other) ⇒ throw new IllegalArgumentException("Can't deserialize to [%s], got [%s]". + format(clazz.getName, other)) + case Left(e) ⇒ + // Fallback to the java serializer, because some interfaces don't implement java.io.Serializable, + // but the impl instance does. This could be optimized by adding java serializers in reference.conf: + // scala.Function0 (the creator) + // com.typesafe.config.Config + // akka.routing.RouterConfig + // akka.actor.Scope + serialization.deserialize(bytes, classOf[java.io.Serializable]) match { + case Right(x) if classManifest[T].erasure.isInstance(x) ⇒ x.asInstanceOf[T] + case _ ⇒ throw e // the first exception + } + } + + } + +} \ No newline at end of file diff --git a/akka-remote/src/main/scala/akka/serialization/DaemonMsgWatchSerializer.scala b/akka-remote/src/main/scala/akka/serialization/DaemonMsgWatchSerializer.scala new file mode 100644 index 0000000000..a564e92088 --- /dev/null +++ b/akka-remote/src/main/scala/akka/serialization/DaemonMsgWatchSerializer.scala @@ -0,0 +1,41 @@ +/** + * Copyright (C) 2009-2012 Typesafe Inc. + */ + +package akka.serialization + +import akka.actor.ActorRef +import akka.remote.DaemonMsgWatch +import akka.remote.RemoteProtocol.ActorRefProtocol +import akka.remote.RemoteProtocol.DaemonMsgWatchProtocol +import akka.actor.ExtendedActorSystem + +/** + * Serializes akka's internal DaemonMsgWatch using protobuf. + */ +class DaemonMsgWatchSerializer(val system: ExtendedActorSystem) extends Serializer { + import ProtobufSerializer.serializeActorRef + import ProtobufSerializer.deserializeActorRef + + def includeManifest: Boolean = true + def identifier = 4 + + def toBinary(obj: AnyRef): Array[Byte] = obj match { + case DaemonMsgWatch(watcher, watched) ⇒ + DaemonMsgWatchProtocol.newBuilder. + setWatcher(serializeActorRef(watcher)). + setWatched(serializeActorRef(watched)). + build.toByteArray + case _ ⇒ + throw new IllegalArgumentException( + "Can't serialize a non-DaemonMsgWatch message using DaemonMsgWatchSerializer [%s]".format(obj)) + } + + def fromBinary(bytes: Array[Byte], clazz: Option[Class[_]]): AnyRef = { + val proto = DaemonMsgWatchProtocol.parseFrom(bytes) + DaemonMsgWatch( + watcher = deserializeActorRef(system, proto.getWatcher), + watched = deserializeActorRef(system, proto.getWatched)) + } + +} \ No newline at end of file diff --git a/akka-remote/src/main/scala/akka/serialization/ProtobufSerializer.scala b/akka-remote/src/main/scala/akka/serialization/ProtobufSerializer.scala index 813a22fba4..72690b3c91 100644 --- a/akka-remote/src/main/scala/akka/serialization/ProtobufSerializer.scala +++ b/akka-remote/src/main/scala/akka/serialization/ProtobufSerializer.scala @@ -6,6 +6,22 @@ package akka.serialization import com.google.protobuf.Message import akka.actor.DynamicAccess +import akka.remote.RemoteProtocol.ActorRefProtocol +import akka.actor.ActorSystem +import akka.actor.ActorRef + +object ProtobufSerializer { + def serializeActorRef(ref: ActorRef): ActorRefProtocol = { + val identifier: String = Serialization.currentTransportAddress.value match { + case null ⇒ ref.path.toString + case address ⇒ ref.path.toStringWithAddress(address) + } + ActorRefProtocol.newBuilder.setPath(identifier).build + } + + def deserializeActorRef(system: ActorSystem, refProtocol: ActorRefProtocol): ActorRef = + system.actorFor(refProtocol.getPath) +} /** * This Serializer serializes `com.google.protobuf.Message`s diff --git a/akka-remote/src/test/scala/akka/serialization/DaemonMsgCreateSerializerSpec.scala b/akka-remote/src/test/scala/akka/serialization/DaemonMsgCreateSerializerSpec.scala new file mode 100644 index 0000000000..eed2c73d2c --- /dev/null +++ b/akka-remote/src/test/scala/akka/serialization/DaemonMsgCreateSerializerSpec.scala @@ -0,0 +1,104 @@ +/** + * Copyright (C) 2009-2012 Typesafe Inc. + */ + +package akka.serialization + +import com.typesafe.config.ConfigFactory +import akka.testkit.AkkaSpec +import akka.actor.Actor +import akka.actor.Address +import akka.actor.Props +import akka.actor.Deploy +import akka.actor.OneForOneStrategy +import akka.actor.SupervisorStrategy +import akka.remote.DaemonMsgCreate +import akka.remote.RemoteScope +import akka.routing.RoundRobinRouter +import akka.routing.FromConfig +import akka.util.duration._ + +object DaemonMsgCreateSerializerSpec { + class MyActor extends Actor { + def receive = { + case _ ⇒ + } + } +} + +@org.junit.runner.RunWith(classOf[org.scalatest.junit.JUnitRunner]) +class DaemonMsgCreateSerializerSpec extends AkkaSpec { + + import DaemonMsgCreateSerializerSpec._ + val ser = SerializationExtension(system) + val supervisor = system.actorOf(Props[MyActor], "supervisor") + + "Serialization" must { + + "resolve DaemonMsgCreateSerializer" in { + ser.serializerFor(classOf[DaemonMsgCreate]).getClass must be(classOf[DaemonMsgCreateSerializer]) + } + + "serialize and de-serialize simple DaemonMsgCreate" in { + + val msg = DaemonMsgCreate( + props = Props[MyActor], + deploy = Deploy(), + path = "foo", + supervisor = supervisor) + + val bytes = ser.serialize(msg) match { + case Left(exception) ⇒ fail(exception) + case Right(bytes) ⇒ bytes + } + ser.deserialize(bytes.asInstanceOf[Array[Byte]], classOf[DaemonMsgCreate]) match { + case Left(exception) ⇒ fail(exception) + case Right(m: DaemonMsgCreate) ⇒ assertDaemonMsgCreate(msg, m) + } + } + + "serialize and de-serialize DaemonMsgCreate with Deploy and RouterConfig" in { + // Duration.Inf doesn't equal Duration.Inf, so we use another for test + val supervisorStrategy = OneForOneStrategy(3, 10 seconds) { + case _ ⇒ SupervisorStrategy.Escalate + } + val deploy1 = Deploy( + path = "path1", + config = ConfigFactory.parseString("a=1"), + routerConfig = RoundRobinRouter(nrOfInstances = 5, supervisorStrategy = supervisorStrategy), + scope = RemoteScope(Address("akka", "Test", "host1", 1921))) + val deploy2 = Deploy( + path = "path2", + config = ConfigFactory.parseString("a=2"), + routerConfig = FromConfig, + scope = RemoteScope(Address("akka", "Test", "host2", 1922))) + val msg = DaemonMsgCreate( + props = Props[MyActor].withDispatcher("my-disp").withDeploy(deploy1), + deploy = deploy2, + path = "foo", + supervisor = supervisor) + + val bytes = ser.serialize(msg) match { + case Left(exception) ⇒ fail(exception) + case Right(bytes) ⇒ bytes + } + ser.deserialize(bytes.asInstanceOf[Array[Byte]], classOf[DaemonMsgCreate]) match { + case Left(exception) ⇒ fail(exception) + case Right(m: DaemonMsgCreate) ⇒ assertDaemonMsgCreate(msg, m) + } + } + + def assertDaemonMsgCreate(expected: DaemonMsgCreate, got: DaemonMsgCreate): Unit = { + // can't compare props.creator + assert(got.props.dispatcher === expected.props.dispatcher) + assert(got.props.dispatcher === expected.props.dispatcher) + assert(got.props.routerConfig === expected.props.routerConfig) + assert(got.props.deploy === expected.props.deploy) + assert(got.deploy === expected.deploy) + assert(got.path === expected.path) + assert(got.supervisor === expected.supervisor) + } + + } +} + diff --git a/akka-remote/src/test/scala/akka/serialization/DaemonMsgWatchSerializerSpec.scala b/akka-remote/src/test/scala/akka/serialization/DaemonMsgWatchSerializerSpec.scala new file mode 100644 index 0000000000..a6069beac1 --- /dev/null +++ b/akka-remote/src/test/scala/akka/serialization/DaemonMsgWatchSerializerSpec.scala @@ -0,0 +1,49 @@ +/** + * Copyright (C) 2009-2012 Typesafe Inc. + */ + +package akka.serialization + +import akka.testkit.AkkaSpec +import akka.remote.DaemonMsgWatch +import akka.actor.Actor +import akka.actor.Props + +object DaemonMsgWatchSerializerSpec { + class MyActor extends Actor { + def receive = { + case _ ⇒ + } + } +} + +@org.junit.runner.RunWith(classOf[org.scalatest.junit.JUnitRunner]) +class DaemonMsgWatchSerializerSpec extends AkkaSpec { + + import DaemonMsgWatchSerializerSpec._ + + val ser = SerializationExtension(system) + + "Serialization" must { + + "resolve DaemonMsgWatchSerializer" in { + ser.serializerFor(classOf[DaemonMsgWatch]).getClass must be(classOf[DaemonMsgWatchSerializer]) + } + + "serialize and de-serialize DaemonMsgWatch" in { + val watcher = system.actorOf(Props[MyActor], "watcher") + val watched = system.actorOf(Props[MyActor], "watched") + val msg = DaemonMsgWatch(watcher, watched) + val bytes = ser.serialize(msg) match { + case Left(exception) ⇒ fail(exception) + case Right(bytes) ⇒ bytes + } + ser.deserialize(bytes.asInstanceOf[Array[Byte]], classOf[DaemonMsgWatch]) match { + case Left(exception) ⇒ fail(exception) + case Right(m) ⇒ assert(m === msg) + } + } + + } +} + From 8924080017797973fcebd28464eea045bedede43 Mon Sep 17 00:00:00 2001 From: Patrik Nordwall Date: Tue, 15 May 2012 16:01:32 +0200 Subject: [PATCH 02/21] Create test-fixture for durable mailboxes. See #2061 * Improved DurableMailboxSpec for stand alone usage * Changed build to publish DurableMailboxSpec in akka-mailboxes-common-test * Changed documentation of durable mailboxes and added full example of how to implement a durable mailbox, with test --- akka-docs/intro/deployment-scenarios.rst | 5 +- akka-docs/intro/getting-started.rst | 3 +- akka-docs/java/microkernel.rst | 2 +- .../actor/mailbox/DurableMailboxDocSpec.scala | 88 ++++++++++++++- .../mailbox/DurableMailboxDocTestBase.java | 13 +-- akka-docs/modules/durable-mailbox.rst | 102 ++++++++++-------- akka-docs/scala/microkernel.rst | 2 +- .../actor/mailbox/FileBasedMailboxSpec.scala | 8 +- .../actor/mailbox/DurableMailboxSpec.scala | 79 ++++++++++++-- .../test/scala/akka/testkit/AkkaSpec.scala | 4 +- project/AkkaBuild.scala | 7 +- 11 files changed, 234 insertions(+), 79 deletions(-) diff --git a/akka-docs/intro/deployment-scenarios.rst b/akka-docs/intro/deployment-scenarios.rst index b2d0334c7d..fc3b38cbd2 100644 --- a/akka-docs/intro/deployment-scenarios.rst +++ b/akka-docs/intro/deployment-scenarios.rst @@ -13,7 +13,7 @@ Akka can be used in different ways: be put into ``WEB-INF/lib`` - As a stand alone application by instantiating ActorSystem in a main class or - using the :ref:`microkernel` + using the :ref:`microkernel-scala` / :ref:`microkernel-java` Using Akka as library @@ -27,5 +27,6 @@ modules to the stack. Using Akka as a stand alone microkernel ---------------------------------------- -Akka can also be run as a stand-alone microkernel. See :ref:`microkernel` for +Akka can also be run as a stand-alone microkernel. See +:ref:`microkernel-scala` / :ref:`microkernel-java` for more information. diff --git a/akka-docs/intro/getting-started.rst b/akka-docs/intro/getting-started.rst index b3bdbf70f3..9c76ee8edf 100644 --- a/akka-docs/intro/getting-started.rst +++ b/akka-docs/intro/getting-started.rst @@ -67,7 +67,8 @@ The Akka distribution includes the microkernel. To run the microkernel put your application jar in the ``deploy`` directory and use the scripts in the ``bin`` directory. -More information is available in the documentation of the :ref:`microkernel`. +More information is available in the documentation of the +:ref:`microkernel-scala` / :ref:`microkernel-java`. Using a build tool ------------------ diff --git a/akka-docs/java/microkernel.rst b/akka-docs/java/microkernel.rst index 551c118e94..d6652fe316 100644 --- a/akka-docs/java/microkernel.rst +++ b/akka-docs/java/microkernel.rst @@ -1,5 +1,5 @@ -.. _microkernel: +.. _microkernel-java: Microkernel (Java) ================== diff --git a/akka-docs/modules/code/akka/docs/actor/mailbox/DurableMailboxDocSpec.scala b/akka-docs/modules/code/akka/docs/actor/mailbox/DurableMailboxDocSpec.scala index 2f67c607ed..25f312cac3 100644 --- a/akka-docs/modules/code/akka/docs/actor/mailbox/DurableMailboxDocSpec.scala +++ b/akka-docs/modules/code/akka/docs/actor/mailbox/DurableMailboxDocSpec.scala @@ -33,8 +33,94 @@ class DurableMailboxDocSpec extends AkkaSpec(DurableMailboxDocSpec.config) { "configuration of dispatcher with durable mailbox" in { //#dispatcher-config-use - val myActor = system.actorOf(Props[MyActor].withDispatcher("my-dispatcher"), name = "myactor") + val myActor = system.actorOf(Props[MyActor]. + withDispatcher("my-dispatcher"), name = "myactor") //#dispatcher-config-use } } + +//#custom-mailbox +import com.typesafe.config.Config +import akka.actor.ActorContext +import akka.actor.ActorRef +import akka.actor.ActorSystem +import akka.dispatch.Envelope +import akka.dispatch.MailboxType +import akka.dispatch.MessageQueue +import akka.actor.mailbox.DurableMessageQueue +import akka.actor.mailbox.DurableMessageSerialization + +class MyMailboxType(systemSettings: ActorSystem.Settings, config: Config) + extends MailboxType { + + override def create(owner: Option[ActorContext]): MessageQueue = owner match { + case Some(o) ⇒ new MyMessageQueue(o) + case None ⇒ throw new IllegalArgumentException( + "requires an owner (i.e. does not work with BalancingDispatcher)") + } +} + +class MyMessageQueue(_owner: ActorContext) + extends DurableMessageQueue(_owner) with DurableMessageSerialization { + + val storage = new QueueStorage + + def enqueue(receiver: ActorRef, envelope: Envelope) { + val data: Array[Byte] = serialize(envelope) + storage.push(data) + } + + def dequeue(): Envelope = { + val data: Option[Array[Byte]] = storage.pull() + data.map(deserialize(_)).getOrElse(null) + } + + def hasMessages: Boolean = !storage.isEmpty + + def numberOfMessages: Int = storage.size + + def cleanUp(owner: ActorContext, deadLetters: MessageQueue): Unit = () + +} +//#custom-mailbox + +// dummy +class QueueStorage { + import java.util.concurrent.ConcurrentLinkedQueue + val queue = new ConcurrentLinkedQueue[Array[Byte]] + def push(data: Array[Byte]): Unit = queue.offer(data) + def pull(): Option[Array[Byte]] = Option(queue.poll()) + def isEmpty: Boolean = queue.isEmpty + def size: Int = queue.size +} + +//#custom-mailbox-test +import akka.actor.mailbox.DurableMailboxSpec + +object MyMailboxSpec { + val config = """ + MyStorage-dispatcher { + mailbox-type = akka.docs.actor.mailbox.MyMailboxType + } + """ +} + +class MyMailboxSpec extends DurableMailboxSpec("MyStorage", MyMailboxSpec.config) { + override def atStartup() { + } + + override def atTermination() { + } + + "MyMailbox" must { + "deliver a message" in { + val actor = createMailboxTestActor() + implicit val sender = testActor + actor ! "hello" + expectMsg("hello") + } + + // add more tests + } +} \ No newline at end of file diff --git a/akka-docs/modules/code/akka/docs/actor/mailbox/DurableMailboxDocTestBase.java b/akka-docs/modules/code/akka/docs/actor/mailbox/DurableMailboxDocTestBase.java index 834dc6f0fb..25158446b6 100644 --- a/akka-docs/modules/code/akka/docs/actor/mailbox/DurableMailboxDocTestBase.java +++ b/akka-docs/modules/code/akka/docs/actor/mailbox/DurableMailboxDocTestBase.java @@ -4,9 +4,8 @@ package akka.docs.actor.mailbox; //#imports -import akka.actor.UntypedActorFactory; -import akka.actor.UntypedActor; import akka.actor.Props; +import akka.actor.ActorRef; //#imports @@ -16,8 +15,8 @@ import org.junit.Test; import akka.testkit.AkkaSpec; import com.typesafe.config.ConfigFactory; -import akka.actor.ActorRef; import akka.actor.ActorSystem; +import akka.actor.UntypedActor; import static org.junit.Assert.*; @@ -39,12 +38,8 @@ public class DurableMailboxDocTestBase { @Test public void configDefinedDispatcher() { //#dispatcher-config-use - ActorRef myActor = system.actorOf( - new Props().withDispatcher("my-dispatcher").withCreator(new UntypedActorFactory() { - public UntypedActor create() { - return new MyUntypedActor(); - } - }), "myactor"); + ActorRef myActor = system.actorOf(new Props(MyUntypedActor.class). + withDispatcher("my-dispatcher"), "myactor"); //#dispatcher-config-use myActor.tell("test"); } diff --git a/akka-docs/modules/durable-mailbox.rst b/akka-docs/modules/durable-mailbox.rst index 74618d978e..4de60ea12b 100644 --- a/akka-docs/modules/durable-mailbox.rst +++ b/akka-docs/modules/durable-mailbox.rst @@ -9,40 +9,45 @@ Overview ======== -Akka supports a set of durable mailboxes. A durable mailbox is a replacement for -the standard actor mailbox that is durable. What this means in practice is that -if there are pending messages in the actor's mailbox when the node of the actor -resides on crashes, then when you restart the node, the actor will be able to -continue processing as if nothing had happened; with all pending messages still -in its mailbox. +A durable mailbox is a replacement for the standard actor mailbox that is durable. +What this means in practice is that if there are pending messages in the actor's +mailbox when the node of the actor resides on crashes, then when you restart the +node, the actor will be able to continue processing as if nothing had happened; +with all pending messages still in its mailbox. -None of these mailboxes implements transactions for current message. It's possible +You configure durable mailboxes through the dispatcher. The actor is oblivious +to which type of mailbox it is using. + +This gives you an excellent way of creating bulkheads in your application, where +groups of actors sharing the same dispatcher also share the same backing +storage. Read more about that in the :ref:`dispatchers-scala` documentation. + +One basic file based durable mailbox is provided by Akka out-of-the-box. +Other implementations can easily be added. Some are available as separate community +Open Source projects, such as: + +* `AMQP Durable Mailbox `_ + + +A durable mailbox typically doesn't implements transactions for current message. It's possible if the actor crashes after receiving a message, but before completing processing of it, that the message could be lost. -.. warning:: **IMPORTANT** +.. warning:: - None of these mailboxes work with blocking message send, i.e. the message + A durable mailbox typically doesn't work with blocking message send, i.e. the message send operations that are relying on futures; ``?`` or ``ask``. If the node has crashed and then restarted, the thread that was blocked waiting for the reply is gone and there is no way we can deliver the message. -The durable mailboxes supported out-of-the-box are: - - ``FileBasedMailbox`` -- backed by a journaling transaction log on the local file system +File-based durable mailbox +========================== -You can easily implement your own mailbox. Look at the existing implementation for inspiration. - -.. _DurableMailbox.General: - -General Usage -------------- - -The durable mailboxes and their configuration options reside in the -``akka.actor.mailbox`` package. - -You configure durable mailboxes through the dispatcher. The -actor is oblivious to which type of mailbox it is using. +This mailbox is backed by a journaling transaction log on the local file +system. It is the simplest to use since it does not require an extra +infrastructure piece to administer, but it is usually sufficient and just what +you need. In the configuration of the dispatcher you specify the fully qualified class name of the mailbox: @@ -60,32 +65,37 @@ Corresponding example in Java: .. includecode:: code/akka/docs/actor/mailbox/DurableMailboxDocTestBase.java :include: imports,dispatcher-config-use -The actor is oblivious to which type of mailbox it is using. - -This gives you an excellent way of creating bulkheads in your application, where -groups of actors sharing the same dispatcher also share the same backing -storage. Read more about that in the :ref:`dispatchers-scala` documentation. - -File-based durable mailbox -========================== - -This mailbox is backed by a journaling transaction log on the local file -system. It is the simplest to use since it does not require an extra -infrastructure piece to administer, but it is usually sufficient and just what -you need. - -You configure durable mailboxes through the dispatcher, as described in -:ref:`DurableMailbox.General` with the following mailbox type. - -Config:: - - my-dispatcher { - mailbox-type = akka.actor.mailbox.FileBasedMailboxType - } - You can also configure and tune the file-based durable mailbox. This is done in the ``akka.actor.mailbox.file-based`` section in the :ref:`configuration`. .. literalinclude:: ../../akka-durable-mailboxes/akka-file-mailbox/src/main/resources/reference.conf :language: none +How to implement a durable mailbox +================================== + +Here is an example of how to implement a custom durable mailbox. Essentially it consists of +a configurator (MailboxType) and a queue implementation (DurableMessageQueue). + +The envelope contains the message sent to the actor, and information about sender. It is the +envelope that needs to be stored. As a help utility you can mixin DurableMessageSerialization +to serialize and deserialize the envelope using the ordinary :ref:`serialization-scala` +mechanism. This optional and you may store the envelope data in any way you like. + +.. includecode:: code/akka/docs/actor/mailbox/DurableMailboxDocSpec.scala + :include: custom-mailbox + +To facilitate testing of a durable mailbox you may use ``DurableMailboxSpec`` as base class. +It implements a few basic tests and helps you setup the a fixture. More tests can be +added in concrete subclass like this: + +.. includecode:: code/akka/docs/actor/mailbox/DurableMailboxDocSpec.scala + :include: custom-mailbox-test + +You find DurableMailboxDocSpec in ``akka-mailboxes-common-test-2.1-SNAPSHOT.jar``. +Add this dependency:: + + "com.typesafe.akka" % "akka-mailboxes-common-test" % "2.1-SNAPSHOT" + +For more inspiration you can look at the old implementations based on Redis, MongoDB, Beanstalk, +and ZooKeeper, which can be found in Akka git repository tag v2.0.1. \ No newline at end of file diff --git a/akka-docs/scala/microkernel.rst b/akka-docs/scala/microkernel.rst index 8fb1aec2c2..108a00588a 100644 --- a/akka-docs/scala/microkernel.rst +++ b/akka-docs/scala/microkernel.rst @@ -1,5 +1,5 @@ -.. _microkernel: +.. _microkernel-scala: Microkernel (Scala) =================== diff --git a/akka-durable-mailboxes/akka-file-mailbox/src/test/scala/akka/actor/mailbox/FileBasedMailboxSpec.scala b/akka-durable-mailboxes/akka-file-mailbox/src/test/scala/akka/actor/mailbox/FileBasedMailboxSpec.scala index be82e0fcb3..6c97142068 100644 --- a/akka-durable-mailboxes/akka-file-mailbox/src/test/scala/akka/actor/mailbox/FileBasedMailboxSpec.scala +++ b/akka-durable-mailboxes/akka-file-mailbox/src/test/scala/akka/actor/mailbox/FileBasedMailboxSpec.scala @@ -25,19 +25,17 @@ class FileBasedMailboxSpec extends DurableMailboxSpec("File", FileBasedMailboxSp } } - def isDurableMailbox(m: Mailbox): Boolean = m.messageQueue.isInstanceOf[FileBasedMessageQueue] - - def clean { + def clean() { FileUtils.deleteDirectory(new java.io.File(queuePath)) } override def atStartup() { - clean + clean() super.atStartup() } override def atTermination() { - clean + clean() super.atTermination() } } diff --git a/akka-durable-mailboxes/akka-mailboxes-common/src/test/scala/akka/actor/mailbox/DurableMailboxSpec.scala b/akka-durable-mailboxes/akka-mailboxes-common/src/test/scala/akka/actor/mailbox/DurableMailboxSpec.scala index ff436c227e..9081a5fcb0 100644 --- a/akka-durable-mailboxes/akka-mailboxes-common/src/test/scala/akka/actor/mailbox/DurableMailboxSpec.scala +++ b/akka-durable-mailboxes/akka-mailboxes-common/src/test/scala/akka/actor/mailbox/DurableMailboxSpec.scala @@ -3,14 +3,25 @@ */ package akka.actor.mailbox -import akka.testkit.AkkaSpec -import akka.testkit.TestLatch -import akka.util.duration._ -import java.io.InputStream -import scala.annotation.tailrec +import DurableMailboxSpecActorFactory.AccumulatorActor +import DurableMailboxSpecActorFactory.MailboxTestActor +import akka.actor.Actor +import akka.actor.ActorRef +import akka.actor.ActorSystem +import akka.actor.LocalActorRef +import akka.actor.Props +import akka.actor.actorRef2Scala +import akka.dispatch.Mailbox +import akka.testkit.TestKit +import akka.util.duration.intToDurationInt import com.typesafe.config.Config -import akka.actor._ -import akka.dispatch.{ Mailbox, Await } +import com.typesafe.config.ConfigFactory +import java.io.InputStream +import java.util.concurrent.TimeoutException +import org.scalatest.BeforeAndAfterAll +import org.scalatest.WordSpec +import org.scalatest.matchers.MustMatchers +import scala.annotation.tailrec object DurableMailboxSpecActorFactory { @@ -28,13 +39,62 @@ object DurableMailboxSpecActorFactory { } +object DurableMailboxSpec { + def fallbackConfig: Config = ConfigFactory.parseString(""" + akka { + event-handlers = ["akka.testkit.TestEventListener"] + loglevel = "WARNING" + stdout-loglevel = "WARNING" + } + """) +} + /** + * Reusable test fixture for durable mailboxes. Implements a few basic tests. More + * tests can be added in concrete subclass. + * * Subclass must define dispatcher in the supplied config for the specific backend. * The id of the dispatcher must be the same as the `-dispatcher`. */ -abstract class DurableMailboxSpec(val backendName: String, config: String) extends AkkaSpec(config) { +abstract class DurableMailboxSpec(system: ActorSystem, val backendName: String) + extends TestKit(system) with WordSpec with MustMatchers with BeforeAndAfterAll { + import DurableMailboxSpecActorFactory._ + /** + * Subclass must define dispatcher in the supplied config for the specific backend. + * The id of the dispatcher must be the same as the `-dispatcher`. + */ + def this(backendName: String, config: String) = { + this(ActorSystem(backendName + "BasedDurableMailboxSpec", + ConfigFactory.parseString(config).withFallback(DurableMailboxSpec.fallbackConfig)), + backendName) + } + + final override def beforeAll { + atStartup() + } + + /** + * May be implemented in concrete subclass to do additional things once before test + * cases are run. + */ + protected def atStartup() {} + + final override def afterAll { + system.shutdown() + try system.awaitTermination(5 seconds) catch { + case _: TimeoutException ⇒ system.log.warning("Failed to stop [{}] within 5 seconds", system.name) + } + atTermination() + } + + /** + * May be implemented in concrete subclass to do additional things once after all + * test cases have been run. + */ + def atTermination() {} + protected def streamMustContain(in: InputStream, words: String): Unit = { val output = new Array[Byte](8192) @@ -60,7 +120,8 @@ abstract class DurableMailboxSpec(val backendName: String, config: String) exten case some ⇒ system.actorOf(props.withDispatcher(backendName + "-dispatcher"), some) } - def isDurableMailbox(m: Mailbox): Boolean + private def isDurableMailbox(m: Mailbox): Boolean = + m.messageQueue.isInstanceOf[DurableMessageQueue] "A " + backendName + " based mailbox backed actor" must { diff --git a/akka-testkit/src/test/scala/akka/testkit/AkkaSpec.scala b/akka-testkit/src/test/scala/akka/testkit/AkkaSpec.scala index fd763e6bad..f24ea49b8c 100644 --- a/akka-testkit/src/test/scala/akka/testkit/AkkaSpec.scala +++ b/akka-testkit/src/test/scala/akka/testkit/AkkaSpec.scala @@ -5,7 +5,7 @@ package akka.testkit import org.scalatest.{ WordSpec, BeforeAndAfterAll, Tag } import org.scalatest.matchers.MustMatchers -import akka.actor.{ ActorSystem, ActorSystemImpl } +import akka.actor.ActorSystem import akka.actor.{ Actor, ActorRef, Props } import akka.event.{ Logging, LoggingAdapter } import akka.util.duration._ @@ -72,7 +72,7 @@ abstract class AkkaSpec(_system: ActorSystem) final override def afterAll { system.shutdown() - try Await.ready(system.asInstanceOf[ActorSystemImpl].terminationFuture, 5 seconds) catch { + try system.awaitTermination(5 seconds) catch { case _: TimeoutException ⇒ system.log.warning("Failed to stop [{}] within 5 seconds", system.name) } atTermination() diff --git a/project/AkkaBuild.scala b/project/AkkaBuild.scala index 4804c0f796..a489d57c8b 100644 --- a/project/AkkaBuild.scala +++ b/project/AkkaBuild.scala @@ -154,7 +154,9 @@ object AkkaBuild extends Build { base = file("akka-durable-mailboxes/akka-mailboxes-common"), dependencies = Seq(remote, testkit % "compile;test->test"), settings = defaultSettings ++ Seq( - libraryDependencies ++= Dependencies.mailboxes + libraryDependencies ++= Dependencies.mailboxes, + // DurableMailboxSpec published in akka-mailboxes-common-test + publishArtifact in Test := true ) ) @@ -257,7 +259,8 @@ object AkkaBuild extends Build { lazy val docs = Project( id = "akka-docs", base = file("akka-docs"), - dependencies = Seq(actor, testkit % "test->test", remote, cluster, slf4j, agent, transactor, fileMailbox, zeroMQ, camel), + dependencies = Seq(actor, testkit % "test->test", mailboxesCommon % "compile;test->test", + remote, cluster, slf4j, agent, transactor, fileMailbox, zeroMQ, camel), settings = defaultSettings ++ Sphinx.settings ++ Seq( unmanagedSourceDirectories in Test <<= baseDirectory { _ ** "code" get }, libraryDependencies ++= Dependencies.docs, From 793af8b4ec316166f1cc3a17259443bd343bc054 Mon Sep 17 00:00:00 2001 From: Patrik Nordwall Date: Tue, 15 May 2012 17:16:46 +0200 Subject: [PATCH 03/21] Imrovements from feedback. See #1755 --- .../akka/serialization/DaemonMsgCreateSerializer.scala | 2 +- .../akka/serialization/DaemonMsgWatchSerializer.scala | 2 +- .../scala/akka/serialization/ProtobufSerializer.scala | 10 ++++++++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/akka-remote/src/main/scala/akka/serialization/DaemonMsgCreateSerializer.scala b/akka-remote/src/main/scala/akka/serialization/DaemonMsgCreateSerializer.scala index cc7e3b3851..7bd3124792 100644 --- a/akka-remote/src/main/scala/akka/serialization/DaemonMsgCreateSerializer.scala +++ b/akka-remote/src/main/scala/akka/serialization/DaemonMsgCreateSerializer.scala @@ -35,7 +35,7 @@ class DaemonMsgCreateSerializer(val system: ExtendedActorSystem) extends Seriali import ProtobufSerializer.serializeActorRef import ProtobufSerializer.deserializeActorRef - def includeManifest: Boolean = true + def includeManifest: Boolean = false def identifier = 3 lazy val serialization = SerializationExtension(system) diff --git a/akka-remote/src/main/scala/akka/serialization/DaemonMsgWatchSerializer.scala b/akka-remote/src/main/scala/akka/serialization/DaemonMsgWatchSerializer.scala index a564e92088..0ca5216da0 100644 --- a/akka-remote/src/main/scala/akka/serialization/DaemonMsgWatchSerializer.scala +++ b/akka-remote/src/main/scala/akka/serialization/DaemonMsgWatchSerializer.scala @@ -17,7 +17,7 @@ class DaemonMsgWatchSerializer(val system: ExtendedActorSystem) extends Serializ import ProtobufSerializer.serializeActorRef import ProtobufSerializer.deserializeActorRef - def includeManifest: Boolean = true + def includeManifest: Boolean = false def identifier = 4 def toBinary(obj: AnyRef): Array[Byte] = obj match { diff --git a/akka-remote/src/main/scala/akka/serialization/ProtobufSerializer.scala b/akka-remote/src/main/scala/akka/serialization/ProtobufSerializer.scala index 72690b3c91..d9a5c7b0c4 100644 --- a/akka-remote/src/main/scala/akka/serialization/ProtobufSerializer.scala +++ b/akka-remote/src/main/scala/akka/serialization/ProtobufSerializer.scala @@ -11,6 +11,11 @@ import akka.actor.ActorSystem import akka.actor.ActorRef object ProtobufSerializer { + + /** + * Helper to serialize an [[akka.actor.ActorRef]] to Akka's + * protobuf representation. + */ def serializeActorRef(ref: ActorRef): ActorRefProtocol = { val identifier: String = Serialization.currentTransportAddress.value match { case null ⇒ ref.path.toString @@ -19,6 +24,11 @@ object ProtobufSerializer { ActorRefProtocol.newBuilder.setPath(identifier).build } + /** + * Helper to materialize (lookup) an [[akka.actor.ActorRef]] + * from Akka's protobuf representation in the supplied + * [[akka.actor.ActorSystem]. + */ def deserializeActorRef(system: ActorSystem, refProtocol: ActorRefProtocol): ActorRef = system.actorFor(refProtocol.getPath) } From 31ace9e83f1a9dc361bc6d1aa4e79c4825e8e07e Mon Sep 17 00:00:00 2001 From: Patrik Nordwall Date: Tue, 15 May 2012 18:22:40 +0200 Subject: [PATCH 04/21] Optimize remote serialization for the create from class case. See #1755 * Added FromClassCreator as special Function0 to be able to serialize class name as protobuf string --- .../src/main/scala/akka/actor/Props.scala | 13 +- .../main/java/akka/remote/RemoteProtocol.java | 314 +++++++++++------- .../src/main/protocol/RemoteProtocol.proto | 9 +- .../DaemonMsgCreateSerializer.scala | 27 +- .../DaemonMsgCreateSerializerSpec.scala | 75 +++-- 5 files changed, 278 insertions(+), 160 deletions(-) diff --git a/akka-actor/src/main/scala/akka/actor/Props.scala b/akka-actor/src/main/scala/akka/actor/Props.scala index 3751898c5c..d66fb6653c 100644 --- a/akka-actor/src/main/scala/akka/actor/Props.scala +++ b/akka-actor/src/main/scala/akka/actor/Props.scala @@ -127,7 +127,7 @@ case class Props( * Java API. */ def this(actorClass: Class[_ <: Actor]) = this( - creator = () ⇒ actorClass.newInstance, + creator = FromClassCreator(actorClass), dispatcher = Dispatchers.DefaultDispatcherId, routerConfig = Props.defaultRoutedProps) @@ -150,7 +150,7 @@ case class Props( * * Java API. */ - def withCreator(c: Class[_ <: Actor]): Props = copy(creator = () ⇒ c.newInstance) + def withCreator(c: Class[_ <: Actor]): Props = copy(creator = FromClassCreator(c)) /** * Returns a new Props with the specified dispatcher set. @@ -166,4 +166,13 @@ case class Props( * Returns a new Props with the specified deployment configuration. */ def withDeploy(d: Deploy): Props = copy(deploy = d) + } + +/** + * Used when creating an Actor from a class. Special Function0 to be + * able to optimize serialization. + */ +private[akka] case class FromClassCreator(clazz: Class[_ <: Actor]) extends Function0[Actor] { + def apply(): Actor = clazz.newInstance +} \ No newline at end of file diff --git a/akka-remote/src/main/java/akka/remote/RemoteProtocol.java b/akka-remote/src/main/java/akka/remote/RemoteProtocol.java index e340a807cf..d168e5acc1 100644 --- a/akka-remote/src/main/java/akka/remote/RemoteProtocol.java +++ b/akka-remote/src/main/java/akka/remote/RemoteProtocol.java @@ -5035,20 +5035,24 @@ public final class RemoteProtocol { public interface PropsProtocolOrBuilder extends com.google.protobuf.MessageOrBuilder { - // required bytes creator = 1; - boolean hasCreator(); - com.google.protobuf.ByteString getCreator(); - - // required string dispatcher = 2; + // required string dispatcher = 1; boolean hasDispatcher(); String getDispatcher(); - // required .DeployProtocol deploy = 3; + // required .DeployProtocol deploy = 2; boolean hasDeploy(); akka.remote.RemoteProtocol.DeployProtocol getDeploy(); akka.remote.RemoteProtocol.DeployProtocolOrBuilder getDeployOrBuilder(); - // optional bytes routerConfig = 4; + // optional string fromClassCreator = 3; + boolean hasFromClassCreator(); + String getFromClassCreator(); + + // optional bytes creator = 4; + boolean hasCreator(); + com.google.protobuf.ByteString getCreator(); + + // optional bytes routerConfig = 5; boolean hasRouterConfig(); com.google.protobuf.ByteString getRouterConfig(); } @@ -5081,21 +5085,11 @@ public final class RemoteProtocol { } private int bitField0_; - // required bytes creator = 1; - public static final int CREATOR_FIELD_NUMBER = 1; - private com.google.protobuf.ByteString creator_; - public boolean hasCreator() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - public com.google.protobuf.ByteString getCreator() { - return creator_; - } - - // required string dispatcher = 2; - public static final int DISPATCHER_FIELD_NUMBER = 2; + // required string dispatcher = 1; + public static final int DISPATCHER_FIELD_NUMBER = 1; private java.lang.Object dispatcher_; public boolean hasDispatcher() { - return ((bitField0_ & 0x00000002) == 0x00000002); + return ((bitField0_ & 0x00000001) == 0x00000001); } public String getDispatcher() { java.lang.Object ref = dispatcher_; @@ -5123,11 +5117,11 @@ public final class RemoteProtocol { } } - // required .DeployProtocol deploy = 3; - public static final int DEPLOY_FIELD_NUMBER = 3; + // required .DeployProtocol deploy = 2; + public static final int DEPLOY_FIELD_NUMBER = 2; private akka.remote.RemoteProtocol.DeployProtocol deploy_; public boolean hasDeploy() { - return ((bitField0_ & 0x00000004) == 0x00000004); + return ((bitField0_ & 0x00000002) == 0x00000002); } public akka.remote.RemoteProtocol.DeployProtocol getDeploy() { return deploy_; @@ -5136,20 +5130,63 @@ public final class RemoteProtocol { return deploy_; } - // optional bytes routerConfig = 4; - public static final int ROUTERCONFIG_FIELD_NUMBER = 4; + // optional string fromClassCreator = 3; + public static final int FROMCLASSCREATOR_FIELD_NUMBER = 3; + private java.lang.Object fromClassCreator_; + public boolean hasFromClassCreator() { + return ((bitField0_ & 0x00000004) == 0x00000004); + } + public String getFromClassCreator() { + java.lang.Object ref = fromClassCreator_; + if (ref instanceof String) { + return (String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + if (com.google.protobuf.Internal.isValidUtf8(bs)) { + fromClassCreator_ = s; + } + return s; + } + } + private com.google.protobuf.ByteString getFromClassCreatorBytes() { + java.lang.Object ref = fromClassCreator_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8((String) ref); + fromClassCreator_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + // optional bytes creator = 4; + public static final int CREATOR_FIELD_NUMBER = 4; + private com.google.protobuf.ByteString creator_; + public boolean hasCreator() { + return ((bitField0_ & 0x00000008) == 0x00000008); + } + public com.google.protobuf.ByteString getCreator() { + return creator_; + } + + // optional bytes routerConfig = 5; + public static final int ROUTERCONFIG_FIELD_NUMBER = 5; private com.google.protobuf.ByteString routerConfig_; public boolean hasRouterConfig() { - return ((bitField0_ & 0x00000008) == 0x00000008); + return ((bitField0_ & 0x00000010) == 0x00000010); } public com.google.protobuf.ByteString getRouterConfig() { return routerConfig_; } private void initFields() { - creator_ = com.google.protobuf.ByteString.EMPTY; dispatcher_ = ""; deploy_ = akka.remote.RemoteProtocol.DeployProtocol.getDefaultInstance(); + fromClassCreator_ = ""; + creator_ = com.google.protobuf.ByteString.EMPTY; routerConfig_ = com.google.protobuf.ByteString.EMPTY; } private byte memoizedIsInitialized = -1; @@ -5157,10 +5194,6 @@ public final class RemoteProtocol { byte isInitialized = memoizedIsInitialized; if (isInitialized != -1) return isInitialized == 1; - if (!hasCreator()) { - memoizedIsInitialized = 0; - return false; - } if (!hasDispatcher()) { memoizedIsInitialized = 0; return false; @@ -5181,16 +5214,19 @@ public final class RemoteProtocol { throws java.io.IOException { getSerializedSize(); if (((bitField0_ & 0x00000001) == 0x00000001)) { - output.writeBytes(1, creator_); + output.writeBytes(1, getDispatcherBytes()); } if (((bitField0_ & 0x00000002) == 0x00000002)) { - output.writeBytes(2, getDispatcherBytes()); + output.writeMessage(2, deploy_); } if (((bitField0_ & 0x00000004) == 0x00000004)) { - output.writeMessage(3, deploy_); + output.writeBytes(3, getFromClassCreatorBytes()); } if (((bitField0_ & 0x00000008) == 0x00000008)) { - output.writeBytes(4, routerConfig_); + output.writeBytes(4, creator_); + } + if (((bitField0_ & 0x00000010) == 0x00000010)) { + output.writeBytes(5, routerConfig_); } getUnknownFields().writeTo(output); } @@ -5203,19 +5239,23 @@ public final class RemoteProtocol { size = 0; if (((bitField0_ & 0x00000001) == 0x00000001)) { size += com.google.protobuf.CodedOutputStream - .computeBytesSize(1, creator_); + .computeBytesSize(1, getDispatcherBytes()); } if (((bitField0_ & 0x00000002) == 0x00000002)) { size += com.google.protobuf.CodedOutputStream - .computeBytesSize(2, getDispatcherBytes()); + .computeMessageSize(2, deploy_); } if (((bitField0_ & 0x00000004) == 0x00000004)) { size += com.google.protobuf.CodedOutputStream - .computeMessageSize(3, deploy_); + .computeBytesSize(3, getFromClassCreatorBytes()); } if (((bitField0_ & 0x00000008) == 0x00000008)) { size += com.google.protobuf.CodedOutputStream - .computeBytesSize(4, routerConfig_); + .computeBytesSize(4, creator_); + } + if (((bitField0_ & 0x00000010) == 0x00000010)) { + size += com.google.protobuf.CodedOutputStream + .computeBytesSize(5, routerConfig_); } size += getUnknownFields().getSerializedSize(); memoizedSerializedSize = size; @@ -5342,18 +5382,20 @@ public final class RemoteProtocol { public Builder clear() { super.clear(); - creator_ = com.google.protobuf.ByteString.EMPTY; - bitField0_ = (bitField0_ & ~0x00000001); dispatcher_ = ""; - bitField0_ = (bitField0_ & ~0x00000002); + bitField0_ = (bitField0_ & ~0x00000001); if (deployBuilder_ == null) { deploy_ = akka.remote.RemoteProtocol.DeployProtocol.getDefaultInstance(); } else { deployBuilder_.clear(); } + bitField0_ = (bitField0_ & ~0x00000002); + fromClassCreator_ = ""; bitField0_ = (bitField0_ & ~0x00000004); - routerConfig_ = com.google.protobuf.ByteString.EMPTY; + creator_ = com.google.protobuf.ByteString.EMPTY; bitField0_ = (bitField0_ & ~0x00000008); + routerConfig_ = com.google.protobuf.ByteString.EMPTY; + bitField0_ = (bitField0_ & ~0x00000010); return this; } @@ -5395,22 +5437,26 @@ public final class RemoteProtocol { if (((from_bitField0_ & 0x00000001) == 0x00000001)) { to_bitField0_ |= 0x00000001; } - result.creator_ = creator_; + result.dispatcher_ = dispatcher_; if (((from_bitField0_ & 0x00000002) == 0x00000002)) { to_bitField0_ |= 0x00000002; } - result.dispatcher_ = dispatcher_; - if (((from_bitField0_ & 0x00000004) == 0x00000004)) { - to_bitField0_ |= 0x00000004; - } if (deployBuilder_ == null) { result.deploy_ = deploy_; } else { result.deploy_ = deployBuilder_.build(); } + if (((from_bitField0_ & 0x00000004) == 0x00000004)) { + to_bitField0_ |= 0x00000004; + } + result.fromClassCreator_ = fromClassCreator_; if (((from_bitField0_ & 0x00000008) == 0x00000008)) { to_bitField0_ |= 0x00000008; } + result.creator_ = creator_; + if (((from_bitField0_ & 0x00000010) == 0x00000010)) { + to_bitField0_ |= 0x00000010; + } result.routerConfig_ = routerConfig_; result.bitField0_ = to_bitField0_; onBuilt(); @@ -5428,15 +5474,18 @@ public final class RemoteProtocol { public Builder mergeFrom(akka.remote.RemoteProtocol.PropsProtocol other) { if (other == akka.remote.RemoteProtocol.PropsProtocol.getDefaultInstance()) return this; - if (other.hasCreator()) { - setCreator(other.getCreator()); - } if (other.hasDispatcher()) { setDispatcher(other.getDispatcher()); } if (other.hasDeploy()) { mergeDeploy(other.getDeploy()); } + if (other.hasFromClassCreator()) { + setFromClassCreator(other.getFromClassCreator()); + } + if (other.hasCreator()) { + setCreator(other.getCreator()); + } if (other.hasRouterConfig()) { setRouterConfig(other.getRouterConfig()); } @@ -5445,10 +5494,6 @@ public final class RemoteProtocol { } public final boolean isInitialized() { - if (!hasCreator()) { - - return false; - } if (!hasDispatcher()) { return false; @@ -5489,15 +5534,10 @@ public final class RemoteProtocol { } case 10: { bitField0_ |= 0x00000001; - creator_ = input.readBytes(); - break; - } - case 18: { - bitField0_ |= 0x00000002; dispatcher_ = input.readBytes(); break; } - case 26: { + case 18: { akka.remote.RemoteProtocol.DeployProtocol.Builder subBuilder = akka.remote.RemoteProtocol.DeployProtocol.newBuilder(); if (hasDeploy()) { subBuilder.mergeFrom(getDeploy()); @@ -5506,8 +5546,18 @@ public final class RemoteProtocol { setDeploy(subBuilder.buildPartial()); break; } + case 26: { + bitField0_ |= 0x00000004; + fromClassCreator_ = input.readBytes(); + break; + } case 34: { bitField0_ |= 0x00000008; + creator_ = input.readBytes(); + break; + } + case 42: { + bitField0_ |= 0x00000010; routerConfig_ = input.readBytes(); break; } @@ -5517,34 +5567,10 @@ public final class RemoteProtocol { private int bitField0_; - // required bytes creator = 1; - private com.google.protobuf.ByteString creator_ = com.google.protobuf.ByteString.EMPTY; - public boolean hasCreator() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - public com.google.protobuf.ByteString getCreator() { - return creator_; - } - public Builder setCreator(com.google.protobuf.ByteString value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000001; - creator_ = value; - onChanged(); - return this; - } - public Builder clearCreator() { - bitField0_ = (bitField0_ & ~0x00000001); - creator_ = getDefaultInstance().getCreator(); - onChanged(); - return this; - } - - // required string dispatcher = 2; + // required string dispatcher = 1; private java.lang.Object dispatcher_ = ""; public boolean hasDispatcher() { - return ((bitField0_ & 0x00000002) == 0x00000002); + return ((bitField0_ & 0x00000001) == 0x00000001); } public String getDispatcher() { java.lang.Object ref = dispatcher_; @@ -5560,29 +5586,29 @@ public final class RemoteProtocol { if (value == null) { throw new NullPointerException(); } - bitField0_ |= 0x00000002; + bitField0_ |= 0x00000001; dispatcher_ = value; onChanged(); return this; } public Builder clearDispatcher() { - bitField0_ = (bitField0_ & ~0x00000002); + bitField0_ = (bitField0_ & ~0x00000001); dispatcher_ = getDefaultInstance().getDispatcher(); onChanged(); return this; } void setDispatcher(com.google.protobuf.ByteString value) { - bitField0_ |= 0x00000002; + bitField0_ |= 0x00000001; dispatcher_ = value; onChanged(); } - // required .DeployProtocol deploy = 3; + // required .DeployProtocol deploy = 2; private akka.remote.RemoteProtocol.DeployProtocol deploy_ = akka.remote.RemoteProtocol.DeployProtocol.getDefaultInstance(); private com.google.protobuf.SingleFieldBuilder< akka.remote.RemoteProtocol.DeployProtocol, akka.remote.RemoteProtocol.DeployProtocol.Builder, akka.remote.RemoteProtocol.DeployProtocolOrBuilder> deployBuilder_; public boolean hasDeploy() { - return ((bitField0_ & 0x00000004) == 0x00000004); + return ((bitField0_ & 0x00000002) == 0x00000002); } public akka.remote.RemoteProtocol.DeployProtocol getDeploy() { if (deployBuilder_ == null) { @@ -5601,7 +5627,7 @@ public final class RemoteProtocol { } else { deployBuilder_.setMessage(value); } - bitField0_ |= 0x00000004; + bitField0_ |= 0x00000002; return this; } public Builder setDeploy( @@ -5612,12 +5638,12 @@ public final class RemoteProtocol { } else { deployBuilder_.setMessage(builderForValue.build()); } - bitField0_ |= 0x00000004; + bitField0_ |= 0x00000002; return this; } public Builder mergeDeploy(akka.remote.RemoteProtocol.DeployProtocol value) { if (deployBuilder_ == null) { - if (((bitField0_ & 0x00000004) == 0x00000004) && + if (((bitField0_ & 0x00000002) == 0x00000002) && deploy_ != akka.remote.RemoteProtocol.DeployProtocol.getDefaultInstance()) { deploy_ = akka.remote.RemoteProtocol.DeployProtocol.newBuilder(deploy_).mergeFrom(value).buildPartial(); @@ -5628,7 +5654,7 @@ public final class RemoteProtocol { } else { deployBuilder_.mergeFrom(value); } - bitField0_ |= 0x00000004; + bitField0_ |= 0x00000002; return this; } public Builder clearDeploy() { @@ -5638,11 +5664,11 @@ public final class RemoteProtocol { } else { deployBuilder_.clear(); } - bitField0_ = (bitField0_ & ~0x00000004); + bitField0_ = (bitField0_ & ~0x00000002); return this; } public akka.remote.RemoteProtocol.DeployProtocol.Builder getDeployBuilder() { - bitField0_ |= 0x00000004; + bitField0_ |= 0x00000002; onChanged(); return getDeployFieldBuilder().getBuilder(); } @@ -5667,10 +5693,70 @@ public final class RemoteProtocol { return deployBuilder_; } - // optional bytes routerConfig = 4; + // optional string fromClassCreator = 3; + private java.lang.Object fromClassCreator_ = ""; + public boolean hasFromClassCreator() { + return ((bitField0_ & 0x00000004) == 0x00000004); + } + public String getFromClassCreator() { + java.lang.Object ref = fromClassCreator_; + if (!(ref instanceof String)) { + String s = ((com.google.protobuf.ByteString) ref).toStringUtf8(); + fromClassCreator_ = s; + return s; + } else { + return (String) ref; + } + } + public Builder setFromClassCreator(String value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000004; + fromClassCreator_ = value; + onChanged(); + return this; + } + public Builder clearFromClassCreator() { + bitField0_ = (bitField0_ & ~0x00000004); + fromClassCreator_ = getDefaultInstance().getFromClassCreator(); + onChanged(); + return this; + } + void setFromClassCreator(com.google.protobuf.ByteString value) { + bitField0_ |= 0x00000004; + fromClassCreator_ = value; + onChanged(); + } + + // optional bytes creator = 4; + private com.google.protobuf.ByteString creator_ = com.google.protobuf.ByteString.EMPTY; + public boolean hasCreator() { + return ((bitField0_ & 0x00000008) == 0x00000008); + } + public com.google.protobuf.ByteString getCreator() { + return creator_; + } + public Builder setCreator(com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000008; + creator_ = value; + onChanged(); + return this; + } + public Builder clearCreator() { + bitField0_ = (bitField0_ & ~0x00000008); + creator_ = getDefaultInstance().getCreator(); + onChanged(); + return this; + } + + // optional bytes routerConfig = 5; private com.google.protobuf.ByteString routerConfig_ = com.google.protobuf.ByteString.EMPTY; public boolean hasRouterConfig() { - return ((bitField0_ & 0x00000008) == 0x00000008); + return ((bitField0_ & 0x00000010) == 0x00000010); } public com.google.protobuf.ByteString getRouterConfig() { return routerConfig_; @@ -5679,13 +5765,13 @@ public final class RemoteProtocol { if (value == null) { throw new NullPointerException(); } - bitField0_ |= 0x00000008; + bitField0_ |= 0x00000010; routerConfig_ = value; onChanged(); return this; } public Builder clearRouterConfig() { - bitField0_ = (bitField0_ & ~0x00000008); + bitField0_ = (bitField0_ & ~0x00000010); routerConfig_ = getDefaultInstance().getRouterConfig(); onChanged(); return this; @@ -6947,17 +7033,17 @@ public final class RemoteProtocol { "\014\n\004port\030\003 \002(\r\"\216\001\n\027DaemonMsgCreateProtoco" + "l\022\035\n\005props\030\001 \002(\0132\016.PropsProtocol\022\037\n\006depl" + "oy\030\002 \002(\0132\017.DeployProtocol\022\014\n\004path\030\003 \002(\t\022" + - "%\n\nsupervisor\030\004 \002(\0132\021.ActorRefProtocol\"k", - "\n\rPropsProtocol\022\017\n\007creator\030\001 \002(\014\022\022\n\ndisp" + - "atcher\030\002 \002(\t\022\037\n\006deploy\030\003 \002(\0132\017.DeployPro" + - "tocol\022\024\n\014routerConfig\030\004 \001(\014\"S\n\016DeployPro" + - "tocol\022\014\n\004path\030\001 \002(\t\022\016\n\006config\030\002 \001(\014\022\024\n\014r" + - "outerConfig\030\003 \001(\014\022\r\n\005scope\030\004 \001(\014\"`\n\026Daem" + - "onMsgWatchProtocol\022\"\n\007watcher\030\001 \002(\0132\021.Ac" + - "torRefProtocol\022\"\n\007watched\030\002 \002(\0132\021.ActorR" + - "efProtocol*7\n\013CommandType\022\013\n\007CONNECT\020\001\022\014" + - "\n\010SHUTDOWN\020\002\022\r\n\tHEARTBEAT\020\003B\017\n\013akka.remo" + - "teH\001" + "%\n\nsupervisor\030\004 \002(\0132\021.ActorRefProtocol\"\205", + "\001\n\rPropsProtocol\022\022\n\ndispatcher\030\001 \002(\t\022\037\n\006" + + "deploy\030\002 \002(\0132\017.DeployProtocol\022\030\n\020fromCla" + + "ssCreator\030\003 \001(\t\022\017\n\007creator\030\004 \001(\014\022\024\n\014rout" + + "erConfig\030\005 \001(\014\"S\n\016DeployProtocol\022\014\n\004path" + + "\030\001 \002(\t\022\016\n\006config\030\002 \001(\014\022\024\n\014routerConfig\030\003" + + " \001(\014\022\r\n\005scope\030\004 \001(\014\"`\n\026DaemonMsgWatchPro" + + "tocol\022\"\n\007watcher\030\001 \002(\0132\021.ActorRefProtoco" + + "l\022\"\n\007watched\030\002 \002(\0132\021.ActorRefProtocol*7\n" + + "\013CommandType\022\013\n\007CONNECT\020\001\022\014\n\010SHUTDOWN\020\002\022" + + "\r\n\tHEARTBEAT\020\003B\017\n\013akka.remoteH\001" }; com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() { @@ -7033,7 +7119,7 @@ public final class RemoteProtocol { internal_static_PropsProtocol_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_PropsProtocol_descriptor, - new java.lang.String[] { "Creator", "Dispatcher", "Deploy", "RouterConfig", }, + new java.lang.String[] { "Dispatcher", "Deploy", "FromClassCreator", "Creator", "RouterConfig", }, akka.remote.RemoteProtocol.PropsProtocol.class, akka.remote.RemoteProtocol.PropsProtocol.Builder.class); internal_static_DeployProtocol_descriptor = diff --git a/akka-remote/src/main/protocol/RemoteProtocol.proto b/akka-remote/src/main/protocol/RemoteProtocol.proto index 7ae11d9cb7..72b04caa57 100644 --- a/akka-remote/src/main/protocol/RemoteProtocol.proto +++ b/akka-remote/src/main/protocol/RemoteProtocol.proto @@ -92,10 +92,11 @@ message DaemonMsgCreateProtocol { * Serialization of akka.actor.Props */ message PropsProtocol { - required bytes creator = 1; - required string dispatcher = 2; - required DeployProtocol deploy = 3; - optional bytes routerConfig = 4; + required string dispatcher = 1; + required DeployProtocol deploy = 2; + optional string fromClassCreator = 3; + optional bytes creator = 4; + optional bytes routerConfig = 5; } /** diff --git a/akka-remote/src/main/scala/akka/serialization/DaemonMsgCreateSerializer.scala b/akka-remote/src/main/scala/akka/serialization/DaemonMsgCreateSerializer.scala index 7bd3124792..ce54ff5adb 100644 --- a/akka-remote/src/main/scala/akka/serialization/DaemonMsgCreateSerializer.scala +++ b/akka-remote/src/main/scala/akka/serialization/DaemonMsgCreateSerializer.scala @@ -5,11 +5,9 @@ package akka.serialization import java.io.Serializable - import com.google.protobuf.ByteString import com.typesafe.config.Config import com.typesafe.config.ConfigFactory - import akka.actor.Actor import akka.actor.ActorRef import akka.actor.Deploy @@ -24,12 +22,14 @@ import akka.remote.RemoteProtocol.DeployProtocol import akka.remote.RemoteProtocol.PropsProtocol import akka.routing.NoRouter import akka.routing.RouterConfig +import akka.actor.FromClassCreator /** * Serializes akka's internal DaemonMsgCreate using protobuf * for the core structure of DaemonMsgCreate, Props and Deploy. - * Serialization of contained RouterConfig, Config, Scope, and creator (scala.Function0) - * is done with configured serializer for those classes, by default java.io.Serializable. + * Serialization of contained RouterConfig, Config, and Scope + * is done with configured serializer for those classes, by + * default java.io.Serializable. */ class DaemonMsgCreateSerializer(val system: ExtendedActorSystem) extends Serializer { import ProtobufSerializer.serializeActorRef @@ -55,9 +55,12 @@ class DaemonMsgCreateSerializer(val system: ExtendedActorSystem) extends Seriali def propsProto = { val builder = PropsProtocol.newBuilder. - setCreator(serialize(props.creator)). setDispatcher(props.dispatcher). setDeploy(deployProto(props.deploy)) + props.creator match { + case FromClassCreator(clazz) ⇒ builder.setFromClassCreator(clazz.getName) + case creator ⇒ builder.setCreator(serialize(creator)) + } if (props.routerConfig != NoRouter) builder.setRouterConfig(serialize(props.routerConfig)) builder.build @@ -92,11 +95,22 @@ class DaemonMsgCreateSerializer(val system: ExtendedActorSystem) extends Seriali } def props = { + val creator = + if (proto.getProps.hasFromClassCreator) { + system.dynamicAccess.getClassFor(proto.getProps.getFromClassCreator) match { + case Right(clazz) ⇒ FromClassCreator(clazz) + case Left(e) ⇒ throw e + } + } else { + deserialize(proto.getProps.getCreator, classOf[() ⇒ Actor]) + } + val routerConfig = if (proto.getProps.hasRouterConfig) deserialize(proto.getProps.getRouterConfig, classOf[RouterConfig]) else NoRouter + Props( - creator = deserialize(proto.getProps.getCreator, classOf[() ⇒ Actor]), + creator = creator, dispatcher = proto.getProps.getDispatcher, routerConfig = routerConfig, deploy = deploy(proto.getProps.getDeploy)) @@ -124,7 +138,6 @@ class DaemonMsgCreateSerializer(val system: ExtendedActorSystem) extends Seriali case Left(e) ⇒ // Fallback to the java serializer, because some interfaces don't implement java.io.Serializable, // but the impl instance does. This could be optimized by adding java serializers in reference.conf: - // scala.Function0 (the creator) // com.typesafe.config.Config // akka.routing.RouterConfig // akka.actor.Scope diff --git a/akka-remote/src/test/scala/akka/serialization/DaemonMsgCreateSerializerSpec.scala b/akka-remote/src/test/scala/akka/serialization/DaemonMsgCreateSerializerSpec.scala index eed2c73d2c..e38a3e1d1f 100644 --- a/akka-remote/src/test/scala/akka/serialization/DaemonMsgCreateSerializerSpec.scala +++ b/akka-remote/src/test/scala/akka/serialization/DaemonMsgCreateSerializerSpec.scala @@ -17,6 +17,7 @@ import akka.remote.RemoteScope import akka.routing.RoundRobinRouter import akka.routing.FromConfig import akka.util.duration._ +import akka.actor.FromClassCreator object DaemonMsgCreateSerializerSpec { class MyActor extends Actor { @@ -39,45 +40,51 @@ class DaemonMsgCreateSerializerSpec extends AkkaSpec { ser.serializerFor(classOf[DaemonMsgCreate]).getClass must be(classOf[DaemonMsgCreateSerializer]) } - "serialize and de-serialize simple DaemonMsgCreate" in { - - val msg = DaemonMsgCreate( - props = Props[MyActor], - deploy = Deploy(), - path = "foo", - supervisor = supervisor) - - val bytes = ser.serialize(msg) match { - case Left(exception) ⇒ fail(exception) - case Right(bytes) ⇒ bytes + "serialize and de-serialize DaemonMsgCreate with FromClassCreator" in { + verifySerialization { + DaemonMsgCreate( + props = Props[MyActor], + deploy = Deploy(), + path = "foo", + supervisor = supervisor) } - ser.deserialize(bytes.asInstanceOf[Array[Byte]], classOf[DaemonMsgCreate]) match { - case Left(exception) ⇒ fail(exception) - case Right(m: DaemonMsgCreate) ⇒ assertDaemonMsgCreate(msg, m) + } + + "serialize and de-serialize DaemonMsgCreate with function creator" in { + verifySerialization { + DaemonMsgCreate( + props = Props().withCreator(new MyActor), + deploy = Deploy(), + path = "foo", + supervisor = supervisor) } } "serialize and de-serialize DaemonMsgCreate with Deploy and RouterConfig" in { - // Duration.Inf doesn't equal Duration.Inf, so we use another for test - val supervisorStrategy = OneForOneStrategy(3, 10 seconds) { - case _ ⇒ SupervisorStrategy.Escalate + verifySerialization { + // Duration.Inf doesn't equal Duration.Inf, so we use another for test + val supervisorStrategy = OneForOneStrategy(3, 10 seconds) { + case _ ⇒ SupervisorStrategy.Escalate + } + val deploy1 = Deploy( + path = "path1", + config = ConfigFactory.parseString("a=1"), + routerConfig = RoundRobinRouter(nrOfInstances = 5, supervisorStrategy = supervisorStrategy), + scope = RemoteScope(Address("akka", "Test", "host1", 1921))) + val deploy2 = Deploy( + path = "path2", + config = ConfigFactory.parseString("a=2"), + routerConfig = FromConfig, + scope = RemoteScope(Address("akka", "Test", "host2", 1922))) + DaemonMsgCreate( + props = Props[MyActor].withDispatcher("my-disp").withDeploy(deploy1), + deploy = deploy2, + path = "foo", + supervisor = supervisor) } - val deploy1 = Deploy( - path = "path1", - config = ConfigFactory.parseString("a=1"), - routerConfig = RoundRobinRouter(nrOfInstances = 5, supervisorStrategy = supervisorStrategy), - scope = RemoteScope(Address("akka", "Test", "host1", 1921))) - val deploy2 = Deploy( - path = "path2", - config = ConfigFactory.parseString("a=2"), - routerConfig = FromConfig, - scope = RemoteScope(Address("akka", "Test", "host2", 1922))) - val msg = DaemonMsgCreate( - props = Props[MyActor].withDispatcher("my-disp").withDeploy(deploy1), - deploy = deploy2, - path = "foo", - supervisor = supervisor) + } + def verifySerialization(msg: DaemonMsgCreate): Unit = { val bytes = ser.serialize(msg) match { case Left(exception) ⇒ fail(exception) case Right(bytes) ⇒ bytes @@ -89,7 +96,9 @@ class DaemonMsgCreateSerializerSpec extends AkkaSpec { } def assertDaemonMsgCreate(expected: DaemonMsgCreate, got: DaemonMsgCreate): Unit = { - // can't compare props.creator + // can't compare props.creator when function + if (expected.props.creator.isInstanceOf[FromClassCreator]) + assert(got.props.creator === expected.props.creator) assert(got.props.dispatcher === expected.props.dispatcher) assert(got.props.dispatcher === expected.props.dispatcher) assert(got.props.routerConfig === expected.props.routerConfig) From b70d7c6227e7294ae16c33873f3f131bf5af8b71 Mon Sep 17 00:00:00 2001 From: Patrik Nordwall Date: Wed, 16 May 2012 09:43:23 +0200 Subject: [PATCH 05/21] Reverted the change to serializeActorRef in DurableMessageSerialization. See #1755 * Discussed with Roland after seeing pull/457 --- .../scala/akka/actor/mailbox/DurableMailbox.scala | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/akka-durable-mailboxes/akka-mailboxes-common/src/main/scala/akka/actor/mailbox/DurableMailbox.scala b/akka-durable-mailboxes/akka-mailboxes-common/src/main/scala/akka/actor/mailbox/DurableMailbox.scala index db7b137bf0..0744215bae 100644 --- a/akka-durable-mailboxes/akka-mailboxes-common/src/main/scala/akka/actor/mailbox/DurableMailbox.scala +++ b/akka-durable-mailboxes/akka-mailboxes-common/src/main/scala/akka/actor/mailbox/DurableMailbox.scala @@ -9,7 +9,6 @@ import akka.remote.MessageSerializer import akka.remote.RemoteProtocol.{ ActorRefProtocol, RemoteMessageProtocol } import com.typesafe.config.Config import akka.actor.ActorSystem -import akka.serialization.Serialization private[akka] object DurableExecutableMailboxConfig { val Name = "[\\.\\/\\$\\s]".r @@ -27,11 +26,13 @@ abstract class DurableMessageQueue(val owner: ActorContext) extends MessageQueue trait DurableMessageSerialization { this: DurableMessageQueue ⇒ - import akka.serialization.ProtobufSerializer.serializeActorRef - import akka.serialization.ProtobufSerializer.deserializeActorRef - def serialize(durableMessage: Envelope): Array[Byte] = { + // It's alright to use ref.path.toString here + // When the sender is a LocalActorRef it should be local when deserialized also. + // When the sender is a RemoteActorRef the path.toString already contains remote address information. + def serializeActorRef(ref: ActorRef): ActorRefProtocol = ActorRefProtocol.newBuilder.setPath(ref.path.toString).build + val message = MessageSerializer.serialize(system, durableMessage.message.asInstanceOf[AnyRef]) val builder = RemoteMessageProtocol.newBuilder .setMessage(message) @@ -43,9 +44,11 @@ trait DurableMessageSerialization { this: DurableMessageQueue ⇒ def deserialize(bytes: Array[Byte]): Envelope = { + def deserializeActorRef(refProtocol: ActorRefProtocol): ActorRef = system.actorFor(refProtocol.getPath) + val durableMessage = RemoteMessageProtocol.parseFrom(bytes) val message = MessageSerializer.deserialize(system, durableMessage.getMessage) - val sender = deserializeActorRef(system, durableMessage.getSender) + val sender = deserializeActorRef(durableMessage.getSender) new Envelope(message, sender)(system) } From 5ca3fe11f87f20b9cd54d3c24df21241c823ec7f Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Wed, 16 May 2012 17:37:23 +0200 Subject: [PATCH 06/21] Adding tons of ScalaDocs for Mailbox.scala --- .../main/scala/akka/dispatch/Mailbox.scala | 49 +++++++++++++++++-- 1 file changed, 44 insertions(+), 5 deletions(-) diff --git a/akka-actor/src/main/scala/akka/dispatch/Mailbox.scala b/akka-actor/src/main/scala/akka/dispatch/Mailbox.scala index 2e3a98e8d9..ba559093d0 100644 --- a/akka-actor/src/main/scala/akka/dispatch/Mailbox.scala +++ b/akka-actor/src/main/scala/akka/dispatch/Mailbox.scala @@ -14,9 +14,15 @@ import akka.actor.ActorContext import com.typesafe.config.Config import akka.actor.ActorSystem +/** + * This exception normally is thrown when a bounded mailbox is over capacity + */ class MessageQueueAppendFailedException(message: String, cause: Throwable = null) extends AkkaException(message, cause) -object Mailbox { +/** + * INTERNAL USE ONLY + */ +private[akka] object Mailbox { type Status = Int @@ -244,6 +250,10 @@ private[akka] abstract class Mailbox(val actor: ActorCell, val messageQueue: Mes } } +/** + * A MessageQueue is one of the core components in forming an Akka Mailbox. + * The MessageQueue is where the normal messages that are sent to Actors will be enqueued (and subsequently dequeued) + */ trait MessageQueue { /** * Try to enqueue the message to this queue, or throw an exception. @@ -277,7 +287,7 @@ trait MessageQueue { } /** - * Internal mailbox implementation detail. + * INTERNAL USE ONLY */ private[akka] trait SystemMessageQueue { /** @@ -294,7 +304,7 @@ private[akka] trait SystemMessageQueue { } /** - * Internal mailbox implementation detail. + * INTERNAL USE ONLY */ private[akka] trait DefaultSystemMessageQueue { self: Mailbox ⇒ @@ -325,6 +335,9 @@ private[akka] trait DefaultSystemMessageQueue { self: Mailbox ⇒ def hasSystemMessages: Boolean = systemQueueGet ne null } +/** + * A QueueBasedMessageQueue is a MessageQueue which is backed by a java.util.Queue + */ trait QueueBasedMessageQueue extends MessageQueue { def queue: Queue[Envelope] def numberOfMessages = queue.size @@ -340,11 +353,18 @@ trait QueueBasedMessageQueue extends MessageQueue { } } +/** + * UnboundedMessageQueueSemantics adds the enqueue/dequeue operations for unbounded java.util.Queues + */ trait UnboundedMessageQueueSemantics extends QueueBasedMessageQueue { def enqueue(receiver: ActorRef, handle: Envelope): Unit = queue add handle def dequeue(): Envelope = queue.poll() } +/** + * BoundedMessageQueueSemantics adds the enqueue/dequeue operations for bounded java.util.Queues, + * and it also forces the java.util.Queue to extend java.util.BlockingQueue + */ trait BoundedMessageQueueSemantics extends QueueBasedMessageQueue { def pushTimeOut: Duration override def queue: BlockingQueue[Envelope] @@ -360,17 +380,27 @@ trait BoundedMessageQueueSemantics extends QueueBasedMessageQueue { def dequeue(): Envelope = queue.poll() } +/** + * DequeBasedMessageQueue forces the underlying java.util.Queue extend java.util.Deque + */ trait DequeBasedMessageQueue extends QueueBasedMessageQueue { def queue: Deque[Envelope] def enqueueFirst(receiver: ActorRef, handle: Envelope): Unit } +/** + * UnboundedMessageQueueSemantics adds the enqueue/dequeue operations for unbounded java.util.Deque + */ trait UnboundedDequeBasedMessageQueueSemantics extends DequeBasedMessageQueue { def enqueue(receiver: ActorRef, handle: Envelope): Unit = queue add handle def enqueueFirst(receiver: ActorRef, handle: Envelope): Unit = queue addFirst handle def dequeue(): Envelope = queue.poll() } +/** + * BoundedMessageQueueSemantics adds the enqueue/dequeue operations for bounded java.util.Deque, + * and it also forces the java.util.Queue to extend java.util.BlockingQueue + */ trait BoundedDequeBasedMessageQueueSemantics extends DequeBasedMessageQueue { def pushTimeOut: Duration override def queue: BlockingDeque[Envelope] @@ -393,14 +423,14 @@ trait BoundedDequeBasedMessageQueueSemantics extends DequeBasedMessageQueue { } /** - * Mailbox configuration. + * MailboxType is used to construct a Messagequeue given an optional ActorContext owner. */ trait MailboxType { def create(owner: Option[ActorContext]): MessageQueue } /** - * It's a case class for Java (new UnboundedMailbox) + * UnboundedMailbox is the standard issue Akka Mailbox as it is unbounded and has quite good performance */ case class UnboundedMailbox() extends MailboxType { @@ -412,6 +442,9 @@ case class UnboundedMailbox() extends MailboxType { } } +/** + * BoundedMailbox is the default bounded mailbox + */ case class BoundedMailbox( final val capacity: Int, final val pushTimeOut: Duration) extends MailboxType { def this(settings: ActorSystem.Settings, config: Config) = this(config.getInt("mailbox-capacity"), @@ -452,6 +485,9 @@ class BoundedPriorityMailbox( final val cmp: Comparator[Envelope], final val cap } } +/** + * This is the default mailbox for Deques, which is unbounded + */ case class UnboundedDequeBasedMailbox() extends MailboxType { def this(settings: ActorSystem.Settings, config: Config) = this() @@ -462,6 +498,9 @@ case class UnboundedDequeBasedMailbox() extends MailboxType { } } +/** + * This is the default mailbox for Deques, which is bounded + */ case class BoundedDequeBasedMailbox( final val capacity: Int, final val pushTimeOut: Duration) extends MailboxType { def this(settings: ActorSystem.Settings, config: Config) = this(config.getInt("mailbox-capacity"), From 58b2af8c09219cc2745814a6231600717111fa2c Mon Sep 17 00:00:00 2001 From: Mirko Friedenhagen Date: Thu, 17 May 2012 22:58:57 +0200 Subject: [PATCH 07/21] Add options for creating epub output for the documentation --- akka-docs/Makefile | 6 ++++++ akka-docs/conf.py | 8 ++++++++ 2 files changed, 14 insertions(+) diff --git a/akka-docs/Makefile b/akka-docs/Makefile index 3c0041537d..c78d5ba317 100644 --- a/akka-docs/Makefile +++ b/akka-docs/Makefile @@ -34,6 +34,7 @@ endif help: @echo "Please use \`make ' where is one of" @echo " pygments to locally install the custom pygments styles" + @echo " epub to make an epub" @echo " html to make standalone HTML files" @echo " singlehtml to make a single large HTML file" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @@ -53,6 +54,11 @@ pygments: $(LOCALPACKAGES): $(MAKE) pygments +epub: $(LOCALPACKAGES) + $(SPHINXBUILD) $(SPHINXFLAGS) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + html: $(LOCALPACKAGES) $(SPHINXBUILD) $(SPHINXFLAGS) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo diff --git a/akka-docs/conf.py b/akka-docs/conf.py index 2e66d8b56c..b632430b59 100644 --- a/akka-docs/conf.py +++ b/akka-docs/conf.py @@ -52,6 +52,14 @@ html_context = { 'include_analytics': 'online' in tags } +# -- Options for EPUB output --------------------------------------------------- +epub_author = "Typesafe Inc" +epub_language = "en" +epub_publisher = epub_author +epub_identifier = "http://doc.akka.io/docs/akka/snapshot/" +epub_scheme = "URL" +epub_cover = ("_sphinx/static/akka.png", "") + # -- Options for LaTeX output -------------------------------------------------- def setup(app): From d65f4bbe595960dc69302bb4cd72931ce5b02ba9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Bone=CC=81r?= Date: Fri, 18 May 2012 10:40:18 +0200 Subject: [PATCH 08/21] Added reference to the NetBeans SBT plugin --- akka-docs/intro/getting-started.rst | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/akka-docs/intro/getting-started.rst b/akka-docs/intro/getting-started.rst index b3bdbf70f3..31d6dc72e6 100644 --- a/akka-docs/intro/getting-started.rst +++ b/akka-docs/intro/getting-started.rst @@ -136,12 +136,17 @@ SBT installation instructions on `https://github.com/harrah/xsbt/wiki/Setup `_ to generate Eclipse project. +Setup SBT project and then use `sbteclipse `_ to generate a Eclipse project. Using Akka with IntelliJ IDEA ----------------------------- -Setup SBT project and then use `sbt-idea `_ to generate IntelliJ IDEA project. +Setup SBT project and then use `sbt-idea `_ to generate a IntelliJ IDEA project. + +Using Akka with NetBeans +------------------------ + +Setup SBT project and then use `sbt-netbeans-plugin `_ to generate a NetBeans project. Build from sources ------------------ From 2278d1fc8edbf63d2de3307d0469873a40d8629f Mon Sep 17 00:00:00 2001 From: Patrik Nordwall Date: Fri, 18 May 2012 11:58:16 +0200 Subject: [PATCH 09/21] ActorSystem.dispatcher should be implicit for easier importability. See #2074 * Makes it more consistent with ActorContext.dispatcher --- akka-actor/src/main/scala/akka/actor/ActorSystem.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/akka-actor/src/main/scala/akka/actor/ActorSystem.scala b/akka-actor/src/main/scala/akka/actor/ActorSystem.scala index b84057b749..20ba0f696e 100644 --- a/akka-actor/src/main/scala/akka/actor/ActorSystem.scala +++ b/akka-actor/src/main/scala/akka/actor/ActorSystem.scala @@ -295,8 +295,9 @@ abstract class ActorSystem extends ActorRefFactory { * Default dispatcher as configured. This dispatcher is used for all actors * in the actor system which do not have a different dispatcher configured * explicitly. + * Importing this member will place the default MessageDispatcher in scope. */ - def dispatcher: MessageDispatcher + implicit def dispatcher: MessageDispatcher /** * Register a block of code (callback) to run after all actors in this actor system have From 877981caef210731ff7a2b93b9a34e6b8aa7aa8f Mon Sep 17 00:00:00 2001 From: Patrik Nordwall Date: Fri, 18 May 2012 13:28:53 +0200 Subject: [PATCH 10/21] DOC: TestKit sample is wrong. See #2072 * Added code to TestKitUsageSpec.scala * Fixed errors * Fixed race --- .../akka/docs/testkit/TestKitUsageSpec.scala | 156 ++++++++++++++++++ akka-docs/scala/testing.rst | 2 + akka-docs/scala/testkit-example.rst | 139 +--------------- 3 files changed, 159 insertions(+), 138 deletions(-) create mode 100644 akka-docs/scala/code/akka/docs/testkit/TestKitUsageSpec.scala diff --git a/akka-docs/scala/code/akka/docs/testkit/TestKitUsageSpec.scala b/akka-docs/scala/code/akka/docs/testkit/TestKitUsageSpec.scala new file mode 100644 index 0000000000..4f6c97abf7 --- /dev/null +++ b/akka-docs/scala/code/akka/docs/testkit/TestKitUsageSpec.scala @@ -0,0 +1,156 @@ +/** + * Copyright (C) 2009-2012 Typesafe Inc. + */ +package akka.docs.testkit + +//#testkit-usage +import scala.util.Random + +import org.scalatest.BeforeAndAfterAll +import org.scalatest.WordSpec +import org.scalatest.matchers.ShouldMatchers + +import com.typesafe.config.ConfigFactory + +import akka.actor.Actor +import akka.actor.ActorRef +import akka.actor.ActorSystem +import akka.actor.Props +import akka.testkit.DefaultTimeout +import akka.testkit.ImplicitSender +import akka.testkit.TestKit +import akka.util.duration._ + +/** + * a Test to show some TestKit examples + */ +class TestKitUsageSpec + extends TestKit(ActorSystem("TestKitUsageSpec", + ConfigFactory.parseString(TestKitUsageSpec.config))) + with DefaultTimeout with ImplicitSender + with WordSpec with ShouldMatchers with BeforeAndAfterAll { + import TestKitUsageSpec._ + + val echoRef = system.actorOf(Props(new EchoActor)) + val forwardRef = system.actorOf(Props(new ForwardingActor(testActor))) + val filterRef = system.actorOf(Props(new FilteringActor(testActor))) + val randomHead = Random.nextInt(6) + val randomTail = Random.nextInt(10) + val headList = List().padTo(randomHead, "0") + val tailList = List().padTo(randomTail, "1") + val seqRef = system.actorOf(Props(new SequencingActor(testActor, headList, tailList))) + + override def afterAll { + system.shutdown() + } + + "An EchoActor" should { + "Respond with the same message it receives" in { + within(500 millis) { + echoRef ! "test" + expectMsg("test") + } + } + } + "A ForwardingActor" should { + "Forward a message it receives" in { + within(500 millis) { + forwardRef ! "test" + expectMsg("test") + } + } + } + "A FilteringActor" should { + "Filter all messages, except expected messagetypes it receives" in { + var messages = List[String]() + within(500 millis) { + filterRef ! "test" + expectMsg("test") + filterRef ! 1 + expectNoMsg + filterRef ! "some" + filterRef ! "more" + filterRef ! 1 + filterRef ! "text" + filterRef ! 1 + + receiveWhile(500 millis) { + case msg: String ⇒ messages = msg :: messages + } + } + messages.length should be(3) + messages.reverse should be(List("some", "more", "text")) + } + } + "A SequencingActor" should { + "receive an interesting message at some point " in { + within(500 millis) { + ignoreMsg { + case msg: String ⇒ msg != "something" + } + seqRef ! "something" + expectMsg("something") + ignoreMsg { + case msg: String ⇒ msg == "1" + } + expectNoMsg + ignoreNoMsg + } + } + } +} + +object TestKitUsageSpec { + // Define your test specific configuration here + val config = """ + akka { + loglevel = "WARNING" + } + """ + + /** + * An Actor that echoes everything you send to it + */ + class EchoActor extends Actor { + def receive = { + case msg ⇒ sender ! msg + } + } + + /** + * An Actor that forwards every message to a next Actor + */ + class ForwardingActor(next: ActorRef) extends Actor { + def receive = { + case msg ⇒ next ! msg + } + } + + /** + * An Actor that only forwards certain messages to a next Actor + */ + class FilteringActor(next: ActorRef) extends Actor { + def receive = { + case msg: String ⇒ next ! msg + case _ ⇒ None + } + } + + /** + * An actor that sends a sequence of messages with a random head list, an + * interesting value and a random tail list. The idea is that you would + * like to test that the interesting value is received and that you cant + * be bothered with the rest + */ + class SequencingActor(next: ActorRef, head: List[String], tail: List[String]) + extends Actor { + def receive = { + case msg ⇒ { + head map (next ! _) + next ! msg + tail map (next ! _) + } + } + } +} +//#testkit-usage \ No newline at end of file diff --git a/akka-docs/scala/testing.rst b/akka-docs/scala/testing.rst index 15f73f4ef0..abb9e0d115 100644 --- a/akka-docs/scala/testing.rst +++ b/akka-docs/scala/testing.rst @@ -194,6 +194,8 @@ is a whole set of examination methods, e.g. receiving all consecutive messages matching certain criteria, receiving a whole sequence of fixed messages or classes, receiving nothing for some time, etc. +The ActorSystem passed in to the constructor of TestKit is accessible with +the the :obj:`system` member. Remember to shut down the actor system after the test is finished (also in case of failure) so that all actors—including the test actor—are stopped. diff --git a/akka-docs/scala/testkit-example.rst b/akka-docs/scala/testkit-example.rst index 54a848d267..7208de5828 100644 --- a/akka-docs/scala/testkit-example.rst +++ b/akka-docs/scala/testkit-example.rst @@ -6,142 +6,5 @@ TestKit Example (Scala) Ray Roestenburg's example code from `his blog `_ adapted to work with Akka 2.x. -.. code-block:: scala +.. includecode:: code/akka/docs/testkit/TestkitUsageSpec.scala#testkit-usage - package unit.akka - - import org.scalatest.matchers.ShouldMatchers - import org.scalatest.{WordSpec, BeforeAndAfterAll} - import akka.actor.Actor._ - import akka.util.duration._ - import akka.testkit.TestKit - import java.util.concurrent.TimeUnit - import akka.actor.{ActorRef, Actor} - import util.Random - - /** - * a Test to show some TestKit examples - */ - - class TestKitUsageSpec extends WordSpec with BeforeAndAfterAll with ShouldMatchers with TestKit { - val system = ActorSystem() - import system._ - val echoRef = actorOf(Props(new EchoActor)) - val forwardRef = actorOf(Props(new ForwardingActor(testActor))) - val filterRef = actorOf(Props(new FilteringActor(testActor))) - val randomHead = Random.nextInt(6) - val randomTail = Random.nextInt(10) - val headList = List().padTo(randomHead, "0") - val tailList = List().padTo(randomTail, "1") - val seqRef = actorOf(Props(new SequencingActor(testActor, headList, tailList))) - - override protected def afterAll(): scala.Unit = { - stopTestActor - echoRef.stop() - forwardRef.stop() - filterRef.stop() - seqRef.stop() - } - - "An EchoActor" should { - "Respond with the same message it receives" in { - within(100 millis) { - echoRef ! "test" - expectMsg("test") - } - } - } - "A ForwardingActor" should { - "Forward a message it receives" in { - within(100 millis) { - forwardRef ! "test" - expectMsg("test") - } - } - } - "A FilteringActor" should { - "Filter all messages, except expected messagetypes it receives" in { - var messages = List[String]() - within(100 millis) { - filterRef ! "test" - expectMsg("test") - filterRef ! 1 - expectNoMsg - filterRef ! "some" - filterRef ! "more" - filterRef ! 1 - filterRef ! "text" - filterRef ! 1 - - receiveWhile(500 millis) { - case msg: String => messages = msg :: messages - } - } - messages.length should be(3) - messages.reverse should be(List("some", "more", "text")) - } - } - "A SequencingActor" should { - "receive an interesting message at some point " in { - within(100 millis) { - seqRef ! "something" - ignoreMsg { - case msg: String => msg != "something" - } - expectMsg("something") - ignoreMsg { - case msg: String => msg == "1" - } - expectNoMsg - } - } - } - } - - /** - * An Actor that echoes everything you send to it - */ - class EchoActor extends Actor { - def receive = { - case msg => { - self.reply(msg) - } - } - } - - /** - * An Actor that forwards every message to a next Actor - */ - class ForwardingActor(next: ActorRef) extends Actor { - def receive = { - case msg => { - next ! msg - } - } - } - - /** - * An Actor that only forwards certain messages to a next Actor - */ - class FilteringActor(next: ActorRef) extends Actor { - def receive = { - case msg: String => { - next ! msg - } - case _ => None - } - } - - /** - * An actor that sends a sequence of messages with a random head list, an interesting value and a random tail list - * The idea is that you would like to test that the interesting value is received and that you cant be bothered with the rest - */ - class SequencingActor(next: ActorRef, head: List[String], tail: List[String]) extends Actor { - def receive = { - case msg => { - head map (next ! _) - next ! msg - tail map (next ! _) - } - } - } From 6c327649908e6d127340076732d7c800f68cee83 Mon Sep 17 00:00:00 2001 From: Patrik Nordwall Date: Fri, 18 May 2012 16:46:31 +0200 Subject: [PATCH 11/21] Embed the source of jmxclient into akka-kernel. See #2079 * Found source code here https://archive-crawler.svn.sourceforge.net * Included org.archive.jmx.Client in akka-kernel * Modified akka-cluster script * Removed dependency to jmxclient from build * Tested from dist with kernel app with cluster settings --- akka-kernel/src/main/dist/bin/akka-cluster | 18 +- .../src/main/java/org/archive/jmx/Client.java | 781 ++++++++++++++++++ project/AkkaBuild.scala | 3 +- 3 files changed, 792 insertions(+), 10 deletions(-) create mode 100644 akka-kernel/src/main/java/org/archive/jmx/Client.java diff --git a/akka-kernel/src/main/dist/bin/akka-cluster b/akka-kernel/src/main/dist/bin/akka-cluster index ecca52fa9b..7bb3a670da 100755 --- a/akka-kernel/src/main/dist/bin/akka-cluster +++ b/akka-kernel/src/main/dist/bin/akka-cluster @@ -3,7 +3,6 @@ # ============== Akka Cluster Administration Tool ============== # # This script is meant to be used from within the Akka distribution. -# Requires setting $AKKA_HOME to the root of the distribution. # # Add these options to the sbt or startup script: # java \ @@ -15,9 +14,12 @@ # FIXME support authentication? if so add: -Dcom.sun.management.jmxremote.password.file= AND tweak this script to support it (arg need 'user:passwd' instead of '-') -# NOTE: The 'cmdline-jmxclient' JAR is available as part of the Akka distribution. -# Provided by Typesafe Maven Repository: http://repo.typesafe.com/typesafe/releases/cmdline-jmxclient. -JMX_CLIENT="java -jar $AKKA_HOME/lib/akka/cmdline-jmxclient-0.10.3.jar -" +declare AKKA_HOME="$(cd "$(cd "$(dirname "$0")"; pwd -P)"/..; pwd)" + +[ -n "$JMX_CLIENT_CLASSPATH" ] || JMX_CLIENT_CLASSPATH="$AKKA_HOME/lib/akka/akka-kernel-*" + +# NOTE: The 'cmdline-jmxclient' is available as part of the Akka distribution. +JMX_CLIENT="java -cp $JMX_CLIENT_CLASSPATH org.archive.jmx.Client -" SELF=`basename $0` # script name HOST=$1 # cluster node:port to talk to through JMX @@ -168,7 +170,7 @@ case "$2" in ;; *) - printf "Usage: $SELF ...\n" + printf "Usage: bin/$SELF ...\n" printf "\n" printf "Supported commands are:\n" printf "%26s - %s\n" "join " "Sends request a JOIN node with the specified URL" @@ -183,9 +185,9 @@ case "$2" in printf "%26s - %s\n" has-convergence "Checks if there is a cluster convergence" printf "Where the should be on the format of 'akka://actor-system-name@hostname:port'\n" printf "\n" - printf "Examples: $SELF localhost:9999 is-available\n" - printf " $SELF localhost:9999 join akka://MySystem@darkstar:2552\n" - printf " $SELF localhost:9999 cluster-status\n" + printf "Examples: bin/$SELF localhost:9999 is-available\n" + printf " bin/$SELF localhost:9999 join akka://MySystem@darkstar:2552\n" + printf " bin/$SELF localhost:9999 cluster-status\n" exit 1 ;; esac diff --git a/akka-kernel/src/main/java/org/archive/jmx/Client.java b/akka-kernel/src/main/java/org/archive/jmx/Client.java new file mode 100644 index 0000000000..136de87ec3 --- /dev/null +++ b/akka-kernel/src/main/java/org/archive/jmx/Client.java @@ -0,0 +1,781 @@ +/* + * Client + * + * $Id$ + * + * Created on Nov 12, 2004 + * + * Copyright (C) 2004 Internet Archive. + * + * This file is part of the Heritrix web crawler (crawler.archive.org). + * + * Heritrix is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * any later version. + * + * Heritrix is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with Heritrix; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package org.archive.jmx; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.text.FieldPosition; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.logging.ConsoleHandler; +import java.util.logging.Handler; +import java.util.logging.LogRecord; +import java.util.logging.Logger; +import java.util.logging.SimpleFormatter; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.management.Attribute; +import javax.management.AttributeList; +import javax.management.InstanceNotFoundException; +import javax.management.IntrospectionException; +import javax.management.MBeanAttributeInfo; +import javax.management.MBeanFeatureInfo; +import javax.management.MBeanInfo; +import javax.management.MBeanOperationInfo; +import javax.management.MBeanParameterInfo; +import javax.management.MBeanServerConnection; +import javax.management.MalformedObjectNameException; +import javax.management.ObjectInstance; +import javax.management.ObjectName; +import javax.management.ReflectionException; +import javax.management.openmbean.CompositeData; +import javax.management.openmbean.TabularData; +import javax.management.remote.JMXConnector; +import javax.management.remote.JMXConnectorFactory; +import javax.management.remote.JMXServiceURL; + + +/** + * A Simple Command-Line JMX Client. + * Tested against the JDK 1.5.0 JMX Agent. + * See Monitoring + * and Management Using JMX. + *

Can supply credentials and do primitive string representation of tabular + * and composite openmbeans. + * @author stack + */ +public class Client { + private static final Logger logger = + Logger.getLogger(Client.class.getName()); + + /** + * Usage string. + */ + private static final String USAGE = "Usage: java -jar" + + " cmdline-jmxclient.jar USER:PASS HOST:PORT [BEAN] [COMMAND]\n" + + "Options:\n" + + " USER:PASS Username and password. Required. If none, pass '-'.\n" + + " E.g. 'controlRole:secret'\n" + + " HOST:PORT Hostname and port to connect to. Required." + + " E.g. localhost:8081.\n" + + " Lists registered beans if only USER:PASS and this" + + " argument.\n" + + " BEAN Optional target bean name. If present we list" + + " available operations\n" + + " and attributes.\n" + + " COMMAND Optional operation to run or attribute to fetch. If" + + " none supplied,\n" + + " all operations and attributes are listed. Attributes" + + " begin with a\n" + + " capital letter: e.g. 'Status' or 'Started'." + + " Operations do not.\n" + + " Operations can take arguments by adding an '=' " + + "followed by\n" + + " comma-delimited params. Pass multiple " + + "attributes/operations to run\n" + + " more than one per invocation. Use commands 'create' and " + + "'destroy'\n" + + " to instantiate and unregister beans ('create' takes name " + + "of class).\n" + + " Pass 'Attributes' to get listing of all attributes and " + + "and their\n" + + " values.\n" + + "Requirements:\n" + + " JDK1.5.0. If connecting to a SUN 1.5.0 JDK JMX Agent, remote side" + + " must be\n" + + " started with system properties such as the following:\n" + + " -Dcom.sun.management.jmxremote.port=PORT\n" + + " -Dcom.sun.management.jmxremote.authenticate=false\n" + + " -Dcom.sun.management.jmxremote.ssl=false\n" + + " The above will start the remote server with no password. See\n" + + " http://java.sun.com/j2se/1.5.0/docs/guide/management/agent.html" + + " for more on\n" + + " 'Monitoring and Management via JMX'.\n" + + "Client Use Examples:\n" + + " To list MBeans on a non-password protected remote agent:\n" + + " % java -jar cmdline-jmxclient-X.X.jar - localhost:8081 \\\n" + + " org.archive.crawler:name=Heritrix,type=Service\n" + + " To list attributes and attributes of the Heritrix MBean:\n" + + " % java -jar cmdline-jmxclient-X.X.jar - localhost:8081 \\\n" + + " org.archive.crawler:name=Heritrix,type=Service \\\n" + + " schedule=http://www.archive.org\n" + + " To set set logging level to FINE on a password protected JVM:\n" + + " % java -jar cmdline-jmxclient-X.X.jar controlRole:secret" + + " localhost:8081 \\\n" + + " java.util.logging:type=Logging \\\n" + + " setLoggerLevel=org.archive.crawler.Heritrix,FINE"; + + /** + * Pattern that matches a command name followed by + * an optional equals and optional comma-delimited list + * of arguments. + */ + protected static final Pattern CMD_LINE_ARGS_PATTERN = + Pattern.compile("^([^=]+)(?:(?:\\=)(.+))?$"); + + private static final String CREATE_CMD_PREFIX = "create="; + + public static void main(String[] args) throws Exception { + Client client = new Client(); + // Set the logger to use our all-on-one-line formatter. + Logger l = Logger.getLogger(""); + Handler [] hs = l.getHandlers(); + for (int i = 0; i < hs.length; i++) { + Handler h = hs[0]; + if (h instanceof ConsoleHandler) { + h.setFormatter(client.new OneLineSimpleLogger()); + } + } + client.execute(args); + } + + protected static void usage() { + usage(0, null); + } + + protected static void usage(int exitCode, String message) { + if (message != null && message.length() > 0) { + System.out.println(message); + } + System.out.println(USAGE); + System.exit(exitCode); + } + + /** + * Constructor. + */ + public Client() { + super(); + } + + /** + * Parse a 'login:password' string. Assumption is that no + * colon in the login name. + * @param userpass + * @return Array of strings with login in first position. + */ + protected String [] parseUserpass(final String userpass) { + if (userpass == null || userpass.equals("-")) { + return null; + } + int index = userpass.indexOf(':'); + if (index <= 0) { + throw new RuntimeException("Unable to parse: " +userpass); + } + return new String [] {userpass.substring(0, index), + userpass.substring(index + 1)}; + } + + /** + * @param login + * @param password + * @return Credentials as map for RMI. + */ + protected Map formatCredentials(final String login, + final String password) { + Map env = null; + String[] creds = new String[] {login, password}; + env = new HashMap(1); + env.put(JMXConnector.CREDENTIALS, creds); + return env; + } + + protected JMXConnector getJMXConnector(final String hostport, + final String login, final String password) + throws IOException { + // Make up the jmx rmi URL and get a connector. + JMXServiceURL rmiurl = new JMXServiceURL("service:jmx:rmi://" + + hostport + "/jndi/rmi://" + hostport + "/jmxrmi"); + return JMXConnectorFactory.connect(rmiurl, + formatCredentials(login, password)); + } + + protected ObjectName getObjectName(final String beanname) + throws MalformedObjectNameException, NullPointerException { + return notEmpty(beanname)? new ObjectName(beanname): null; + } + + /** + * Version of execute called from the cmdline. + * Prints out result of execution on stdout. + * Parses cmdline args. Then calls {@link #execute(String, String, + * String, String, String[], boolean)}. + * @param args Cmdline args. + * @throws Exception + */ + protected void execute(final String [] args) + throws Exception { + // Process command-line. + if (args.length == 0 || args.length == 1) { + usage(); + } + String userpass = args[0]; + String hostport = args[1]; + String beanname = null; + String [] command = null; + if (args.length > 2) { + beanname = args[2]; + } + if (args.length > 3) { + command = new String [args.length - 3]; + for (int i = 3; i < args.length; i++) { + command[i - 3] = args[i]; + } + } + String [] loginPassword = parseUserpass(userpass); + Object [] result = execute(hostport, + ((loginPassword == null)? null: loginPassword[0]), + ((loginPassword == null)? null: loginPassword[1]), beanname, + command); + // Print out results on stdout. Only log if a result. + if (result != null) { + for (int i = 0; i < result.length; i++) { + if (result[i] != null && result[i].toString().length() > 0) { + if (command != null) { + logger.info(command[i] + ": " + result[i]); + } else { + logger.info("\n" + result[i].toString()); + } + } + } + } + } + + protected Object [] execute(final String hostport, final String login, + final String password, final String beanname, + final String [] command) + throws Exception { + return execute(hostport, login, password, beanname, command, false); + } + + public Object [] executeOneCmd(final String hostport, final String login, + final String password, final String beanname, + final String command) + throws Exception { + return execute(hostport, login, password, beanname, + new String[] {command}, true); + } + + /** + * Execute command against remote JMX agent. + * @param hostport 'host:port' combination. + * @param login RMI login to use. + * @param password RMI password to use. + * @param beanname Name of remote bean to run command against. + * @param command Array of commands to run. + * @param oneBeanOnly Set true if passed beanname is + * an exact name and the query for a bean is only supposed to return + * one bean instance. If not, we raise an exception (Otherwise, if false, + * then we deal with possibility of multiple bean instances coming back + * from query). Set to true when want to get an attribute or run an + * operation. + * @return Array of results -- one per command. + * @throws Exception + */ + protected Object [] execute(final String hostport, final String login, + final String password, final String beanname, + final String [] command, final boolean oneBeanOnly) + throws Exception { + JMXConnector jmxc = getJMXConnector(hostport, login, password); + Object [] result = null; + try { + result = doBeans(jmxc.getMBeanServerConnection(), + getObjectName(beanname), command, oneBeanOnly); + } finally { + jmxc.close(); + } + return result; + } + + protected boolean notEmpty(String s) { + return s != null && s.length() > 0; + } + + protected Object [] doBeans(final MBeanServerConnection mbsc, + final ObjectName objName, final String[] command, + final boolean oneBeanOnly) + throws Exception { + Object [] result = null; + Set beans = mbsc.queryMBeans(objName, null); + if (beans.size() == 0) { + // No bean found. Check if we are to create a bean? + if (command.length == 1 && notEmpty(command[0]) + && command[0].startsWith(CREATE_CMD_PREFIX)) { + String className = + command[0].substring(CREATE_CMD_PREFIX.length()); + mbsc.createMBean(className, objName); + } else { + // TODO: Is there a better JMX exception that RE for this + // scenario? + throw new RuntimeException(objName.getCanonicalName() + + " not registered."); + } + } else if (beans.size() == 1) { + result = doBean(mbsc, (ObjectInstance) beans.iterator().next(), + command); + } else { + if (oneBeanOnly) { + throw new RuntimeException("Only supposed to be one bean " + + "query result"); + } + // This is case of multiple beans in query results. + // Print name of each into a StringBuffer. Return as one + // result. + StringBuffer buffer = new StringBuffer(); + for (Iterator i = beans.iterator(); i.hasNext();) { + Object obj = i.next(); + if (obj instanceof ObjectName) { + buffer.append((((ObjectName) obj).getCanonicalName())); + } else if (obj instanceof ObjectInstance) { + buffer.append((((ObjectInstance) obj).getObjectName() + .getCanonicalName())); + } else { + throw new RuntimeException("Unexpected object type: " + obj); + } + buffer.append("\n"); + } + result = new String [] {buffer.toString()}; + } + return result; + } + + /** + * Get attribute or run operation against passed bean instance. + * + * @param mbsc Server connection. + * @param instance Bean instance we're to get attributes from or run + * operation against. + * @param command Command to run (May be null). + * @return Result. If multiple commands, multiple results. + * @throws Exception + */ + protected Object [] doBean(MBeanServerConnection mbsc, + ObjectInstance instance, String [] command) + throws Exception { + // If no command, then print out list of attributes and operations. + if (command == null || command.length <= 0) { + return new String [] {listOptions(mbsc, instance)}; + } + + // Maybe multiple attributes/operations listed on one command line. + Object [] result = new Object[command.length]; + for (int i = 0; i < command.length; i++) { + result[i] = doSubCommand(mbsc, instance, command[i]); + } + return result; + } + + public Object doSubCommand(MBeanServerConnection mbsc, + ObjectInstance instance, String subCommand) + throws Exception { + // First, handle special case of our being asked to destroy a bean. + if (subCommand.equals("destroy")) { + mbsc.unregisterMBean(instance.getObjectName()); + return null; + } else if (subCommand.startsWith(CREATE_CMD_PREFIX)) { + throw new IllegalArgumentException("You cannot call create " + + "on an already existing bean."); + } + + // Get attribute and operation info. + MBeanAttributeInfo [] attributeInfo = + mbsc.getMBeanInfo(instance.getObjectName()).getAttributes(); + MBeanOperationInfo [] operationInfo = + mbsc.getMBeanInfo(instance.getObjectName()).getOperations(); + // Now, bdbje JMX bean doesn't follow the convention of attributes + // having uppercase first letter and operations having lowercase + // first letter. But most beans do. Be prepared to handle the bdbje + // case. + Object result = null; + if (Character.isUpperCase(subCommand.charAt(0))) { + // Probably an attribute. + if (!isFeatureInfo(attributeInfo, subCommand) && + isFeatureInfo(operationInfo, subCommand)) { + // Its not an attribute name. Looks like its name of an + // operation. Try it. + result = + doBeanOperation(mbsc, instance, subCommand, operationInfo); + } else { + // Then it is an attribute OR its not an attribute name nor + // operation name and the below invocation will throw a + // AttributeNotFoundException. + result = doAttributeOperation(mbsc, instance, subCommand, + attributeInfo); + } + } else { + // Must be an operation. + if (!isFeatureInfo(operationInfo, subCommand) && + isFeatureInfo(attributeInfo, subCommand)) { + // Its not an operation name but looks like it could be an + // attribute name. Try it. + result = doAttributeOperation(mbsc, instance, subCommand, + attributeInfo); + } else { + // Its an operation name OR its neither operation nor attribute + // name and the below will throw a NoSuchMethodException. + result = + doBeanOperation(mbsc, instance, subCommand, operationInfo); + } + } + + // Look at the result. Is it of composite or tabular type? + // If so, convert to a String representation. + if (result instanceof CompositeData) { + result = recurseCompositeData(new StringBuffer("\n"), "", "", + (CompositeData)result); + } else if (result instanceof TabularData) { + result = recurseTabularData(new StringBuffer("\n"), "", "", + (TabularData)result); + } else if (result instanceof String []) { + String [] strs = (String [])result; + StringBuffer buffer = new StringBuffer("\n"); + for (int i = 0; i < strs.length; i++) { + buffer.append(strs[i]); + buffer.append("\n"); + } + result = buffer; + } else if (result instanceof AttributeList) { + AttributeList list = (AttributeList)result; + if (list.size() <= 0) { + result = null; + } else { + StringBuffer buffer = new StringBuffer("\n"); + for (Iterator ii = list.iterator(); ii.hasNext();) { + Attribute a = (Attribute)ii.next(); + buffer.append(a.getName()); + buffer.append(": "); + buffer.append(a.getValue()); + buffer.append("\n"); + } + result = buffer; + } + } + return result; + } + + protected boolean isFeatureInfo(MBeanFeatureInfo [] infos, String cmd) { + return getFeatureInfo(infos, cmd) != null; + } + + protected MBeanFeatureInfo getFeatureInfo(MBeanFeatureInfo [] infos, + String cmd) { + // Cmd may be carrying arguments. Don't count them in the compare. + int index = cmd.indexOf('='); + String name = (index > 0)? cmd.substring(0, index): cmd; + for (int i = 0; i < infos.length; i++) { + if (infos[i].getName().equals(name)) { + return infos[i]; + } + } + return null; + } + + protected StringBuffer recurseTabularData(StringBuffer buffer, + String indent, String name, TabularData data) { + addNameToBuffer(buffer, indent, name); + java.util.Collection c = data.values(); + for (Iterator i = c.iterator(); i.hasNext();) { + Object obj = i.next(); + if (obj instanceof CompositeData) { + recurseCompositeData(buffer, indent + " ", "", + (CompositeData)obj); + } else if (obj instanceof TabularData) { + recurseTabularData(buffer, indent, "", + (TabularData)obj); + } else { + buffer.append(obj); + } + } + return buffer; + } + + protected StringBuffer recurseCompositeData(StringBuffer buffer, + String indent, String name, CompositeData data) { + indent = addNameToBuffer(buffer, indent, name); + for (Iterator i = data.getCompositeType().keySet().iterator(); + i.hasNext();) { + String key = (String)i.next(); + Object o = data.get(key); + if (o instanceof CompositeData) { + recurseCompositeData(buffer, indent + " ", key, + (CompositeData)o); + } else if (o instanceof TabularData) { + recurseTabularData(buffer, indent, key, (TabularData)o); + } else { + buffer.append(indent); + buffer.append(key); + buffer.append(": "); + buffer.append(o); + buffer.append("\n"); + } + } + return buffer; + } + + protected String addNameToBuffer(StringBuffer buffer, String indent, + String name) { + if (name == null || name.length() == 0) { + return indent; + } + buffer.append(indent); + buffer.append(name); + buffer.append(":\n"); + // Move all that comes under this 'name' over by one space. + return indent + " "; + } + + /** + * Class that parses commandline arguments. + * Expected format is 'operationName=arg0,arg1,arg2...'. We are assuming no + * spaces nor comma's in argument values. + */ + protected class CommandParse { + private String cmd; + private String [] args; + + protected CommandParse(String command) throws ParseException { + parse(command); + } + + private void parse(String command) throws ParseException { + Matcher m = CMD_LINE_ARGS_PATTERN.matcher(command); + if (m == null || !m.matches()) { + throw new ParseException("Failed parse of " + command, 0); + } + + this.cmd = m.group(1); + if (m.group(2) != null && m.group(2).length() > 0) { + this.args = m.group(2).split(","); + } else { + this.args = null; + } + } + + protected String getCmd() { + return this.cmd; + } + + protected String [] getArgs() { + return this.args; + } + } + + protected Object doAttributeOperation(MBeanServerConnection mbsc, + ObjectInstance instance, String command, MBeanAttributeInfo [] infos) + throws Exception { + // Usually we get attributes. If an argument, then we're being asked + // to set attribute. + CommandParse parse = new CommandParse(command); + if (parse.getArgs() == null || parse.getArgs().length == 0) { + // Special-casing. If the subCommand is 'Attributes', then return + // list of all attributes. + if (command.equals("Attributes")) { + String [] names = new String[infos.length]; + for (int i = 0; i < infos.length; i++) { + names[i] = infos[i].getName(); + } + return mbsc.getAttributes(instance.getObjectName(), names); + } + return mbsc.getAttribute(instance.getObjectName(), parse.getCmd()); + } + if (parse.getArgs().length != 1) { + throw new IllegalArgumentException("One only argument setting " + + "attribute values: " + parse.getArgs()); + } + // Get first attribute of name 'cmd'. Assumption is no method + // overrides. Then, look at the attribute and use its type. + MBeanAttributeInfo info = + (MBeanAttributeInfo)getFeatureInfo(infos, parse.getCmd()); + java.lang.reflect.Constructor c = Class.forName( + info.getType()).getConstructor(new Class[] {String.class}); + Attribute a = new Attribute(parse.getCmd(), + c.newInstance(new Object[] {parse.getArgs()[0]})); + mbsc.setAttribute(instance.getObjectName(), a); + return null; + } + + protected Object doBeanOperation(MBeanServerConnection mbsc, + ObjectInstance instance, String command, MBeanOperationInfo [] infos) + throws Exception { + // Parse command line. + CommandParse parse = new CommandParse(command); + + // Get first method of name 'cmd'. Assumption is no method + // overrides. Then, look at the method and use its signature + // to make sure client sends over parameters of the correct type. + MBeanOperationInfo op = + (MBeanOperationInfo)getFeatureInfo(infos, parse.getCmd()); + Object result = null; + if (op == null) { + result = "Operation " + parse.getCmd() + " not found."; + } else { + MBeanParameterInfo [] paraminfos = op.getSignature(); + int paraminfosLength = (paraminfos == null)? 0: paraminfos.length; + int objsLength = (parse.getArgs() == null)? + 0: parse.getArgs().length; + if (paraminfosLength != objsLength) { + result = "Passed param count does not match signature count"; + } else { + String [] signature = new String[paraminfosLength]; + Object [] params = (paraminfosLength == 0)? null + : new Object[paraminfosLength]; + for (int i = 0; i < paraminfosLength; i++) { + MBeanParameterInfo paraminfo = paraminfos[i]; + java.lang.reflect.Constructor c = Class.forName( + paraminfo.getType()).getConstructor( + new Class[] {String.class}); + params[i] = + c.newInstance(new Object[] {parse.getArgs()[i]}); + signature[i] = paraminfo.getType(); + } + result = mbsc.invoke(instance.getObjectName(), parse.getCmd(), + params, signature); + } + } + return result; + } + + protected String listOptions(MBeanServerConnection mbsc, + ObjectInstance instance) + throws InstanceNotFoundException, IntrospectionException, + ReflectionException, IOException { + StringBuffer result = new StringBuffer(); + MBeanInfo info = mbsc.getMBeanInfo(instance.getObjectName()); + MBeanAttributeInfo [] attributes = info.getAttributes(); + if (attributes.length > 0) { + result.append("Attributes:"); + result.append("\n"); + for (int i = 0; i < attributes.length; i++) { + result.append(' ' + attributes[i].getName() + + ": " + attributes[i].getDescription() + + " (type=" + attributes[i].getType() + + ")"); + result.append("\n"); + } + } + MBeanOperationInfo [] operations = info.getOperations(); + if (operations.length > 0) { + result.append("Operations:"); + result.append("\n"); + for (int i = 0; i < operations.length; i++) { + MBeanParameterInfo [] params = operations[i].getSignature(); + StringBuffer paramsStrBuffer = new StringBuffer(); + if (params != null) { + for (int j = 0; j < params.length; j++) { + paramsStrBuffer.append("\n name="); + paramsStrBuffer.append(params[j].getName()); + paramsStrBuffer.append(" type="); + paramsStrBuffer.append(params[j].getType()); + paramsStrBuffer.append(" "); + paramsStrBuffer.append(params[j].getDescription()); + } + } + result.append(' ' + operations[i].getName() + + ": " + operations[i].getDescription() + + "\n Parameters " + params.length + + ", return type=" + operations[i].getReturnType() + + paramsStrBuffer.toString()); + result.append("\n"); + } + } + return result.toString(); + } + + /** + * Logger that writes entry on one line with less verbose date. + * Modelled on the OneLineSimpleLogger from Heritrix. + * + * @author stack + * @version $Revision$, $Date$ + */ + private class OneLineSimpleLogger extends SimpleFormatter { + /** + * Date instance. + * + * Keep around instance of date. + */ + private Date date = new Date(); + + /** + * Field position instance. + * + * Keep around this instance. + */ + private FieldPosition position = new FieldPosition(0); + + /** + * MessageFormatter for date. + */ + private SimpleDateFormat formatter = + new SimpleDateFormat("MM/dd/yyyy HH:mm:ss Z"); + + /** + * Persistent buffer in which we conjure the log. + */ + private StringBuffer buffer = new StringBuffer(); + + + public OneLineSimpleLogger() { + super(); + } + + public synchronized String format(LogRecord record) { + this.buffer.setLength(0); + this.date.setTime(record.getMillis()); + this.position.setBeginIndex(0); + this.formatter.format(this.date, this.buffer, this.position); + this.buffer.append(' '); + if (record.getSourceClassName() != null) { + this.buffer.append(record.getSourceClassName()); + } else { + this.buffer.append(record.getLoggerName()); + } + this.buffer.append(' '); + this.buffer.append(formatMessage(record)); + this.buffer.append(System.getProperty("line.separator")); + if (record.getThrown() != null) { + try { + StringWriter writer = new StringWriter(); + PrintWriter printer = new PrintWriter(writer); + record.getThrown().printStackTrace(printer); + writer.close(); + this.buffer.append(writer.toString()); + } catch (Exception e) { + this.buffer.append("Failed to get stack trace: " + + e.getMessage()); + } + } + return this.buffer.toString(); + } + } +} \ No newline at end of file diff --git a/project/AkkaBuild.scala b/project/AkkaBuild.scala index 4804c0f796..3b1b84ef77 100644 --- a/project/AkkaBuild.scala +++ b/project/AkkaBuild.scala @@ -380,7 +380,7 @@ object Dependencies { val fileMailbox = Seq(Test.commonsIo, Test.scalatest, Test.junit) - val kernel = Seq(jmxClient, Test.scalatest, Test.junit) + val kernel = Seq(Test.scalatest, Test.junit) val camel = Seq(camelCore, Test.scalatest, Test.junit, Test.mockito) @@ -408,7 +408,6 @@ object Dependency { // Compile val camelCore = "org.apache.camel" % "camel-core" % V.Camel // ApacheV2 - val jmxClient = "cmdline-jmxclient" % "cmdline-jmxclient" % "0.10.3" // LGPL val netty = "io.netty" % "netty" % V.Netty // ApacheV2 val protobuf = "com.google.protobuf" % "protobuf-java" % V.Protobuf // New BSD val scalaStm = "org.scala-tools" % "scala-stm_2.9.1" % V.ScalaStm // Modified BSD (Scala) From 4e2c4955b34095781729b733cf3db296eb41643e Mon Sep 17 00:00:00 2001 From: Patrik Nordwall Date: Sun, 20 May 2012 20:16:06 +0200 Subject: [PATCH 12/21] Changed package to akka.jmx, for OSGi purposes. See #2079 --- akka-kernel/src/main/dist/bin/akka-cluster | 2 +- akka-kernel/src/main/java/{org/archive => akka}/jmx/Client.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename akka-kernel/src/main/java/{org/archive => akka}/jmx/Client.java (99%) diff --git a/akka-kernel/src/main/dist/bin/akka-cluster b/akka-kernel/src/main/dist/bin/akka-cluster index 7bb3a670da..3e76cdbb11 100755 --- a/akka-kernel/src/main/dist/bin/akka-cluster +++ b/akka-kernel/src/main/dist/bin/akka-cluster @@ -19,7 +19,7 @@ declare AKKA_HOME="$(cd "$(cd "$(dirname "$0")"; pwd -P)"/..; pwd)" [ -n "$JMX_CLIENT_CLASSPATH" ] || JMX_CLIENT_CLASSPATH="$AKKA_HOME/lib/akka/akka-kernel-*" # NOTE: The 'cmdline-jmxclient' is available as part of the Akka distribution. -JMX_CLIENT="java -cp $JMX_CLIENT_CLASSPATH org.archive.jmx.Client -" +JMX_CLIENT="java -cp $JMX_CLIENT_CLASSPATH akka.jmx.Client -" SELF=`basename $0` # script name HOST=$1 # cluster node:port to talk to through JMX diff --git a/akka-kernel/src/main/java/org/archive/jmx/Client.java b/akka-kernel/src/main/java/akka/jmx/Client.java similarity index 99% rename from akka-kernel/src/main/java/org/archive/jmx/Client.java rename to akka-kernel/src/main/java/akka/jmx/Client.java index 136de87ec3..9ebf63e9eb 100644 --- a/akka-kernel/src/main/java/org/archive/jmx/Client.java +++ b/akka-kernel/src/main/java/akka/jmx/Client.java @@ -23,7 +23,7 @@ * along with Heritrix; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -package org.archive.jmx; +package akka.jmx; import java.io.IOException; import java.io.PrintWriter; From 6eb8da6eb54c62e05920829089c29f966bfcbef1 Mon Sep 17 00:00:00 2001 From: Patrik Nordwall Date: Sun, 20 May 2012 21:00:13 +0200 Subject: [PATCH 13/21] Minor adjustments from feedback. See #2072 --- .../akka/docs/testkit/TestKitUsageSpec.scala | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/akka-docs/scala/code/akka/docs/testkit/TestKitUsageSpec.scala b/akka-docs/scala/code/akka/docs/testkit/TestKitUsageSpec.scala index 4f6c97abf7..d2b2f9367d 100644 --- a/akka-docs/scala/code/akka/docs/testkit/TestKitUsageSpec.scala +++ b/akka-docs/scala/code/akka/docs/testkit/TestKitUsageSpec.scala @@ -36,8 +36,8 @@ class TestKitUsageSpec val filterRef = system.actorOf(Props(new FilteringActor(testActor))) val randomHead = Random.nextInt(6) val randomTail = Random.nextInt(10) - val headList = List().padTo(randomHead, "0") - val tailList = List().padTo(randomTail, "1") + val headList = Seq().padTo(randomHead, "0") + val tailList = Seq().padTo(randomTail, "1") val seqRef = system.actorOf(Props(new SequencingActor(testActor, headList, tailList))) override def afterAll { @@ -62,7 +62,7 @@ class TestKitUsageSpec } "A FilteringActor" should { "Filter all messages, except expected messagetypes it receives" in { - var messages = List[String]() + var messages = Seq[String]() within(500 millis) { filterRef ! "test" expectMsg("test") @@ -75,11 +75,11 @@ class TestKitUsageSpec filterRef ! 1 receiveWhile(500 millis) { - case msg: String ⇒ messages = msg :: messages + case msg: String ⇒ messages = msg +: messages } } messages.length should be(3) - messages.reverse should be(List("some", "more", "text")) + messages.reverse should be(Seq("some", "more", "text")) } } "A SequencingActor" should { @@ -142,13 +142,13 @@ object TestKitUsageSpec { * like to test that the interesting value is received and that you cant * be bothered with the rest */ - class SequencingActor(next: ActorRef, head: List[String], tail: List[String]) + class SequencingActor(next: ActorRef, head: Seq[String], tail: Seq[String]) extends Actor { def receive = { case msg ⇒ { - head map (next ! _) + head foreach { next ! _ } next ! msg - tail map (next ! _) + tail foreach { next ! _ } } } } From 1e82a231c9afd22a758b858d534981eccd6a280d Mon Sep 17 00:00:00 2001 From: Patrik Nordwall Date: Mon, 21 May 2012 07:46:48 +0200 Subject: [PATCH 14/21] Incorporate review feedback. See #2061 --- .../akka/docs/actor/mailbox/DurableMailboxDocSpec.scala | 8 +++++++- akka-docs/modules/durable-mailbox.rst | 7 ++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/akka-docs/modules/code/akka/docs/actor/mailbox/DurableMailboxDocSpec.scala b/akka-docs/modules/code/akka/docs/actor/mailbox/DurableMailboxDocSpec.scala index 25f312cac3..c81f16e896 100644 --- a/akka-docs/modules/code/akka/docs/actor/mailbox/DurableMailboxDocSpec.scala +++ b/akka-docs/modules/code/akka/docs/actor/mailbox/DurableMailboxDocSpec.scala @@ -73,13 +73,19 @@ class MyMessageQueue(_owner: ActorContext) def dequeue(): Envelope = { val data: Option[Array[Byte]] = storage.pull() - data.map(deserialize(_)).getOrElse(null) + data.map(deserialize).orNull } def hasMessages: Boolean = !storage.isEmpty def numberOfMessages: Int = storage.size + /** + * Called when the mailbox is disposed. + * An ordinary mailbox would send remaining messages to deadLetters, + * but the purpose of a durable mailbox is to continue + * with the same message queue when the actor is started again. + */ def cleanUp(owner: ActorContext, deadLetters: MessageQueue): Unit = () } diff --git a/akka-docs/modules/durable-mailbox.rst b/akka-docs/modules/durable-mailbox.rst index 4de60ea12b..aca9d51eb5 100644 --- a/akka-docs/modules/durable-mailbox.rst +++ b/akka-docs/modules/durable-mailbox.rst @@ -9,7 +9,7 @@ Overview ======== -A durable mailbox is a replacement for the standard actor mailbox that is durable. +A durable mailbox is a mailbox which stores the messages on durable storage. What this means in practice is that if there are pending messages in the actor's mailbox when the node of the actor resides on crashes, then when you restart the node, the actor will be able to continue processing as if nothing had happened; @@ -29,7 +29,7 @@ Open Source projects, such as: * `AMQP Durable Mailbox `_ -A durable mailbox typically doesn't implements transactions for current message. It's possible +A durable mailbox is like any other mailbox not likely to be transactional. It's possible if the actor crashes after receiving a message, but before completing processing of it, that the message could be lost. @@ -98,4 +98,5 @@ Add this dependency:: "com.typesafe.akka" % "akka-mailboxes-common-test" % "2.1-SNAPSHOT" For more inspiration you can look at the old implementations based on Redis, MongoDB, Beanstalk, -and ZooKeeper, which can be found in Akka git repository tag v2.0.1. \ No newline at end of file +and ZooKeeper, which can be found in Akka git repository tag +`v2.0.1 `_. \ No newline at end of file From 7784513537df669f048484feea900963fc1a9cb1 Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Mon, 21 May 2012 13:39:39 +0200 Subject: [PATCH 15/21] Fixing logic bug introduced in refactor --- .../src/main/scala/akka/dispatch/BalancingDispatcher.scala | 2 +- akka-actor/src/main/scala/akka/dispatch/Dispatcher.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/akka-actor/src/main/scala/akka/dispatch/BalancingDispatcher.scala b/akka-actor/src/main/scala/akka/dispatch/BalancingDispatcher.scala index dea29643c7..43e8944105 100644 --- a/akka-actor/src/main/scala/akka/dispatch/BalancingDispatcher.scala +++ b/akka-actor/src/main/scala/akka/dispatch/BalancingDispatcher.scala @@ -87,7 +87,7 @@ class BalancingDispatcher( @tailrec def scheduleOne(i: Iterator[ActorCell] = team.iterator): Unit = if (messageQueue.hasMessages && i.hasNext - && (executorService match { + && (executorService.executor match { case lm: LoadMetrics ⇒ lm.atFullThrottle == false case other ⇒ true }) diff --git a/akka-actor/src/main/scala/akka/dispatch/Dispatcher.scala b/akka-actor/src/main/scala/akka/dispatch/Dispatcher.scala index c8ae187c66..3c17ab8db4 100644 --- a/akka-actor/src/main/scala/akka/dispatch/Dispatcher.scala +++ b/akka-actor/src/main/scala/akka/dispatch/Dispatcher.scala @@ -41,7 +41,7 @@ class Dispatcher( @volatile private var executorServiceDelegate: LazyExecutorServiceDelegate = new LazyExecutorServiceDelegate(executorServiceFactoryProvider.createExecutorServiceFactory(id, prerequisites.threadFactory)) - protected final def executorService: ExecutorService = executorServiceDelegate + protected final def executorService: ExecutorServiceDelegate = executorServiceDelegate /** * INTERNAL USE ONLY From e14f9d01304db0fc42a96f641d6107ab48ee57ee Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Mon, 21 May 2012 13:40:14 +0200 Subject: [PATCH 16/21] Switching to indexOf instead of Seq.contains --- akka-actor/src/main/scala/akka/actor/ActorSelection.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/akka-actor/src/main/scala/akka/actor/ActorSelection.scala b/akka-actor/src/main/scala/akka/actor/ActorSelection.scala index 44767cb0b6..93a26c6289 100644 --- a/akka-actor/src/main/scala/akka/actor/ActorSelection.scala +++ b/akka-actor/src/main/scala/akka/actor/ActorSelection.scala @@ -52,7 +52,7 @@ object ActorSelection { */ def apply(anchor: ActorRef, path: String): ActorSelection = { val elems = path.split("/+").dropWhile(_.isEmpty) - val compiled: Array[AnyRef] = elems map (x ⇒ if (x.contains('?') || x.contains('*')) Helpers.makePattern(x) else x) + val compiled: Array[AnyRef] = elems map (x ⇒ if ((x.indexOf('?') != -1) || (x.indexOf('*') != -1)) Helpers.makePattern(x) else x) new ActorSelection with ScalaActorSelection { def target = anchor def path = compiled From 26f6c48ae1c5642b8fb4752829211e16bc0e7762 Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Mon, 21 May 2012 13:47:48 +0200 Subject: [PATCH 17/21] HUGE CHANGE - moving behaviorStack into ActorCell --- .../test/scala/akka/actor/ActorRefSpec.scala | 2 +- .../scala/akka/actor/ActorWithStashSpec.scala | 2 +- .../test/scala/akka/actor/FSMActorSpec.scala | 2 +- .../scala/akka/actor/ReceiveTimeoutSpec.scala | 8 ++-- .../akka/actor/RestartStrategySpec.scala | 10 ++-- .../akka/actor/SupervisorHierarchySpec.scala | 4 +- .../scala/akka/actor/SupervisorMiscSpec.scala | 2 +- .../akka/actor/dispatch/ActorModelSpec.scala | 4 +- .../src/main/scala/akka/actor/Actor.scala | 45 ++---------------- .../src/main/scala/akka/actor/ActorCell.scala | 29 +++++++---- .../src/main/scala/akka/actor/ActorPath.scala | 4 +- .../src/main/scala/akka/actor/ActorRef.scala | 10 ++-- .../src/main/scala/akka/actor/FSM.scala | 2 +- .../main/scala/akka/actor/FaultHandling.scala | 7 +-- akka-actor/src/main/scala/akka/actor/IO.scala | 2 +- .../src/main/scala/akka/actor/Scheduler.scala | 2 +- .../main/scala/akka/actor/UntypedActor.scala | 2 +- .../src/main/scala/akka/camel/Producer.scala | 2 +- .../akka/camelexamples/ExamplesSupport.scala | 6 +-- .../_2_SupervisedConsumers.scala | 4 +- .../akka/camel/ProducerFeatureTest.scala | 4 +- .../component/ActorProducerTest.scala | 2 +- akka-docs/scala/actors.rst | 2 +- .../scala/akka/testkit/TestActorRef.scala | 2 +- .../zeromq/ConcurrentSocketActorSpec.scala | 2 +- file-based/mailbox_user__a | 0 file-based/mailbox_user__b | 0 file-based/mailbox_user__c | Bin 12892 -> 0 bytes file-based/mailbox_user__d | Bin 703 -> 0 bytes file-based/mailbox_user__e | Bin 703 -> 0 bytes file-based/mailbox_user__f | Bin 703 -> 0 bytes 31 files changed, 71 insertions(+), 90 deletions(-) delete mode 100644 file-based/mailbox_user__a delete mode 100644 file-based/mailbox_user__b delete mode 100644 file-based/mailbox_user__c delete mode 100644 file-based/mailbox_user__d delete mode 100644 file-based/mailbox_user__e delete mode 100644 file-based/mailbox_user__f diff --git a/akka-actor-tests/src/test/scala/akka/actor/ActorRefSpec.scala b/akka-actor-tests/src/test/scala/akka/actor/ActorRefSpec.scala index e8c667bc7e..bec066d97a 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/ActorRefSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/ActorRefSpec.scala @@ -393,7 +393,7 @@ class ActorRefSpec extends AkkaSpec with DefaultTimeout { override def postRestart(reason: Throwable) = latch.countDown() })) - protected def receive = { case "sendKill" ⇒ ref ! Kill } + def receive = { case "sendKill" ⇒ ref ! Kill } })) boss ! "sendKill" diff --git a/akka-actor-tests/src/test/scala/akka/actor/ActorWithStashSpec.scala b/akka-actor-tests/src/test/scala/akka/actor/ActorWithStashSpec.scala index c516a17a42..524913b01d 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/ActorWithStashSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/ActorWithStashSpec.scala @@ -131,7 +131,7 @@ class ActorWithStashSpec extends AkkaSpec(ActorWithStashSpec.testConf) with Defa val hasMsgLatch = new TestLatch val slaveProps = myProps(new Actor with Stash { - protected def receive = { + def receive = { case "crash" ⇒ throw new Exception("Crashing...") diff --git a/akka-actor-tests/src/test/scala/akka/actor/FSMActorSpec.scala b/akka-actor-tests/src/test/scala/akka/actor/FSMActorSpec.scala index ef49cbc18d..cc98a23f1f 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/FSMActorSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/FSMActorSpec.scala @@ -147,7 +147,7 @@ class FSMActorSpec extends AkkaSpec(Map("akka.actor.debug.fsm" -> true)) with Im object Hello object Bye val tester = system.actorOf(Props(new Actor { - protected def receive = { + def receive = { case Hello ⇒ lock ! "hello" case "world" ⇒ answerLatch.open case Bye ⇒ lock ! "bye" diff --git a/akka-actor-tests/src/test/scala/akka/actor/ReceiveTimeoutSpec.scala b/akka-actor-tests/src/test/scala/akka/actor/ReceiveTimeoutSpec.scala index dc08df1c98..09fe9c103f 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/ReceiveTimeoutSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/ReceiveTimeoutSpec.scala @@ -22,7 +22,7 @@ class ReceiveTimeoutSpec extends AkkaSpec { val timeoutActor = system.actorOf(Props(new Actor { context.setReceiveTimeout(500 milliseconds) - protected def receive = { + def receive = { case ReceiveTimeout ⇒ timeoutLatch.open } })) @@ -38,7 +38,7 @@ class ReceiveTimeoutSpec extends AkkaSpec { val timeoutActor = system.actorOf(Props(new Actor { context.setReceiveTimeout(500 milliseconds) - protected def receive = { + def receive = { case Tick ⇒ () case ReceiveTimeout ⇒ timeoutLatch.open } @@ -58,7 +58,7 @@ class ReceiveTimeoutSpec extends AkkaSpec { val timeoutActor = system.actorOf(Props(new Actor { context.setReceiveTimeout(500 milliseconds) - protected def receive = { + def receive = { case Tick ⇒ () case ReceiveTimeout ⇒ count.incrementAndGet @@ -78,7 +78,7 @@ class ReceiveTimeoutSpec extends AkkaSpec { val timeoutLatch = TestLatch() val timeoutActor = system.actorOf(Props(new Actor { - protected def receive = { + def receive = { case ReceiveTimeout ⇒ timeoutLatch.open } })) diff --git a/akka-actor-tests/src/test/scala/akka/actor/RestartStrategySpec.scala b/akka-actor-tests/src/test/scala/akka/actor/RestartStrategySpec.scala index 829ab081e0..8d114bc396 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/RestartStrategySpec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/RestartStrategySpec.scala @@ -40,7 +40,7 @@ class RestartStrategySpec extends AkkaSpec with DefaultTimeout { val slaveProps = Props(new Actor { - protected def receive = { + def receive = { case Ping ⇒ countDownLatch.countDown() case Crash ⇒ throw new Exception("Crashing...") } @@ -83,7 +83,7 @@ class RestartStrategySpec extends AkkaSpec with DefaultTimeout { val slaveProps = Props(new Actor { - protected def receive = { + def receive = { case Crash ⇒ throw new Exception("Crashing...") } @@ -110,7 +110,7 @@ class RestartStrategySpec extends AkkaSpec with DefaultTimeout { val slaveProps = Props(new Actor { - protected def receive = { + def receive = { case Ping ⇒ if (!pingLatch.isOpen) pingLatch.open else secondPingLatch.open case Crash ⇒ throw new Exception("Crashing...") @@ -166,7 +166,7 @@ class RestartStrategySpec extends AkkaSpec with DefaultTimeout { val slaveProps = Props(new Actor { - protected def receive = { + def receive = { case Ping ⇒ countDownLatch.countDown() case Crash ⇒ throw new Exception("Crashing...") } @@ -221,7 +221,7 @@ class RestartStrategySpec extends AkkaSpec with DefaultTimeout { val slaveProps = Props(new Actor { - protected def receive = { + def receive = { case Ping ⇒ countDownLatch.countDown() case Crash ⇒ throw new Exception("Crashing...") } diff --git a/akka-actor-tests/src/test/scala/akka/actor/SupervisorHierarchySpec.scala b/akka-actor-tests/src/test/scala/akka/actor/SupervisorHierarchySpec.scala index a04e83f39b..62752d8052 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/SupervisorHierarchySpec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/SupervisorHierarchySpec.scala @@ -20,7 +20,7 @@ object SupervisorHierarchySpec { */ class CountDownActor(countDown: CountDownLatch, override val supervisorStrategy: SupervisorStrategy) extends Actor { - protected def receive = { + def receive = { case p: Props ⇒ sender ! context.actorOf(p) } // test relies on keeping children around during restart @@ -67,7 +67,7 @@ class SupervisorHierarchySpec extends AkkaSpec with DefaultTimeout { val crasher = context.watch(context.actorOf(Props(new CountDownActor(countDownMessages, SupervisorStrategy.defaultStrategy)))) - protected def receive = { + def receive = { case "killCrasher" ⇒ crasher ! Kill case Terminated(_) ⇒ countDownMax.countDown() } diff --git a/akka-actor-tests/src/test/scala/akka/actor/SupervisorMiscSpec.scala b/akka-actor-tests/src/test/scala/akka/actor/SupervisorMiscSpec.scala index 92af540a9a..197e749d2e 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/SupervisorMiscSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/SupervisorMiscSpec.scala @@ -37,7 +37,7 @@ class SupervisorMiscSpec extends AkkaSpec(SupervisorMiscSpec.config) with Defaul val workerProps = Props(new Actor { override def postRestart(cause: Throwable) { countDownLatch.countDown() } - protected def receive = { + def receive = { case "status" ⇒ this.sender ! "OK" case _ ⇒ this.context.stop(self) } diff --git a/akka-actor-tests/src/test/scala/akka/actor/dispatch/ActorModelSpec.scala b/akka-actor-tests/src/test/scala/akka/actor/dispatch/ActorModelSpec.scala index 88358e9f16..854a562745 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/dispatch/ActorModelSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/dispatch/ActorModelSpec.scala @@ -400,9 +400,9 @@ abstract class ActorModelSpec(config: String) extends AkkaSpec(config) with Defa val a = newTestActor(dispatcher.id) val f1 = a ? Reply("foo") val f2 = a ? Reply("bar") - val f3 = try { a ? Interrupt } catch { case ie: InterruptedException ⇒ Promise.failed(ActorInterruptedException(ie)) } + val f3 = try { a ? Interrupt } catch { case ie: InterruptedException ⇒ Promise.failed(new ActorInterruptedException(ie)) } val f4 = a ? Reply("foo2") - val f5 = try { a ? Interrupt } catch { case ie: InterruptedException ⇒ Promise.failed(ActorInterruptedException(ie)) } + val f5 = try { a ? Interrupt } catch { case ie: InterruptedException ⇒ Promise.failed(new ActorInterruptedException(ie)) } val f6 = a ? Reply("bar2") assert(Await.result(f1, timeout.duration) === "foo") diff --git a/akka-actor/src/main/scala/akka/actor/Actor.scala b/akka-actor/src/main/scala/akka/actor/Actor.scala index 7c020925eb..b26da76ff2 100644 --- a/akka-actor/src/main/scala/akka/actor/Actor.scala +++ b/akka-actor/src/main/scala/akka/actor/Actor.scala @@ -152,7 +152,7 @@ case class DeathPactException private[akka] (dead: ActorRef) * When an InterruptedException is thrown inside an Actor, it is wrapped as an ActorInterruptedException as to * avoid cascading interrupts to other threads than the originally interrupted one. */ -case class ActorInterruptedException private[akka] (cause: Throwable) extends AkkaException(cause.getMessage, cause) with NoStackTrace +class ActorInterruptedException private[akka] (cause: Throwable) extends AkkaException(cause.getMessage, cause) with NoStackTrace /** * This message is published to the EventStream whenever an Actor receives a message it doesn't understand @@ -173,6 +173,7 @@ object Status { /** * This class/message type is preferably used to indicate failure of some operation performed. + * As an example, it is used to signal failure with AskSupport is used (ask/?). */ case class Failure(cause: Throwable) extends Status } @@ -317,7 +318,7 @@ trait Actor { * This defines the initial actor behavior, it must return a partial function * with the actor logic. */ - protected def receive: Receive + def receive: Receive /** * User overridable definition the strategy to use for supervising @@ -377,45 +378,5 @@ trait Actor { case _ ⇒ context.system.eventStream.publish(UnhandledMessage(message, sender, self)) } } - - // ========================================= - // ==== INTERNAL IMPLEMENTATION DETAILS ==== - // ========================================= - - /** - * For Akka internal use only. - */ - private[akka] final def apply(msg: Any) = { - //FIXME replace with behaviorStack.head.applyOrElse(msg, unhandled) + "-optimize" - val head = behaviorStack.head - if (head.isDefinedAt(msg)) head.apply(msg) else unhandled(msg) - } - - /** - * For Akka internal use only. - */ - private[akka] def pushBehavior(behavior: Receive): Unit = { - behaviorStack = behaviorStack.push(behavior) - } - - /** - * For Akka internal use only. - */ - private[akka] def popBehavior(): Unit = { - val original = behaviorStack - val popped = original.pop - behaviorStack = if (popped.isEmpty) original else popped - } - - /** - * For Akka internal use only. - */ - private[akka] def clearBehaviorStack(): Unit = - behaviorStack = Stack.empty[Receive].push(behaviorStack.last) - - /** - * For Akka internal use only. - */ - private var behaviorStack: Stack[Receive] = Stack.empty[Receive].push(receive) } diff --git a/akka-actor/src/main/scala/akka/actor/ActorCell.scala b/akka-actor/src/main/scala/akka/actor/ActorCell.scala index bd5342fec4..6a25ac04a9 100644 --- a/akka-actor/src/main/scala/akka/actor/ActorCell.scala +++ b/akka-actor/src/main/scala/akka/actor/ActorCell.scala @@ -409,6 +409,8 @@ private[akka] class ActorCell( var actor: Actor = _ + private var behaviorStack: Stack[Actor.Receive] = Stack.empty + @volatile //This must be volatile since it isn't protected by the mailbox status var mailbox: Mailbox = _ @@ -489,8 +491,7 @@ private[akka] class ActorCell( //This method is in charge of setting up the contextStack and create a new instance of the Actor protected def newActor(): Actor = { - val stackBefore = contextStack.get - contextStack.set(stackBefore.push(this)) + contextStack.set(contextStack.get.push(this)) try { val instance = props.creator() @@ -511,6 +512,7 @@ private[akka] class ActorCell( def create(): Unit = if (isNormal) { try { val created = newActor() + behaviorStack = Stack.empty.push(created.receive) actor = created created.preStart() checkReceiveTimeout @@ -612,7 +614,7 @@ private[akka] class ActorCell( cancelReceiveTimeout() // FIXME: leave this here??? messageHandle.message match { case msg: AutoReceivedMessage ⇒ autoReceiveMessage(messageHandle) - case msg ⇒ actor(msg) + case msg ⇒ receiveMessage(msg) } currentMessage = null // reset current message after successful invocation } catch { @@ -628,14 +630,14 @@ private[akka] class ActorCell( if (actor ne null) actor.supervisorStrategy.handleSupervisorFailing(self, children) } finally { t match { // Wrap InterruptedExceptions and rethrow - case _: InterruptedException ⇒ parent.tell(Failed(ActorInterruptedException(t)), self); throw t + case _: InterruptedException ⇒ parent.tell(Failed(new ActorInterruptedException(t)), self); throw t case _ ⇒ parent.tell(Failed(t), self) } } def become(behavior: Actor.Receive, discardOld: Boolean = true): Unit = { if (discardOld) unbecome() - actor.pushBehavior(behavior) + behaviorStack = behaviorStack.push(behavior) } /** @@ -651,9 +653,13 @@ private[akka] class ActorCell( become(newReceive, discardOld) } - def unbecome(): Unit = actor.popBehavior() + def unbecome(): Unit = { + val original = behaviorStack + val popped = original.pop + behaviorStack = if (popped.isEmpty) original else popped + } - def autoReceiveMessage(msg: Envelope) { + def autoReceiveMessage(msg: Envelope): Unit = { if (system.settings.DebugAutoReceive) system.eventStream.publish(Debug(self.path.toString, clazz(actor), "received AutoReceiveMessage " + msg)) @@ -667,6 +673,12 @@ private[akka] class ActorCell( } } + final def receiveMessage(msg: Any): Unit = { + //FIXME replace with behaviorStack.head.applyOrElse(msg, unhandled) + "-optimize" + val head = behaviorStack.head + if (head.isDefinedAt(msg)) head.apply(msg) else actor.unhandled(msg) + } + private def doTerminate() { val a = actor try { @@ -682,7 +694,7 @@ private[akka] class ActorCell( if (system.settings.DebugLifecycle) system.eventStream.publish(Debug(self.path.toString, clazz(actor), "stopped")) } finally { - if (a ne null) a.clearBehaviorStack() + behaviorStack = Stack.empty clearActorFields(a) actor = null } @@ -694,6 +706,7 @@ private[akka] class ActorCell( actor.supervisorStrategy.handleSupervisorRestarted(cause, self, children) val freshActor = newActor() + behaviorStack = Stack.empty.push(freshActor.receive) actor = freshActor // this must happen before postRestart has a chance to fail if (freshActor eq failedActor) setActorFields(freshActor, this, self) // If the creator returns the same instance, we need to restore our nulled out fields. diff --git a/akka-actor/src/main/scala/akka/actor/ActorPath.scala b/akka-actor/src/main/scala/akka/actor/ActorPath.scala index e8c277660f..aa93dbcc47 100644 --- a/akka-actor/src/main/scala/akka/actor/ActorPath.scala +++ b/akka-actor/src/main/scala/akka/actor/ActorPath.scala @@ -15,7 +15,9 @@ object ActorPath { } /** - * This Regular Expression is used to validate a path element (Actor Name) + * This Regular Expression is used to validate a path element (Actor Name). + * Since Actors form a tree, it is addressable using an URL, therefor an Actor Name has to conform to: + * http://www.ietf.org/rfc/rfc2396.txt */ val ElementRegex = """[-\w:@&=+,.!~*'_;][-\w:@&=+,.!~*'$_;]*""".r } diff --git a/akka-actor/src/main/scala/akka/actor/ActorRef.scala b/akka-actor/src/main/scala/akka/actor/ActorRef.scala index d0ad270957..46e3440f95 100644 --- a/akka-actor/src/main/scala/akka/actor/ActorRef.scala +++ b/akka-actor/src/main/scala/akka/actor/ActorRef.scala @@ -335,9 +335,10 @@ private[akka] class LocalActorRef private[akka] ( /** * Memento pattern for serializing ActorRefs transparently + * INTERNAL API */ //TODO add @SerialVersionUID(1L) when SI-4804 is fixed -case class SerializedActorRef private (path: String) { +private[akka] case class SerializedActorRef private (path: String) { import akka.serialization.JavaSerializer.currentSystem @throws(classOf[java.io.ObjectStreamException]) @@ -350,8 +351,11 @@ case class SerializedActorRef private (path: String) { someSystem.actorFor(path) } } -//FIXME: Should SerializedActorRef be private[akka] ? -object SerializedActorRef { + +/** + * INTERNAL API + */ +private[akka] object SerializedActorRef { def apply(path: ActorPath): SerializedActorRef = { Serialization.currentTransportAddress.value match { case null ⇒ new SerializedActorRef(path.toString) diff --git a/akka-actor/src/main/scala/akka/actor/FSM.scala b/akka-actor/src/main/scala/akka/actor/FSM.scala index 71d1ec7e69..762f23b16b 100644 --- a/akka-actor/src/main/scala/akka/actor/FSM.scala +++ b/akka-actor/src/main/scala/akka/actor/FSM.scala @@ -437,7 +437,7 @@ trait FSM[S, D] extends Listeners with ActorLogging { * Main actor receive() method * ******************************************* */ - override final protected def receive: Receive = { + override final def receive: Receive = { case TimeoutMarker(gen) ⇒ if (generation == gen) { processMsg(StateTimeout, "state timeout") diff --git a/akka-actor/src/main/scala/akka/actor/FaultHandling.scala b/akka-actor/src/main/scala/akka/actor/FaultHandling.scala index 383010f9de..8641153476 100644 --- a/akka-actor/src/main/scala/akka/actor/FaultHandling.scala +++ b/akka-actor/src/main/scala/akka/actor/FaultHandling.scala @@ -176,9 +176,10 @@ object SupervisorStrategy extends SupervisorStrategyLowPriorityImplicits { /** * Sort so that subtypes always precede their supertypes, but without * obeying any order between unrelated subtypes (insert sort). + * + * INTERNAL API */ - //FIXME Should this really be public API? - def sort(in: Iterable[CauseDirective]): Seq[CauseDirective] = + private[akka] def sort(in: Iterable[CauseDirective]): Seq[CauseDirective] = (new ArrayBuffer[CauseDirective](in.size) /: in) { (buf, ca) ⇒ buf.indexWhere(_._1 isAssignableFrom ca._1) match { case -1 ⇒ buf append ca @@ -195,7 +196,7 @@ object SupervisorStrategy extends SupervisorStrategyLowPriorityImplicits { } /** - * An Akka SupervisorStrategy is + * An Akka SupervisorStrategy is the policy to apply for crashing children */ abstract class SupervisorStrategy { diff --git a/akka-actor/src/main/scala/akka/actor/IO.scala b/akka-actor/src/main/scala/akka/actor/IO.scala index 3ff91c4fa8..63eb2e4b3a 100644 --- a/akka-actor/src/main/scala/akka/actor/IO.scala +++ b/akka-actor/src/main/scala/akka/actor/IO.scala @@ -987,7 +987,7 @@ final class IOManagerActor extends Actor with ActorLogging { } } - protected def receive = { + def receive = { case Select ⇒ select() if (running) self ! Select diff --git a/akka-actor/src/main/scala/akka/actor/Scheduler.scala b/akka-actor/src/main/scala/akka/actor/Scheduler.scala index 8ad3d8ee98..850cb02048 100644 --- a/akka-actor/src/main/scala/akka/actor/Scheduler.scala +++ b/akka-actor/src/main/scala/akka/actor/Scheduler.scala @@ -236,7 +236,7 @@ private[akka] class ContinuousCancellable extends AtomicReference[HWTimeout](Con def isCancelled(): Boolean = get match { case null ⇒ true - case some ⇒ isCancelled() + case some ⇒ some.isCancelled() } def cancel(): Unit = diff --git a/akka-actor/src/main/scala/akka/actor/UntypedActor.scala b/akka-actor/src/main/scala/akka/actor/UntypedActor.scala index c56a2a0167..9420ab84cc 100644 --- a/akka-actor/src/main/scala/akka/actor/UntypedActor.scala +++ b/akka-actor/src/main/scala/akka/actor/UntypedActor.scala @@ -156,7 +156,7 @@ abstract class UntypedActor extends Actor { */ override def postRestart(reason: Throwable): Unit = super.postRestart(reason) - final protected def receive = { case msg ⇒ onReceive(msg) } + final def receive = { case msg ⇒ onReceive(msg) } } /** diff --git a/akka-camel/src/main/scala/akka/camel/Producer.scala b/akka-camel/src/main/scala/akka/camel/Producer.scala index 80537fda12..33541d4611 100644 --- a/akka-camel/src/main/scala/akka/camel/Producer.scala +++ b/akka-camel/src/main/scala/akka/camel/Producer.scala @@ -134,7 +134,7 @@ trait Producer extends ProducerSupport { this: Actor ⇒ * Default implementation of Actor.receive. Any messages received by this actors * will be produced to the endpoint specified by endpointUri. */ - protected def receive = produce + def receive = produce } /** diff --git a/akka-camel/src/main/scala/akka/camelexamples/ExamplesSupport.scala b/akka-camel/src/main/scala/akka/camelexamples/ExamplesSupport.scala index 3e35b8c7c9..df5b0e5508 100644 --- a/akka-camel/src/main/scala/akka/camelexamples/ExamplesSupport.scala +++ b/akka-camel/src/main/scala/akka/camelexamples/ExamplesSupport.scala @@ -19,7 +19,7 @@ private[camelexamples] class SysOutConsumer extends Consumer { override def activationTimeout = 10 seconds def endpointUri = "file://data/input/CamelConsumer" - protected def receive = { + def receive = { case msg: CamelMessage ⇒ { printf("Received '%s'\n", msg.bodyAs[String]) } @@ -30,12 +30,12 @@ private[camelexamples] class TroubleMaker extends Consumer { def endpointUri = "WRONG URI" println("Trying to instantiate conumer with uri: " + endpointUri) - protected def receive = { case _ ⇒ } + def receive = { case _ ⇒ } } private[camelexamples] class SysOutActor(implicit camel: Camel) extends Actor { implicit val camelContext = camel.context - protected def receive = { + def receive = { case msg: CamelMessage ⇒ { printf("Received '%s'\n", msg.bodyAs[String]) } diff --git a/akka-camel/src/main/scala/akka/camelexamples/_2_SupervisedConsumers.scala b/akka-camel/src/main/scala/akka/camelexamples/_2_SupervisedConsumers.scala index 5d321b28db..cdf46f012f 100644 --- a/akka-camel/src/main/scala/akka/camelexamples/_2_SupervisedConsumers.scala +++ b/akka-camel/src/main/scala/akka/camelexamples/_2_SupervisedConsumers.scala @@ -14,7 +14,7 @@ private[camelexamples] object SupervisedConsumersExample extends App { system.actorOf(Props(new Actor { context.watch(context.actorOf(Props[EndpointManager])) - protected def receive = { + def receive = { case Terminated(ref) ⇒ system.shutdown() } })) @@ -30,7 +30,7 @@ private[camelexamples] class EndpointManager extends Actor { watch(actorOf(Props[SysOutConsumer])) watch(actorOf(Props[TroubleMaker])) - protected def receive = { + def receive = { case Terminated(ref) ⇒ { printf("Hey! One of the endpoints has died: %s. I am doing sepuku...\n", ref) self ! PoisonPill diff --git a/akka-camel/src/test/scala/akka/camel/ProducerFeatureTest.scala b/akka-camel/src/test/scala/akka/camel/ProducerFeatureTest.scala index cef098b8fe..a7e5b9e4cb 100644 --- a/akka-camel/src/test/scala/akka/camel/ProducerFeatureTest.scala +++ b/akka-camel/src/test/scala/akka/camel/ProducerFeatureTest.scala @@ -244,7 +244,7 @@ object ProducerFeatureTest { } class TestResponder extends Actor { - protected def receive = { + def receive = { case msg: CamelMessage ⇒ msg.body match { case "fail" ⇒ context.sender ! akka.actor.Status.Failure(new AkkaCamelException(new Exception("failure"), msg.headers)) case _ ⇒ @@ -256,7 +256,7 @@ object ProducerFeatureTest { } class ReplyingForwardTarget extends Actor { - protected def receive = { + def receive = { case msg: CamelMessage ⇒ context.sender ! (msg.addHeader("test" -> "result")) case msg: akka.actor.Status.Failure ⇒ diff --git a/akka-camel/src/test/scala/akka/camel/internal/component/ActorProducerTest.scala b/akka-camel/src/test/scala/akka/camel/internal/component/ActorProducerTest.scala index 8146b17399..a0e153fd54 100644 --- a/akka-camel/src/test/scala/akka/camel/internal/component/ActorProducerTest.scala +++ b/akka-camel/src/test/scala/akka/camel/internal/component/ActorProducerTest.scala @@ -334,7 +334,7 @@ trait ActorProducerFixture extends MockitoSugar with BeforeAndAfterAll with Befo } def echoActor = system.actorOf(Props(new Actor { - protected def receive = { + def receive = { case msg ⇒ sender ! "received " + msg } })) diff --git a/akka-docs/scala/actors.rst b/akka-docs/scala/actors.rst index 5374c8a37c..9269c841f5 100644 --- a/akka-docs/scala/actors.rst +++ b/akka-docs/scala/actors.rst @@ -443,7 +443,7 @@ An Actor has to implement the ``receive`` method to receive messages: .. code-block:: scala - protected def receive: PartialFunction[Any, Unit] + def receive: PartialFunction[Any, Unit] Note: Akka has an alias to the ``PartialFunction[Any, Unit]`` type called ``Receive`` (``akka.actor.Actor.Receive``), so you can use this type instead for diff --git a/akka-testkit/src/main/scala/akka/testkit/TestActorRef.scala b/akka-testkit/src/main/scala/akka/testkit/TestActorRef.scala index 8a2f61bf76..0a5d6163e8 100644 --- a/akka-testkit/src/main/scala/akka/testkit/TestActorRef.scala +++ b/akka-testkit/src/main/scala/akka/testkit/TestActorRef.scala @@ -56,7 +56,7 @@ class TestActorRef[T <: Actor]( * thrown will be available to you, while still being able to use * become/unbecome. */ - def receive(o: Any) { underlyingActor.apply(o) } + def receive(o: Any): Unit = underlying.receiveMessage(o) /** * Retrieve reference to the underlying actor, where the static type matches the factory used inside the diff --git a/akka-zeromq/src/test/scala/akka/zeromq/ConcurrentSocketActorSpec.scala b/akka-zeromq/src/test/scala/akka/zeromq/ConcurrentSocketActorSpec.scala index dcc456b544..fe0d715dba 100644 --- a/akka-zeromq/src/test/scala/akka/zeromq/ConcurrentSocketActorSpec.scala +++ b/akka-zeromq/src/test/scala/akka/zeromq/ConcurrentSocketActorSpec.scala @@ -138,7 +138,7 @@ class ConcurrentSocketActorSpec extends AkkaSpec { } } - protected def receive = { + def receive = { case _ ⇒ val payload = "%s".format(messageNumber) messageNumber += 1 diff --git a/file-based/mailbox_user__a b/file-based/mailbox_user__a deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/file-based/mailbox_user__b b/file-based/mailbox_user__b deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/file-based/mailbox_user__c b/file-based/mailbox_user__c deleted file mode 100644 index e84f2a5e4f42e4329047049aad7186418b4bb478..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12892 zcmZQ7Wnf_NcU_QY&d2}E-d`)^;Mm4L+D95PfYcdKlYFSN2Nk%QJ$tcRGWi=UP8MUk?qcEeE)dN?W z84X-%W<+Lb7D9O$ZbW8jMh&aUEX}B4HJPOuHLNDHG^2*qWR_;su$s)$j2c#xS(;J9 zYBEbRDp+kyW@$zZs|T($GbXb%3#GguH72t(qlVRFmS)tjn#|IS8dj58no+}QGD|aR zSWRYWMh&aUEX}B3wF#M}88xgXvoxcI)dN?WnUGnUg;8FRnvhwVQNwC7OEYR%O=f9E z4Xep4&8T5DnWY&utR}NGqk`3@WR_;(lxHqeGD|aRSWRYWMh&aUEX}B4HJPOuHLNDH zG^2*qWR_;su$s)$j2c#xS(-&qAzzbOno+@OGcrpvYFJHXX+{mJ$t=yNVKteh88xgX zvoxcI)nt}t)UcY&(kznld~HT%X+{mJ$t=yNVKteh85OKHC$lu8hSg-2X4J5n%+ib+ zR+CwpMNyu)%*iaxs9`mkrCBr;d`)I)Mh&aUEX}B4HJPOuHLNDHG^2vm7G#!Y)UcY& z(u^8blUbTk!)h{1vslXWwFQ}_88xgXvoxcI)nt}t)UcY&(u^8blUbTk!)h{1vpC9A zxFwmT88xgXvoxcI)nt}t)UcY&(u^8blUbTk!)h{1Giq2(W@$zZtH~_Qs9`mkrCB@` oiWD+RvvLLo2J);H_o@E2Co+Z6FV+5~?A0N{bSca#DR0Gjo#iD}oDBll4oBQ;YOf zQiMXe0@u7{U@b0U5X?#}OVrCr%uCnv%qvMvPc0I9v|!2i#&!!P21ZW?*0RK$($tC~ z1_6XRztY^K)S|XEQ)RiQJm_X(V5lfyU|?VrU{q4)QpIg|N@`+?Pijd?YEd!c;Bq<> z2~KANh4kQZJ~IiN{bSca#DR0Gjo#iD}oDBll4oBQ;YOf zQiVdf0@u7{U@b0U5X?#}OVrCr%uCnv%qvMvPc0I9v|!2i#&!!P21ZW?*0RK$($tC~ z1_6XRztY^K)S|XEQ)RiQJm_X(V5lfyU|?VrU{q4)QpIg|N@`+?Pijd?YEd!c;Bq<> z2~KANh4kQZJ~IiX)PzmpCSuN{bSca#DR0Gjo#iD}oDBll4oBQ;YOf z(u6{}0@u7{U@b0U5X?#}OVrCr%uCnv%qvMvPc0I9v|!2i#&!!P21ZW?*0RK$($tC~ z1_6XRztY^K)S|XEQ)RiQJm_X(V5lfyU|?VrU{q4)QpIg|N@`+?Pijd?YEdyG8_2z2 z_uCB?_cM{;{=wyPW)fTu33&*~RKmc(U{6-~^Ko&3(oYEkb8%^|0HcyFmp1N*FRm;u UNzK(SNi8mMOfJbUGK5$U024mYO#lD@ From a98827c150e7df63aa88bb4708e472a1d262d901 Mon Sep 17 00:00:00 2001 From: Patrik Nordwall Date: Mon, 21 May 2012 14:35:23 +0200 Subject: [PATCH 18/21] unb0rkening the akka-docs --- .../main/java/akka/remote/RemoteProtocol.java | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/akka-remote/src/main/java/akka/remote/RemoteProtocol.java b/akka-remote/src/main/java/akka/remote/RemoteProtocol.java index d168e5acc1..0794e54364 100644 --- a/akka-remote/src/main/java/akka/remote/RemoteProtocol.java +++ b/akka-remote/src/main/java/akka/remote/RemoteProtocol.java @@ -309,7 +309,7 @@ public final class RemoteProtocol { maybeForceBuilderInitialization(); } - private Builder(BuilderParent parent) { + private Builder(com.google.protobuf.GeneratedMessage.BuilderParent parent) { super(parent); maybeForceBuilderInitialization(); } @@ -981,7 +981,7 @@ public final class RemoteProtocol { maybeForceBuilderInitialization(); } - private Builder(BuilderParent parent) { + private Builder(com.google.protobuf.GeneratedMessage.BuilderParent parent) { super(parent); maybeForceBuilderInitialization(); } @@ -1977,7 +1977,7 @@ public final class RemoteProtocol { maybeForceBuilderInitialization(); } - private Builder(BuilderParent parent) { + private Builder(com.google.protobuf.GeneratedMessage.BuilderParent parent) { super(parent); maybeForceBuilderInitialization(); } @@ -2527,7 +2527,7 @@ public final class RemoteProtocol { maybeForceBuilderInitialization(); } - private Builder(BuilderParent parent) { + private Builder(com.google.protobuf.GeneratedMessage.BuilderParent parent) { super(parent); maybeForceBuilderInitialization(); } @@ -2936,7 +2936,7 @@ public final class RemoteProtocol { maybeForceBuilderInitialization(); } - private Builder(BuilderParent parent) { + private Builder(com.google.protobuf.GeneratedMessage.BuilderParent parent) { super(parent); maybeForceBuilderInitialization(); } @@ -3410,7 +3410,7 @@ public final class RemoteProtocol { maybeForceBuilderInitialization(); } - private Builder(BuilderParent parent) { + private Builder(com.google.protobuf.GeneratedMessage.BuilderParent parent) { super(parent); maybeForceBuilderInitialization(); } @@ -3909,7 +3909,7 @@ public final class RemoteProtocol { maybeForceBuilderInitialization(); } - private Builder(BuilderParent parent) { + private Builder(com.google.protobuf.GeneratedMessage.BuilderParent parent) { super(parent); maybeForceBuilderInitialization(); } @@ -4487,7 +4487,7 @@ public final class RemoteProtocol { maybeForceBuilderInitialization(); } - private Builder(BuilderParent parent) { + private Builder(com.google.protobuf.GeneratedMessage.BuilderParent parent) { super(parent); maybeForceBuilderInitialization(); } @@ -5367,7 +5367,7 @@ public final class RemoteProtocol { maybeForceBuilderInitialization(); } - private Builder(BuilderParent parent) { + private Builder(com.google.protobuf.GeneratedMessage.BuilderParent parent) { super(parent); maybeForceBuilderInitialization(); } @@ -6067,7 +6067,7 @@ public final class RemoteProtocol { maybeForceBuilderInitialization(); } - private Builder(BuilderParent parent) { + private Builder(com.google.protobuf.GeneratedMessage.BuilderParent parent) { super(parent); maybeForceBuilderInitialization(); } @@ -6584,7 +6584,7 @@ public final class RemoteProtocol { maybeForceBuilderInitialization(); } - private Builder(BuilderParent parent) { + private Builder(com.google.protobuf.GeneratedMessage.BuilderParent parent) { super(parent); maybeForceBuilderInitialization(); } From 2a370520fd5fd7f8799d35c23950692056c94717 Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Mon, 21 May 2012 14:50:49 +0200 Subject: [PATCH 19/21] Cleaning up the cancellables, null-object pattern ftw --- .../src/main/scala/akka/actor/Scheduler.scala | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/akka-actor/src/main/scala/akka/actor/Scheduler.scala b/akka-actor/src/main/scala/akka/actor/Scheduler.scala index 850cb02048..30cadc5a3b 100644 --- a/akka-actor/src/main/scala/akka/actor/Scheduler.scala +++ b/akka-actor/src/main/scala/akka/actor/Scheduler.scala @@ -216,6 +216,14 @@ private[akka] object ContinuousCancellable { override def isCancelled: Boolean = false override def cancel: Unit = () } + + val cancelled: HWTimeout = new HWTimeout { + override def getTimer: Timer = null + override def getTask: TimerTask = null + override def isExpired: Boolean = false + override def isCancelled: Boolean = true + override def cancel: Unit = () + } } /** * Wrapper of a [[org.jboss.netty.akka.util.Timeout]] that delegates all @@ -229,24 +237,15 @@ private[akka] class ContinuousCancellable extends AtomicReference[HWTimeout](Con } @tailrec private[akka] final def swap(newTimeout: HWTimeout): Unit = get match { - case null ⇒ newTimeout.cancel() - case some if some.isCancelled ⇒ cancel(); newTimeout.cancel() + case some if some.isCancelled ⇒ try cancel() finally newTimeout.cancel() case some ⇒ if (!compareAndSet(some, newTimeout)) swap(newTimeout) } - def isCancelled(): Boolean = get match { - case null ⇒ true - case some ⇒ some.isCancelled() - } - - def cancel(): Unit = - getAndSet(null) match { - case null ⇒ - case some ⇒ some.cancel() - } + def isCancelled(): Boolean = get().isCancelled() + def cancel(): Unit = getAndSet(ContinuousCancellable.cancelled).cancel() } -private[akka] class DefaultCancellable(val timeout: HWTimeout) extends Cancellable { - override def cancel(): Unit = timeout.cancel() - override def isCancelled: Boolean = timeout.isCancelled +private[akka] class DefaultCancellable(timeout: HWTimeout) extends AtomicReference[HWTimeout](timeout) with Cancellable { + override def cancel(): Unit = getAndSet(ContinuousCancellable.cancelled).cancel() + override def isCancelled: Boolean = get().isCancelled } From c7ca6af9274dfb2b92f44f17062a831717fbc279 Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Mon, 21 May 2012 14:53:07 +0200 Subject: [PATCH 20/21] Adding a more robust test for the SchedulerSpec --- .../src/test/scala/akka/actor/SchedulerSpec.scala | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/akka-actor-tests/src/test/scala/akka/actor/SchedulerSpec.scala b/akka-actor-tests/src/test/scala/akka/actor/SchedulerSpec.scala index 3b87af2aad..beeb2a4c3b 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/SchedulerSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/SchedulerSpec.scala @@ -18,7 +18,12 @@ class SchedulerSpec extends AkkaSpec with BeforeAndAfterEach with DefaultTimeout } override def afterEach { - while (cancellables.peek() ne null) { Option(cancellables.poll()).foreach(_.cancel()) } + while (cancellables.peek() ne null) { + for (c ← Option(cancellables.poll())) { + c.cancel() + c.isCancelled must be === true + } + } } "A Scheduler" must { From 6e46b089ff44617980fe8ce807a3000cbc088137 Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Mon, 21 May 2012 16:42:33 +0200 Subject: [PATCH 21/21] Adding the arguably more correct behavior stacking --- .../src/main/scala/akka/actor/ActorCell.scala | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/akka-actor/src/main/scala/akka/actor/ActorCell.scala b/akka-actor/src/main/scala/akka/actor/ActorCell.scala index 6a25ac04a9..c73e6fc4b2 100644 --- a/akka-actor/src/main/scala/akka/actor/ActorCell.scala +++ b/akka-actor/src/main/scala/akka/actor/ActorCell.scala @@ -185,6 +185,8 @@ private[akka] object ActorCell { final val emptyReceiveTimeoutData: (Long, Cancellable) = (-1, emptyCancellable) + final val behaviorStackPlaceHolder: Stack[Actor.Receive] = Stack.empty.push(Actor.emptyBehavior) + sealed trait SuspendReason case object UserRequest extends SuspendReason case class Recreation(cause: Throwable) extends SuspendReason @@ -493,11 +495,18 @@ private[akka] class ActorCell( protected def newActor(): Actor = { contextStack.set(contextStack.get.push(this)) try { + import ActorCell.behaviorStackPlaceHolder + + behaviorStack = behaviorStackPlaceHolder val instance = props.creator() if (instance eq null) throw ActorInitializationException(self, "Actor instance passed to actorOf can't be 'null'") + behaviorStack = behaviorStack match { + case `behaviorStackPlaceHolder` ⇒ Stack.empty.push(instance.receive) + case newBehaviors ⇒ Stack.empty.push(instance.receive).pushAll(newBehaviors.reverse.drop(1)) + } instance } finally { val stackAfter = contextStack.get @@ -512,7 +521,6 @@ private[akka] class ActorCell( def create(): Unit = if (isNormal) { try { val created = newActor() - behaviorStack = Stack.empty.push(created.receive) actor = created created.preStart() checkReceiveTimeout @@ -648,10 +656,8 @@ private[akka] class ActorCell( /* * UntypedActorContext impl */ - def become(behavior: Procedure[Any], discardOld: Boolean): Unit = { - def newReceive: Actor.Receive = { case msg ⇒ behavior.apply(msg) } - become(newReceive, discardOld) - } + def become(behavior: Procedure[Any], discardOld: Boolean): Unit = + become({ case msg ⇒ behavior.apply(msg) }: Actor.Receive, discardOld) def unbecome(): Unit = { val original = behaviorStack @@ -694,7 +700,7 @@ private[akka] class ActorCell( if (system.settings.DebugLifecycle) system.eventStream.publish(Debug(self.path.toString, clazz(actor), "stopped")) } finally { - behaviorStack = Stack.empty + behaviorStack = ActorCell.behaviorStackPlaceHolder clearActorFields(a) actor = null } @@ -704,9 +710,7 @@ private[akka] class ActorCell( private def doRecreate(cause: Throwable, failedActor: Actor): Unit = try { // after all killed children have terminated, recreate the rest, then go on to start the new instance actor.supervisorStrategy.handleSupervisorRestarted(cause, self, children) - val freshActor = newActor() - behaviorStack = Stack.empty.push(freshActor.receive) actor = freshActor // this must happen before postRestart has a chance to fail if (freshActor eq failedActor) setActorFields(freshActor, this, self) // If the creator returns the same instance, we need to restore our nulled out fields.