2012-01-19 14:38:44 +00:00
|
|
|
/**
|
|
|
|
|
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
package akka.camel.internal
|
|
|
|
|
|
|
|
|
|
import akka.actor._
|
|
|
|
|
import collection.mutable.WeakHashMap
|
2012-03-18 10:46:08 +01:00
|
|
|
import akka.camel._
|
2012-09-03 12:08:46 +02:00
|
|
|
import internal.ActivationProtocol._
|
2012-01-19 14:38:44 +00:00
|
|
|
|
2012-03-01 17:32:10 +01:00
|
|
|
/**
|
2012-03-18 10:46:08 +01:00
|
|
|
* For internal use only. An actor that tracks activation and de-activation of endpoints.
|
2012-03-01 17:32:10 +01:00
|
|
|
*/
|
|
|
|
|
private[akka] final class ActivationTracker extends Actor with ActorLogging {
|
2012-01-19 14:38:44 +00:00
|
|
|
val activations = new WeakHashMap[ActorRef, ActivationStateMachine]
|
|
|
|
|
|
2012-03-01 17:32:10 +01:00
|
|
|
/**
|
|
|
|
|
* A state machine that keeps track of the endpoint activation status of an actor.
|
|
|
|
|
*/
|
2012-01-19 14:38:44 +00:00
|
|
|
class ActivationStateMachine {
|
|
|
|
|
type State = PartialFunction[ActivationMessage, Unit]
|
|
|
|
|
|
|
|
|
|
var receive: State = notActivated()
|
|
|
|
|
|
2012-03-01 17:32:10 +01:00
|
|
|
/**
|
|
|
|
|
* Not activated state
|
|
|
|
|
* @return a partial function that handles messages in the 'not activated' state
|
|
|
|
|
*/
|
2012-01-19 14:38:44 +00:00
|
|
|
def notActivated(): State = {
|
|
|
|
|
var awaitingActivation = List[ActorRef]()
|
|
|
|
|
var awaitingDeActivation = List[ActorRef]()
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
case AwaitActivation(ref) ⇒ awaitingActivation ::= sender
|
|
|
|
|
case AwaitDeActivation(ref) ⇒ awaitingDeActivation ::= sender
|
2012-03-01 17:32:10 +01:00
|
|
|
case msg @ EndpointActivated(ref) ⇒
|
2012-01-19 14:38:44 +00:00
|
|
|
awaitingActivation.foreach(_ ! msg)
|
|
|
|
|
receive = activated(awaitingDeActivation)
|
2012-03-01 17:32:10 +01:00
|
|
|
case EndpointFailedToActivate(ref, cause) ⇒
|
2012-01-19 14:38:44 +00:00
|
|
|
awaitingActivation.foreach(_ ! EndpointFailedToActivate(ref, cause))
|
|
|
|
|
receive = failedToActivate(cause)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-01 17:32:10 +01:00
|
|
|
/**
|
|
|
|
|
* Activated state.
|
|
|
|
|
* @param currentAwaitingDeActivation the current <code>ActorRef</code>s awaiting de-activation
|
|
|
|
|
* @return a partial function that handles messages in the 'activated' state
|
|
|
|
|
*/
|
2012-01-19 14:38:44 +00:00
|
|
|
def activated(currentAwaitingDeActivation: List[ActorRef]): State = {
|
|
|
|
|
var awaitingDeActivation = currentAwaitingDeActivation
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
case AwaitActivation(ref) ⇒ sender ! EndpointActivated(ref)
|
|
|
|
|
case AwaitDeActivation(ref) ⇒ awaitingDeActivation ::= sender
|
2012-03-01 17:32:10 +01:00
|
|
|
case msg @ EndpointDeActivated(ref) ⇒
|
2012-01-19 14:38:44 +00:00
|
|
|
awaitingDeActivation foreach (_ ! msg)
|
|
|
|
|
receive = deactivated
|
2012-03-01 17:32:10 +01:00
|
|
|
case msg @ EndpointFailedToDeActivate(ref, cause) ⇒
|
2012-01-19 14:38:44 +00:00
|
|
|
awaitingDeActivation foreach (_ ! msg)
|
|
|
|
|
receive = failedToDeActivate(cause)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-01 17:32:10 +01:00
|
|
|
/**
|
|
|
|
|
* De-activated state
|
|
|
|
|
* @return a partial function that handles messages in the 'de-activated' state
|
|
|
|
|
*/
|
2012-01-19 14:38:44 +00:00
|
|
|
def deactivated: State = {
|
|
|
|
|
case AwaitActivation(ref) ⇒ sender ! EndpointActivated(ref)
|
|
|
|
|
case AwaitDeActivation(ref) ⇒ sender ! EndpointDeActivated(ref)
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-01 17:32:10 +01:00
|
|
|
/**
|
|
|
|
|
* Failed to activate state
|
|
|
|
|
* @param cause the cause for the failure
|
|
|
|
|
* @return a partial function that handles messages in 'failed to activate' state
|
|
|
|
|
*/
|
2012-01-19 14:38:44 +00:00
|
|
|
def failedToActivate(cause: Throwable): State = {
|
|
|
|
|
case AwaitActivation(ref) ⇒ sender ! EndpointFailedToActivate(ref, cause)
|
|
|
|
|
case AwaitDeActivation(ref) ⇒ sender ! EndpointFailedToActivate(ref, cause)
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-01 17:32:10 +01:00
|
|
|
/**
|
|
|
|
|
* Failed to de-activate state
|
|
|
|
|
* @param cause the cause for the failure
|
|
|
|
|
* @return a partial function that handles messages in 'failed to de-activate' state
|
|
|
|
|
*/
|
2012-01-19 14:38:44 +00:00
|
|
|
def failedToDeActivate(cause: Throwable): State = {
|
|
|
|
|
case AwaitActivation(ref) ⇒ sender ! EndpointActivated(ref)
|
|
|
|
|
case AwaitDeActivation(ref) ⇒ sender ! EndpointFailedToDeActivate(ref, cause)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override def receive = {
|
2012-03-01 17:32:10 +01:00
|
|
|
case msg @ ActivationMessage(ref) ⇒
|
2012-05-23 15:17:49 +02:00
|
|
|
(activations.getOrElseUpdate(ref, new ActivationStateMachine).receive orElse logStateWarning(ref))(msg)
|
2012-01-19 14:38:44 +00:00
|
|
|
}
|
|
|
|
|
|
2012-05-23 15:17:49 +02:00
|
|
|
private[this] def logStateWarning(actorRef: ActorRef): Receive =
|
|
|
|
|
{ case msg ⇒ log.warning("Message [{}] not expected in current state of actor [{}]", msg, actorRef) }
|
2012-01-19 14:38:44 +00:00
|
|
|
}
|
|
|
|
|
|
2012-03-18 10:46:08 +01:00
|
|
|
/**
|
|
|
|
|
* For internal use only. A request message to the ActivationTracker for the status of activation.
|
|
|
|
|
* @param ref the actorRef
|
|
|
|
|
*/
|
|
|
|
|
private[camel] case class AwaitActivation(ref: ActorRef) extends ActivationMessage(ref)
|
2012-01-19 14:38:44 +00:00
|
|
|
|
2012-03-18 10:46:08 +01:00
|
|
|
/**
|
|
|
|
|
* For internal use only. A request message to the ActivationTracker for the status of de-activation.
|
|
|
|
|
* For internal use only.
|
|
|
|
|
* @param ref the actorRef
|
|
|
|
|
*/
|
|
|
|
|
private[camel] case class AwaitDeActivation(ref: ActorRef) extends ActivationMessage(ref)
|