From ee0c6c655fed7b21afc03978b93b0dbe269ce76a Mon Sep 17 00:00:00 2001 From: jboner Date: Mon, 30 Nov 2009 10:11:52 +0100 Subject: [PATCH 1/8] added PersistentMap.newMap(id) and PersistinteMap.getMap(id) for Map, Vector and Ref --- akka-actors/src/main/scala/actor/Actor.scala | 53 +++++---- .../src/main/scala/actor/ActorRegistry.scala | 5 + .../src/main/scala/actor/Scheduler.scala | 2 +- .../src/main/scala/actor/Supervisor.scala | 6 +- .../src/main/scala/stm/Transaction.scala | 21 ++-- .../scala/stm/TransactionManagement.scala | 17 +-- .../main/scala/stm/TransactionalState.scala | 9 +- .../src/main/scala/PersistentState.scala | 106 +++++++++++++----- config/akka-reference.conf | 1 + 9 files changed, 143 insertions(+), 77 deletions(-) diff --git a/akka-actors/src/main/scala/actor/Actor.scala b/akka-actors/src/main/scala/actor/Actor.scala index 85d39a97d7..695fc5198a 100644 --- a/akka-actors/src/main/scala/actor/Actor.scala +++ b/akka-actors/src/main/scala/actor/Actor.scala @@ -66,7 +66,7 @@ class ActorMessageInvoker(val actor: Actor) extends MessageInvoker { /** * @author Jonas Bonér */ -object Actor { +object Actor extends Logging { val TIMEOUT = config.getInt("akka.actor.timeout", 5000) val SERIALIZE_MESSAGES = config.getBool("akka.actor.serialize-messages", false) @@ -74,7 +74,7 @@ object Actor { implicit val Self: AnyRef = this def receive = { case unknown => - log.error( + Actor.log.error( "Actor.Sender can't process messages. Received message [%s]." + "This error could occur if you either:" + "\n\t- Explicitly send a message to the Actor.Sender object." + @@ -163,7 +163,7 @@ object Actor { * */ def actor(lifeCycleConfig: LifeCycle)(body: PartialFunction[Any, Unit]): Actor = new Actor() { - lifeCycle = lifeCycleConfig + lifeCycle = Some(lifeCycleConfig) start def receive = body } @@ -186,7 +186,7 @@ object Actor { def actor[A](lifeCycleConfig: LifeCycle)(body: => Unit) = { def handler[A](body: Unit) = new { def receive(handler: PartialFunction[Any, Unit]) = new Actor() { - lifeCycle = lifeCycleConfig + lifeCycle = Some(lifeCycleConfig) start body def receive = handler @@ -209,7 +209,7 @@ object Actor { * * @author Jonas Bonér */ -trait Actor extends Logging with TransactionManagement { +trait Actor extends TransactionManagement { ActorRegistry.register(this) implicit protected val self: Actor = this @@ -228,7 +228,7 @@ trait Actor extends Logging with TransactionManagement { private var _config: Option[AnyRef] = None private val _remoteFlagLock = new ReadWriteLock private[akka] var _remoteAddress: Option[InetSocketAddress] = None - private[akka] val _linkedActors = new HashSet[Actor] + private[akka] var _linkedActors: Option[HashSet[Actor]] = None private[akka] var _mailbox: MessageQueue = _ private[akka] var _supervisor: Option[Actor] = None @@ -328,9 +328,9 @@ trait Actor extends Logging with TransactionManagement { /** * User overridable callback/setting. * - * Defines the life-cycle for a supervised actor. Default is 'LifeCycle(Permanent)' but can be overridden. + * Defines the life-cycle for a supervised actor. */ - @volatile var lifeCycle: LifeCycle = LifeCycle(Permanent) + @volatile var lifeCycle: Option[LifeCycle] = None /** * User overridable callback/setting. @@ -418,7 +418,7 @@ trait Actor extends Logging with TransactionManagement { _isRunning = true //if (isTransactional) this !! TransactionalInit } - log.info("[%s] has started", toString) + Actor.log.info("[%s] has started", toString) this } @@ -438,6 +438,7 @@ trait Actor extends Logging with TransactionManagement { _isRunning = false _isShutDown = true shutdown + ActorRegistry.unregister(this) } } @@ -615,11 +616,11 @@ trait Actor extends Logging with TransactionManagement { */ protected[this] def link(actor: Actor) = { if (_isRunning) { - _linkedActors.add(actor) + getLinkedActors.add(actor) if (actor._supervisor.isDefined) throw new IllegalStateException( "Actor can only have one supervisor [" + actor + "], e.g. link(actor) fails") actor._supervisor = Some(this) - log.debug("Linking actor [%s] to actor [%s]", actor, this) + Actor.log.debug("Linking actor [%s] to actor [%s]", actor, this) } else throw new IllegalStateException( "Actor has not been started, you need to invoke 'actor.start' before using it") } @@ -631,10 +632,10 @@ trait Actor extends Logging with TransactionManagement { */ protected[this] def unlink(actor: Actor) = { if (_isRunning) { - if (!_linkedActors.contains(actor)) throw new IllegalStateException("Actor [" + actor + "] is not a linked actor, can't unlink") - _linkedActors.remove(actor) + if (!getLinkedActors.contains(actor)) throw new IllegalStateException("Actor [" + actor + "] is not a linked actor, can't unlink") + getLinkedActors.remove(actor) actor._supervisor = None - log.debug("Unlinking actor [%s] from actor [%s]", actor, this) + Actor.log.debug("Unlinking actor [%s] from actor [%s]", actor, this) } else throw new IllegalStateException( "Actor has not been started, you need to invoke 'actor.start' before using it") } @@ -773,7 +774,7 @@ trait Actor extends Logging with TransactionManagement { else dispatch(messageHandle) } catch { case e => - log.error(e, "Could not invoke actor [%s]", this) + Actor.log.error(e, "Could not invoke actor [%s]", this) throw e } } @@ -790,7 +791,7 @@ trait Actor extends Logging with TransactionManagement { else throw new IllegalArgumentException("No handler matching message [" + message + "] in " + toString) } catch { case e => - log.error(e, "Could not invoke actor [%s]", this) + Actor.log.error(e, "Could not invoke actor [%s]", this) // FIXME to fix supervisor restart of remote actor for oneway calls, inject a supervisor proxy that can send notification back to client if (_supervisor.isDefined) _supervisor.get ! Exit(this, e) if (senderFuture.isDefined) senderFuture.get.completeWithException(this, e) @@ -830,7 +831,7 @@ trait Actor extends Logging with TransactionManagement { } else proceed } catch { case e => - log.error(e, "Could not invoke actor [%s]", this) + Actor.log.error(e, "Could not invoke actor [%s]", this) if (senderFuture.isDefined) senderFuture.get.completeWithException(this, e) clearTransaction // need to clear currentTransaction before call to supervisor // FIXME to fix supervisor restart of remote actor for oneway calls, inject a supervisor proxy that can send notification back to client @@ -871,15 +872,16 @@ trait Actor extends Logging with TransactionManagement { } private[this] def restartLinkedActors(reason: AnyRef) = { - _linkedActors.toArray.toList.asInstanceOf[List[Actor]].foreach { actor => - actor.lifeCycle match { + getLinkedActors.toArray.toList.asInstanceOf[List[Actor]].foreach { actor => + if (actor.lifeCycle.isEmpty) actor.lifeCycle = Some(LifeCycle(Permanent)) + actor.lifeCycle.get match { case LifeCycle(scope, _) => { scope match { case Permanent => actor.restart(reason) case Temporary => - log.info("Actor [%s] configured as TEMPORARY will not be restarted.", actor.id) - _linkedActors.remove(actor) // remove the temporary actor + Actor.log.info("Actor [%s] configured as TEMPORARY will not be restarted.", actor.id) + getLinkedActors.remove(actor) // remove the temporary actor } } } @@ -888,7 +890,7 @@ trait Actor extends Logging with TransactionManagement { private[Actor] def restart(reason: AnyRef) = synchronized { preRestart(reason, _config) - log.info("Restarting actor [%s] configured as PERMANENT.", id) + Actor.log.info("Restarting actor [%s] configured as PERMANENT.", id) postRestart(reason, _config) } @@ -899,6 +901,13 @@ trait Actor extends Logging with TransactionManagement { } else None } + protected def getLinkedActors: HashSet[Actor] = { + if (_linkedActors.isEmpty) { + val set = new HashSet[Actor] + _linkedActors = Some(set) + set + } else _linkedActors.get + } private[akka] def swapDispatcher(disp: MessageDispatcher) = synchronized { messageDispatcher = disp diff --git a/akka-actors/src/main/scala/actor/ActorRegistry.scala b/akka-actors/src/main/scala/actor/ActorRegistry.scala index fc40a9003a..327a7e6395 100755 --- a/akka-actors/src/main/scala/actor/ActorRegistry.scala +++ b/akka-actors/src/main/scala/actor/ActorRegistry.scala @@ -43,4 +43,9 @@ object ActorRegistry { case None => actorsById + (id -> (actor :: Nil)) } } + + def unregister(actor: Actor) = synchronized { + actorsByClassName - actor.getClass.getName + actorsById - actor.getClass.getName + } } diff --git a/akka-actors/src/main/scala/actor/Scheduler.scala b/akka-actors/src/main/scala/actor/Scheduler.scala index 9b9ee8bc7e..6266c17942 100644 --- a/akka-actors/src/main/scala/actor/Scheduler.scala +++ b/akka-actors/src/main/scala/actor/Scheduler.scala @@ -28,7 +28,7 @@ case class SchedulerException(msg: String, e: Throwable) extends RuntimeExceptio * which is licensed under the Apache 2 License. */ class ScheduleActor(val receiver: Actor, val future: ScheduledFuture[AnyRef]) extends Actor with Logging { - lifeCycle = LifeCycle(Permanent) + lifeCycle = Some(LifeCycle(Permanent)) def receive = { case UnSchedule => diff --git a/akka-actors/src/main/scala/actor/Supervisor.scala b/akka-actors/src/main/scala/actor/Supervisor.scala index ec65fbfec7..a84779a917 100644 --- a/akka-actors/src/main/scala/actor/Supervisor.scala +++ b/akka-actors/src/main/scala/actor/Supervisor.scala @@ -95,7 +95,7 @@ sealed class Supervisor private[akka] (handler: FaultHandlingStrategy) override def start = synchronized { ConfiguratorRepository.registerConfigurator(this) - _linkedActors.toArray.toList.asInstanceOf[List[Actor]].foreach { actor => + getLinkedActors.toArray.toList.asInstanceOf[List[Actor]].foreach { actor => actor.start log.info("Starting actor: %s", actor) } @@ -104,7 +104,7 @@ sealed class Supervisor private[akka] (handler: FaultHandlingStrategy) override def stop = synchronized { super[Actor].stop - _linkedActors.toArray.toList.asInstanceOf[List[Actor]].foreach { actor => + getLinkedActors.toArray.toList.asInstanceOf[List[Actor]].foreach { actor => actor.stop log.info("Shutting actor down: %s", actor) } @@ -121,7 +121,7 @@ sealed class Supervisor private[akka] (handler: FaultHandlingStrategy) server match { case Supervise(actor, lifeCycle) => actors.put(actor.getClass.getName, actor) - actor.lifeCycle = lifeCycle + actor.lifeCycle = Some(lifeCycle) startLink(actor) case SupervisorConfig(_, _) => // recursive configuration diff --git a/akka-actors/src/main/scala/stm/Transaction.scala b/akka-actors/src/main/scala/stm/Transaction.scala index d34661c37a..09222366bb 100644 --- a/akka-actors/src/main/scala/stm/Transaction.scala +++ b/akka-actors/src/main/scala/stm/Transaction.scala @@ -70,7 +70,8 @@ class TransactionRetryException(message: String) extends RuntimeException(messag * // For example, if you have a List with TransactionalRef * val refs: List[TransactionalRef] = ... * - * // You can use them together with Transaction in a for comprehension since TransactionalRef is also monadic + * // You can use them together with Transaction in a for comprehension since + * // TransactionalRef is also monadic * for { * tx <- Transaction * ref <- refs @@ -107,7 +108,8 @@ object Transaction extends TransactionManagement { def foreach(f: Transaction => Unit): Unit = atomic { f(getTransactionInScope) } /** - * Creates a "pure" STM atomic transaction and by-passes all transactions hooks such as persistence etc. + * Creates a "pure" STM atomic transaction and by-passes all transactions hooks + * such as persistence etc. * Only for internal usage. */ private[akka] def pureAtomic[T](body: => T): T = new AtomicTemplate[T]( @@ -246,13 +248,18 @@ object Transaction extends TransactionManagement { private[akka] def register(uuid: String, storage: Committable) = persistentStateMap.put(uuid, storage) private def ensureIsActive = if (status != TransactionStatus.Active) - throw new IllegalStateException("Expected ACTIVE transaction - current status [" + status + "]: " + toString) + throw new IllegalStateException( + "Expected ACTIVE transaction - current status [" + status + "]: " + toString) - private def ensureIsActiveOrAborted = if (!(status == TransactionStatus.Active || status == TransactionStatus.Aborted)) - throw new IllegalStateException("Expected ACTIVE or ABORTED transaction - current status [" + status + "]: " + toString) + private def ensureIsActiveOrAborted = + if (!(status == TransactionStatus.Active || status == TransactionStatus.Aborted)) + throw new IllegalStateException( + "Expected ACTIVE or ABORTED transaction - current status [" + status + "]: " + toString) - private def ensureIsActiveOrNew = if (!(status == TransactionStatus.Active || status == TransactionStatus.New)) - throw new IllegalStateException("Expected ACTIVE or NEW transaction - current status [" + status + "]: " + toString) + private def ensureIsActiveOrNew = + if (!(status == TransactionStatus.Active || status == TransactionStatus.New)) + throw new IllegalStateException( + "Expected ACTIVE or NEW transaction - current status [" + status + "]: " + toString) // For reinitialize transaction after sending it over the wire private[akka] def reinit = synchronized { diff --git a/akka-actors/src/main/scala/stm/TransactionManagement.scala b/akka-actors/src/main/scala/stm/TransactionManagement.scala index 6a3ee9abf8..8e63b9c0d1 100644 --- a/akka-actors/src/main/scala/stm/TransactionManagement.scala +++ b/akka-actors/src/main/scala/stm/TransactionManagement.scala @@ -8,24 +8,20 @@ import java.util.concurrent.atomic.AtomicBoolean import se.scalablesolutions.akka.util.Logging -import scala.collection.mutable.HashSet - import org.multiverse.api.ThreadLocalTransaction._ class StmException(msg: String) extends RuntimeException(msg) -class TransactionAwareWrapperException(val cause: Throwable, val tx: Option[Transaction]) extends RuntimeException(cause) { +class TransactionAwareWrapperException( + val cause: Throwable, val tx: Option[Transaction]) extends RuntimeException(cause) { override def toString(): String = "TransactionAwareWrapperException[" + cause + ", " + tx + "]" } object TransactionManagement extends TransactionManagement { import se.scalablesolutions.akka.Config._ - // FIXME reenable 'akka.stm.restart-on-collision' when new STM is in place - val RESTART_TRANSACTION_ON_COLLISION = false //akka.Kernel.config.getBool("akka.stm.restart-on-collision", true) - val TIME_WAITING_FOR_COMPLETION = config.getInt("akka.stm.wait-for-completion", 1000) - val NR_OF_TIMES_WAITING_FOR_COMPLETION = config.getInt("akka.stm.wait-nr-of-times", 3) - val MAX_NR_OF_RETRIES = config.getInt("akka.stm.max-nr-of-retries", 100) - val TRANSACTION_ENABLED = new AtomicBoolean(config.getBool("akka.stm.service", false)) + + val MAX_NR_OF_RETRIES = config.getInt("akka.stm.max-nr-of-retries", 100) + val TRANSACTION_ENABLED = new AtomicBoolean(config.getBool("akka.stm.service", false)) def isTransactionalityEnabled = TRANSACTION_ENABLED.get def disableTransactions = TRANSACTION_ENABLED.set(false) @@ -37,7 +33,6 @@ object TransactionManagement extends TransactionManagement { trait TransactionManagement extends Logging { import TransactionManagement.currentTransaction - private[akka] val activeTransactions = new HashSet[Transaction] private[akka] def createNewTransaction = currentTransaction.set(Some(new Transaction)) @@ -60,7 +55,5 @@ trait TransactionManagement extends Logging { private[akka] def incrementTransaction = if (isTransactionInScope) getTransactionInScope.increment private[akka] def decrementTransaction = if (isTransactionInScope) getTransactionInScope.decrement - - private[akka] def removeTransactionIfTopLevel(tx: Transaction) = if (tx.isTopLevel) { activeTransactions -= tx } } diff --git a/akka-actors/src/main/scala/stm/TransactionalState.scala b/akka-actors/src/main/scala/stm/TransactionalState.scala index bd89a41224..16fc4f31f8 100644 --- a/akka-actors/src/main/scala/stm/TransactionalState.scala +++ b/akka-actors/src/main/scala/stm/TransactionalState.scala @@ -44,8 +44,7 @@ object TransactionalState { */ @serializable trait Transactional { - // FIXME: won't work across the remote machines, use [http://johannburkard.de/software/uuid/] - var uuid = Uuid.newUuid.toString + val uuid: String } /** @@ -75,6 +74,7 @@ object TransactionalRef { */ class TransactionalRef[T] extends Transactional { import org.multiverse.api.ThreadLocalTransaction._ + val uuid = Uuid.newUuid.toString private[this] val ref: Ref[T] = atomic { new Ref } @@ -126,6 +126,8 @@ object TransactionalMap { */ class TransactionalMap[K, V] extends Transactional with scala.collection.mutable.Map[K, V] { protected[this] val ref = TransactionalRef[HashTrie[K, V]] + val uuid = Uuid.newUuid.toString + ref.swap(new HashTrie[K, V]) def -=(key: K) = remove(key) @@ -176,7 +178,10 @@ object TransactionalVector { * @author Jonas Bonér */ class TransactionalVector[T] extends Transactional with RandomAccessSeq[T] { + val uuid = Uuid.newUuid.toString + private[this] val ref = TransactionalRef[Vector[T]] + ref.swap(EmptyVector) def clear = ref.swap(EmptyVector) diff --git a/akka-persistence/src/main/scala/PersistentState.scala b/akka-persistence/src/main/scala/PersistentState.scala index 3a63ea16f9..f08d2cd925 100644 --- a/akka-persistence/src/main/scala/PersistentState.scala +++ b/akka-persistence/src/main/scala/PersistentState.scala @@ -4,9 +4,11 @@ package se.scalablesolutions.akka.state -import util.Logging import se.scalablesolutions.akka.stm.TransactionManagement.currentTransaction import se.scalablesolutions.akka.collection._ +import se.scalablesolutions.akka.util.Logging + +import org.codehaus.aspectwerkz.proxy.Uuid class NoTransactionInScopeException extends RuntimeException @@ -18,34 +20,67 @@ case class TokyoCabinetStorageConfig() extends PersistentStorageConfig case class MongoStorageConfig() extends PersistentStorageConfig /** - * Example Scala usage: + * Example Scala usage. + *

+ * New map with generated id. *

  * val myMap = PersistentState.newMap(CassandraStorageConfig)
  * 
- *

+ * + * New map with user-defined id. + *

+ * val myMap = PersistentState.newMap(CassandraStorageConfig, id)
+ * 
+ * + * Get map by user-defined id. + *
+ * val myMap = PersistentState.getMap(CassandraStorageConfig, id)
+ * 
+ * * Example Java usage: *
  * TransactionalMap myMap = PersistentState.newMap(new CassandraStorageConfig());
  * 
+ * + * @author Jonas Bonér */ object PersistentState { - def newMap(config: PersistentStorageConfig): PersistentMap = config match { - case CassandraStorageConfig() => new CassandraPersistentMap - case MongoStorageConfig() => new MongoPersistentMap + def newMap(config: PersistentStorageConfig): PersistentMap = + // FIXME: won't work across the remote machines, use [http://johannburkard.de/software/uuid/] + newMap(config, Uuid.newUuid.toString) + + def newVector(config: PersistentStorageConfig): PersistentVector = + newVector(config, Uuid.newUuid.toString) + + def newRef(config: PersistentStorageConfig): PersistentRef = + newRef(config, Uuid.newUuid.toString) + + def getMap(config: PersistentStorageConfig, id: String): PersistentMap = + newMap(config, id) + + def getVector(config: PersistentStorageConfig, id: String): PersistentVector = + newVector(config, id) + + def getRef(config: PersistentStorageConfig, id: String): PersistentRef = + newRef(config, id) + + def newMap(config: PersistentStorageConfig, id: String): PersistentMap = config match { + case CassandraStorageConfig() => new CassandraPersistentMap(id) + case MongoStorageConfig() => new MongoPersistentMap(id) case TerracottaStorageConfig() => throw new UnsupportedOperationException case TokyoCabinetStorageConfig() => throw new UnsupportedOperationException } - def newVector(config: PersistentStorageConfig): PersistentVector = config match { - case CassandraStorageConfig() => new CassandraPersistentVector - case MongoStorageConfig() => new MongoPersistentVector + def newVector(config: PersistentStorageConfig, id: String): PersistentVector = config match { + case CassandraStorageConfig() => new CassandraPersistentVector(id) + case MongoStorageConfig() => new MongoPersistentVector(id) case TerracottaStorageConfig() => throw new UnsupportedOperationException case TokyoCabinetStorageConfig() => throw new UnsupportedOperationException } - def newRef(config: PersistentStorageConfig): PersistentRef = config match { - case CassandraStorageConfig() => new CassandraPersistentRef - case MongoStorageConfig() => new MongoPersistentRef + def newRef(config: PersistentStorageConfig, id: String): PersistentRef = config match { + case CassandraStorageConfig() => new CassandraPersistentRef(id) + case MongoStorageConfig() => new MongoPersistentRef(id) case TerracottaStorageConfig() => throw new UnsupportedOperationException case TokyoCabinetStorageConfig() => throw new UnsupportedOperationException } @@ -60,7 +95,8 @@ object PersistentState { * * @author Jonas Bonér */ -trait PersistentMap extends scala.collection.mutable.Map[AnyRef, AnyRef] with Transactional with Committable with Logging { +trait PersistentMap extends scala.collection.mutable.Map[AnyRef, AnyRef] + with Transactional with Committable with Logging { protected val newAndUpdatedEntries = TransactionalState.newMap[AnyRef, AnyRef] protected val removedEntries = TransactionalState.newVector[AnyRef] protected val shouldClearOnCommit = TransactionalRef[Boolean]() @@ -71,7 +107,8 @@ trait PersistentMap extends scala.collection.mutable.Map[AnyRef, AnyRef] with Tr def commit = { storage.removeMapStorageFor(uuid, removedEntries.toList) storage.insertMapStorageEntriesFor(uuid, newAndUpdatedEntries.toList) - if (shouldClearOnCommit.isDefined && shouldClearOnCommit.get.get) storage.removeMapStorageFor(uuid) + if (shouldClearOnCommit.isDefined && shouldClearOnCommit.get.get) + storage.removeMapStorageFor(uuid) newAndUpdatedEntries.clear removedEntries.clear } @@ -95,9 +132,11 @@ trait PersistentMap extends scala.collection.mutable.Map[AnyRef, AnyRef] with Tr removedEntries.add(key) } - def slice(start: Option[AnyRef], count: Int): List[Tuple2[AnyRef, AnyRef]] = slice(start, None, count) + def slice(start: Option[AnyRef], count: Int): List[Tuple2[AnyRef, AnyRef]] = + slice(start, None, count) - def slice(start: Option[AnyRef], finish: Option[AnyRef], count: Int): List[Tuple2[AnyRef, AnyRef]] = try { + def slice(start: Option[AnyRef], finish: Option[AnyRef], count: Int): + List[Tuple2[AnyRef, AnyRef]] = try { storage.getMapStorageRangeFor(uuid, start, finish, count) } catch { case e: Exception => Nil } @@ -107,7 +146,8 @@ trait PersistentMap extends scala.collection.mutable.Map[AnyRef, AnyRef] with Tr } override def contains(key: AnyRef): Boolean = try { - newAndUpdatedEntries.contains(key) || storage.getMapStorageEntryFor(uuid, key).isDefined + newAndUpdatedEntries.contains(key) || + storage.getMapStorageEntryFor(uuid, key).isDefined } catch { case e: Exception => false } override def size: Int = try { @@ -148,22 +188,22 @@ trait PersistentMap extends scala.collection.mutable.Map[AnyRef, AnyRef] with Tr } /** - * Implements a persistent transaction - - al map based on the Cassandra distributed P2P key-value storage. + * Implements a persistent transactional map based on the Cassandra distributed P2P key-value storage. * - * @author Debasish Ghosh + * @author Jonas Bonér */ -class CassandraPersistentMap extends PersistentMap { +class CassandraPersistentMap(id: String) extends PersistentMap { + val uuid = id val storage = CassandraStorage } /** - * Implements a persistent transactional map based on the MongoDB distributed P2P key-value storage. + * Implements a persistent transactional map based on the MongoDB document storage. * * @author Debasish Ghosh */ -class MongoPersistentMap extends PersistentMap { +class MongoPersistentMap(id: String) extends PersistentMap { + val uuid = id val storage = MongoStorage } @@ -244,20 +284,24 @@ trait PersistentVector extends RandomAccessSeq[AnyRef] with Transactional with C } /** - * Implements a persistent transactional vector based on the Cassandra distributed P2P key-value storage. + * Implements a persistent transactional vector based on the Cassandra + * distributed P2P key-value storage. * * @author Jonas Bonér */ -class CassandraPersistentVector extends PersistentVector { +class CassandraPersistentVector(id: String) extends PersistentVector { + val uuid = id val storage = CassandraStorage } /** - * Implements a persistent transactional vector based on the MongoDB distributed P2P key-value storage. + * Implements a persistent transactional vector based on the MongoDB + * document storage. * * @author Debaissh Ghosh */ -class MongoPersistentVector extends PersistentVector { +class MongoPersistentVector(id: String) extends PersistentVector { + val uuid = id val storage = MongoStorage } @@ -297,10 +341,12 @@ trait PersistentRef extends Transactional with Committable { } } -class CassandraPersistentRef extends PersistentRef { +class CassandraPersistentRef(id: String) extends PersistentRef { + val uuid = id val storage = CassandraStorage } -class MongoPersistentRef extends PersistentRef { +class MongoPersistentRef(id: String) extends PersistentRef { + val uuid = id val storage = MongoStorage } diff --git a/config/akka-reference.conf b/config/akka-reference.conf index 8ca35927e9..3fa382f252 100644 --- a/config/akka-reference.conf +++ b/config/akka-reference.conf @@ -28,6 +28,7 @@ service = on + max-nr-of-retries = 100 distributed = off # not implemented yet From 968896e8802cbd1d2043154b94e5ccf9418517a4 Mon Sep 17 00:00:00 2001 From: "ross.mcdonald" Date: Mon, 30 Nov 2009 16:32:36 +0000 Subject: [PATCH 2/8] typos in modified actor --- akka-actors/src/main/scala/actor/Actor.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/akka-actors/src/main/scala/actor/Actor.scala b/akka-actors/src/main/scala/actor/Actor.scala index 695fc5198a..0ef59286f1 100644 --- a/akka-actors/src/main/scala/actor/Actor.scala +++ b/akka-actors/src/main/scala/actor/Actor.scala @@ -411,7 +411,7 @@ trait Actor extends TransactionManagement { * Starts up the actor and its message queue. */ def start: Actor = synchronized { - if (_isShutDown) throw new IllegalStateException("Can't restart an actor that have been shut down with 'exit'") + if (_isShutDown) throw new IllegalStateException("Can't restart an actor that has been shut down with 'exit'") if (!_isRunning) { dispatcher.registerHandler(this, new ActorMessageInvoker(this)) messageDispatcher.start @@ -530,10 +530,10 @@ trait Actor extends TransactionManagement { def !![T](message: AnyRef): Option[T] = !![T](message, timeout) /** - * This method is evil and have been removed. Use '!!' with a timeout instead. + * This method is evil and has been removed. Use '!!' with a timeout instead. */ def !?[T](message: AnyRef): T = throw new UnsupportedOperationException( - "'!?' is evil and have been removed. Use '!!' with a timeout instead") + "'!?' is evil and has been removed. Use '!!' with a timeout instead") /** * Use reply(..) to reply with a message to the original sender of the message currently From 8bb370675abdbfc2b2fef439315d2fcfa80e3584 Mon Sep 17 00:00:00 2001 From: jboner Date: Mon, 30 Nov 2009 18:42:36 +0100 Subject: [PATCH 3/8] edit of logging --- akka-actors/src/main/scala/actor/Actor.scala | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/akka-actors/src/main/scala/actor/Actor.scala b/akka-actors/src/main/scala/actor/Actor.scala index 695fc5198a..03153f2f19 100644 --- a/akka-actors/src/main/scala/actor/Actor.scala +++ b/akka-actors/src/main/scala/actor/Actor.scala @@ -552,7 +552,8 @@ trait Actor extends TransactionManagement { "\n\t\t1. Send a message to a remote actor" + "\n\t\t2. Send a message from an instance that is *not* an actor" + "\n\t\t3. Send a message to an Active Object annotated with the '@oneway' annotation? " + - "\n\tIf so, switch to '!!' (or remove '@oneway') which passes on an implicit future that will be bound by the argument passed to 'reply'." ) + "\n\tIf so, switch to '!!' (or remove '@oneway') which passes on an implicit future" + + "\n\tthat will be bound by the argument passed to 'reply'." ) case Some(future) => future.completeWithResult(message) } @@ -632,7 +633,8 @@ trait Actor extends TransactionManagement { */ protected[this] def unlink(actor: Actor) = { if (_isRunning) { - if (!getLinkedActors.contains(actor)) throw new IllegalStateException("Actor [" + actor + "] is not a linked actor, can't unlink") + if (!getLinkedActors.contains(actor)) throw new IllegalStateException( + "Actor [" + actor + "] is not a linked actor, can't unlink") getLinkedActors.remove(actor) actor._supervisor = None Actor.log.debug("Unlinking actor [%s] from actor [%s]", actor, this) From 174ca6a63c2d30ad5198759c2a5ba208e427a790 Mon Sep 17 00:00:00 2001 From: jboner Date: Mon, 30 Nov 2009 20:19:30 +0100 Subject: [PATCH 4/8] Fixed issue #35: @transactionrequired as config element in declarative config --- .../src/main/scala/actor/ActiveObject.scala | 108 +++++++++++++++--- .../ActiveObjectGuiceConfigurator.scala | 23 ++-- .../src/main/scala/config/Config.scala | 80 ++++++++++--- .../src/main/scala/config/Configurator.scala | 5 +- 4 files changed, 174 insertions(+), 42 deletions(-) diff --git a/akka-actors/src/main/scala/actor/ActiveObject.scala b/akka-actors/src/main/scala/actor/ActiveObject.scala index f6b45bcf53..d3584ed93b 100644 --- a/akka-actors/src/main/scala/actor/ActiveObject.scala +++ b/akka-actors/src/main/scala/actor/ActiveObject.scala @@ -37,73 +37,145 @@ object ActiveObject { val AKKA_CAMEL_ROUTING_SCHEME = "akka" def newInstance[T](target: Class[T], timeout: Long): T = - newInstance(target, new Dispatcher(None), None, timeout) + newInstance(target, new Dispatcher(false, None), None, timeout) def newInstance[T](target: Class[T], timeout: Long, restartCallbacks: Option[RestartCallbacks]): T = - newInstance(target, new Dispatcher(restartCallbacks), None, timeout) + newInstance(target, new Dispatcher(false, restartCallbacks), None, timeout) def newInstance[T](intf: Class[T], target: AnyRef, timeout: Long): T = - newInstance(intf, target, new Dispatcher(None), None, timeout) + newInstance(intf, target, new Dispatcher(false, None), None, timeout) def newInstance[T](intf: Class[T], target: AnyRef, timeout: Long, restartCallbacks: Option[RestartCallbacks]): T = - newInstance(intf, target, new Dispatcher(restartCallbacks), None, timeout) + newInstance(intf, target, new Dispatcher(false, restartCallbacks), None, timeout) + + def newInstance[T](target: Class[T], timeout: Long, transactionRequired: Boolean): T = + newInstance(target, new Dispatcher(transactionRequired, None), None, timeout) + + def newInstance[T](target: Class[T], timeout: Long, transactionRequired: Boolean, restartCallbacks: Option[RestartCallbacks]): T = + newInstance(target, new Dispatcher(transactionRequired, restartCallbacks), None, timeout) + + def newInstance[T](intf: Class[T], target: AnyRef, timeout: Long, transactionRequired: Boolean): T = + newInstance(intf, target, new Dispatcher(transactionRequired, None), None, timeout) + + def newInstance[T](intf: Class[T], target: AnyRef, timeout: Long, transactionRequired: Boolean, restartCallbacks: Option[RestartCallbacks]): T = + newInstance(intf, target, new Dispatcher(transactionRequired, restartCallbacks), None, timeout) def newRemoteInstance[T](target: Class[T], timeout: Long, hostname: String, port: Int): T = - newInstance(target, new Dispatcher(None), Some(new InetSocketAddress(hostname, port)), timeout) + newInstance(target, new Dispatcher(false, None), Some(new InetSocketAddress(hostname, port)), timeout) def newRemoteInstance[T](target: Class[T], timeout: Long, hostname: String, port: Int, restartCallbacks: Option[RestartCallbacks]): T = - newInstance(target, new Dispatcher(restartCallbacks), Some(new InetSocketAddress(hostname, port)), timeout) + newInstance(target, new Dispatcher(false, restartCallbacks), Some(new InetSocketAddress(hostname, port)), timeout) def newRemoteInstance[T](intf: Class[T], target: AnyRef, timeout: Long, hostname: String, port: Int): T = - newInstance(intf, target, new Dispatcher(None), Some(new InetSocketAddress(hostname, port)), timeout) + newInstance(intf, target, new Dispatcher(false, None), Some(new InetSocketAddress(hostname, port)), timeout) def newRemoteInstance[T](intf: Class[T], target: AnyRef, timeout: Long, hostname: String, port: Int, restartCallbacks: Option[RestartCallbacks]): T = - newInstance(intf, target, new Dispatcher(restartCallbacks), Some(new InetSocketAddress(hostname, port)), timeout) + newInstance(intf, target, new Dispatcher(false, restartCallbacks), Some(new InetSocketAddress(hostname, port)), timeout) + + def newRemoteInstance[T](target: Class[T], timeout: Long, transactionRequired: Boolean, hostname: String, port: Int): T = + newInstance(target, new Dispatcher(transactionRequired, None), Some(new InetSocketAddress(hostname, port)), timeout) + + def newRemoteInstance[T](target: Class[T], timeout: Long, transactionRequired: Boolean, hostname: String, port: Int, restartCallbacks: Option[RestartCallbacks]): T = + newInstance(target, new Dispatcher(transactionRequired, restartCallbacks), Some(new InetSocketAddress(hostname, port)), timeout) + + def newRemoteInstance[T](intf: Class[T], target: AnyRef, timeout: Long, transactionRequired: Boolean, hostname: String, port: Int): T = + newInstance(intf, target, new Dispatcher(transactionRequired, None), Some(new InetSocketAddress(hostname, port)), timeout) + + def newRemoteInstance[T](intf: Class[T], target: AnyRef, timeout: Long, transactionRequired: Boolean, hostname: String, port: Int, restartCallbacks: Option[RestartCallbacks]): T = + newInstance(intf, target, new Dispatcher(transactionRequired, restartCallbacks), Some(new InetSocketAddress(hostname, port)), timeout) def newInstance[T](target: Class[T], timeout: Long, dispatcher: MessageDispatcher): T = { - val actor = new Dispatcher(None) + val actor = new Dispatcher(false, None) actor.messageDispatcher = dispatcher newInstance(target, actor, None, timeout) } def newInstance[T](target: Class[T], timeout: Long, dispatcher: MessageDispatcher, restartCallbacks: Option[RestartCallbacks]): T = { - val actor = new Dispatcher(restartCallbacks) + val actor = new Dispatcher(false, restartCallbacks) actor.messageDispatcher = dispatcher newInstance(target, actor, None, timeout) } def newInstance[T](intf: Class[T], target: AnyRef, timeout: Long, dispatcher: MessageDispatcher): T = { - val actor = new Dispatcher(None) + val actor = new Dispatcher(false, None) actor.messageDispatcher = dispatcher newInstance(intf, target, actor, None, timeout) } def newInstance[T](intf: Class[T], target: AnyRef, timeout: Long, dispatcher: MessageDispatcher, restartCallbacks: Option[RestartCallbacks]): T = { - val actor = new Dispatcher(restartCallbacks) + val actor = new Dispatcher(false, restartCallbacks) + actor.messageDispatcher = dispatcher + newInstance(intf, target, actor, None, timeout) + } + + def newInstance[T](target: Class[T], timeout: Long, transactionRequired: Boolean, dispatcher: MessageDispatcher): T = { + val actor = new Dispatcher(transactionRequired, None) + actor.messageDispatcher = dispatcher + newInstance(target, actor, None, timeout) + } + + def newInstance[T](target: Class[T], timeout: Long, transactionRequired: Boolean, dispatcher: MessageDispatcher, restartCallbacks: Option[RestartCallbacks]): T = { + val actor = new Dispatcher(transactionRequired, restartCallbacks) + actor.messageDispatcher = dispatcher + newInstance(target, actor, None, timeout) + } + + def newInstance[T](intf: Class[T], target: AnyRef, timeout: Long, transactionRequired: Boolean, dispatcher: MessageDispatcher): T = { + val actor = new Dispatcher(transactionRequired, None) + actor.messageDispatcher = dispatcher + newInstance(intf, target, actor, None, timeout) + } + + def newInstance[T](intf: Class[T], target: AnyRef, timeout: Long, transactionRequired: Boolean, dispatcher: MessageDispatcher, restartCallbacks: Option[RestartCallbacks]): T = { + val actor = new Dispatcher(transactionRequired, restartCallbacks) actor.messageDispatcher = dispatcher newInstance(intf, target, actor, None, timeout) } def newRemoteInstance[T](target: Class[T], timeout: Long, dispatcher: MessageDispatcher, hostname: String, port: Int): T = { - val actor = new Dispatcher(None) + val actor = new Dispatcher(false, None) actor.messageDispatcher = dispatcher newInstance(target, actor, Some(new InetSocketAddress(hostname, port)), timeout) } def newRemoteInstance[T](target: Class[T], timeout: Long, dispatcher: MessageDispatcher, hostname: String, port: Int, restartCallbacks: Option[RestartCallbacks]): T = { - val actor = new Dispatcher(restartCallbacks) + val actor = new Dispatcher(false, restartCallbacks) actor.messageDispatcher = dispatcher newInstance(target, actor, Some(new InetSocketAddress(hostname, port)), timeout) } def newRemoteInstance[T](intf: Class[T], target: AnyRef, timeout: Long, dispatcher: MessageDispatcher, hostname: String, port: Int): T = { - val actor = new Dispatcher(None) + val actor = new Dispatcher(false, None) actor.messageDispatcher = dispatcher newInstance(intf, target, actor, Some(new InetSocketAddress(hostname, port)), timeout) } def newRemoteInstance[T](intf: Class[T], target: AnyRef, timeout: Long, dispatcher: MessageDispatcher, hostname: String, port: Int, restartCallbacks: Option[RestartCallbacks]): T = { - val actor = new Dispatcher(restartCallbacks) + val actor = new Dispatcher(false, restartCallbacks) + actor.messageDispatcher = dispatcher + newInstance(intf, target, actor, Some(new InetSocketAddress(hostname, port)), timeout) + } + + def newRemoteInstance[T](target: Class[T], timeout: Long, transactionRequired: Boolean, dispatcher: MessageDispatcher, hostname: String, port: Int): T = { + val actor = new Dispatcher(transactionRequired, None) + actor.messageDispatcher = dispatcher + newInstance(target, actor, Some(new InetSocketAddress(hostname, port)), timeout) + } + + def newRemoteInstance[T](target: Class[T], timeout: Long, transactionRequired: Boolean, dispatcher: MessageDispatcher, hostname: String, port: Int, restartCallbacks: Option[RestartCallbacks]): T = { + val actor = new Dispatcher(transactionRequired, restartCallbacks) + actor.messageDispatcher = dispatcher + newInstance(target, actor, Some(new InetSocketAddress(hostname, port)), timeout) + } + + def newRemoteInstance[T](intf: Class[T], target: AnyRef, timeout: Long, transactionRequired: Boolean, dispatcher: MessageDispatcher, hostname: String, port: Int): T = { + val actor = new Dispatcher(transactionRequired, None) + actor.messageDispatcher = dispatcher + newInstance(intf, target, actor, Some(new InetSocketAddress(hostname, port)), timeout) + } + + def newRemoteInstance[T](intf: Class[T], target: AnyRef, timeout: Long, transactionRequired: Boolean, dispatcher: MessageDispatcher, hostname: String, port: Int, restartCallbacks: Option[RestartCallbacks]): T = { + val actor = new Dispatcher(transactionRequired, restartCallbacks) actor.messageDispatcher = dispatcher newInstance(intf, target, actor, Some(new InetSocketAddress(hostname, port)), timeout) } @@ -282,7 +354,7 @@ private[akka] sealed class ActiveObjectAspect { * * @author Jonas Bonér */ -private[akka] class Dispatcher(val callbacks: Option[RestartCallbacks]) extends Actor { +private[akka] class Dispatcher(transactionalRequired: Boolean, val callbacks: Option[RestartCallbacks]) extends Actor { private val ZERO_ITEM_CLASS_ARRAY = Array[Class[_]]() private val ZERO_ITEM_OBJECT_ARRAY = Array[Object[_]]() @@ -292,7 +364,7 @@ private[akka] class Dispatcher(val callbacks: Option[RestartCallbacks]) extends private var initTxState: Option[Method] = None private[actor] def initialize(targetClass: Class[_], targetInstance: AnyRef) = { - if (targetClass.isAnnotationPresent(Annotations.transactionrequired)) makeTransactionRequired + if (transactionalRequired || targetClass.isAnnotationPresent(Annotations.transactionrequired)) makeTransactionRequired id = targetClass.getName target = Some(targetInstance) val methods = targetInstance.getClass.getDeclaredMethods.toList diff --git a/akka-actors/src/main/scala/config/ActiveObjectGuiceConfigurator.scala b/akka-actors/src/main/scala/config/ActiveObjectGuiceConfigurator.scala index 04f90c331d..93a1e9c4e2 100644 --- a/akka-actors/src/main/scala/config/ActiveObjectGuiceConfigurator.scala +++ b/akka-actors/src/main/scala/config/ActiveObjectGuiceConfigurator.scala @@ -19,6 +19,8 @@ import java.net.InetSocketAddress import java.lang.reflect.Method /** + * This is an class for internal usage. Instead use the se.scalablesolutions.akka.config.ActiveObjectConfigurator class for creating ActiveObjects. + * * @author Jonas Bonér */ private[akka] class ActiveObjectGuiceConfigurator extends ActiveObjectConfiguratorBase with Logging { // with CamelConfigurator { @@ -44,9 +46,12 @@ private[akka] class ActiveObjectGuiceConfigurator extends ActiveObjectConfigurat */ override def getInstance[T](clazz: Class[T]): T = synchronized { log.debug("Retrieving active object [%s]", clazz.getName) - if (injector == null) throw new IllegalStateException("inject() and/or supervise() must be called before invoking getInstance(clazz)") + if (injector == null) throw new IllegalStateException( + "inject() and/or supervise() must be called before invoking getInstance(clazz)") val (proxy, targetInstance, component) = - activeObjectRegistry.getOrElse(clazz, throw new IllegalStateException("Class [" + clazz.getName + "] has not been put under supervision (by passing in the config to the 'configure' and then invoking 'supervise') method")) + activeObjectRegistry.getOrElse(clazz, throw new IllegalStateException( + "Class [" + clazz.getName + "] has not been put under supervision " + + "(by passing in the config to the 'configure' and then invoking 'supervise') method")) injector.injectMembers(targetInstance) proxy.asInstanceOf[T] } @@ -96,10 +101,12 @@ private[akka] class ActiveObjectGuiceConfigurator extends ActiveObjectConfigurat private def newSubclassingProxy(component: Component): DependencyBinding = { val targetClass = component.target - val actor = new Dispatcher(component.lifeCycle.callbacks) + val actor = new Dispatcher(component.transactionRequired, component.lifeCycle.callbacks) if (component.dispatcher.isDefined) actor.swapDispatcher(component.dispatcher.get) val remoteAddress = - if (component.remoteAddress.isDefined) Some(new InetSocketAddress(component.remoteAddress.get.hostname, component.remoteAddress.get.port)) + if (component.remoteAddress.isDefined) + Some(new InetSocketAddress( + component.remoteAddress.get.hostname, component.remoteAddress.get.port)) else None val proxy = ActiveObject.newInstance(targetClass, actor, remoteAddress, component.timeout).asInstanceOf[AnyRef] supervised ::= Supervise(actor, component.lifeCycle) @@ -111,12 +118,14 @@ private[akka] class ActiveObjectGuiceConfigurator extends ActiveObjectConfigurat val targetClass = component.intf.get val targetInstance = component.target.newInstance.asInstanceOf[AnyRef] // TODO: perhaps need to put in registry component.target.getConstructor(Array[Class[_]](): _*).setAccessible(true) - val actor = new Dispatcher(component.lifeCycle.callbacks) + val actor = new Dispatcher(component.transactionRequired, component.lifeCycle.callbacks) if (component.dispatcher.isDefined) actor.swapDispatcher(component.dispatcher.get) val remoteAddress = - if (component.remoteAddress.isDefined) Some(new InetSocketAddress(component.remoteAddress.get.hostname, component.remoteAddress.get.port)) + if (component.remoteAddress.isDefined) + Some(new InetSocketAddress(component.remoteAddress.get.hostname, component.remoteAddress.get.port)) else None - val proxy = ActiveObject.newInstance(targetClass, targetInstance, actor, remoteAddress, component.timeout).asInstanceOf[AnyRef] + val proxy = ActiveObject.newInstance( + targetClass, targetInstance, actor, remoteAddress, component.timeout).asInstanceOf[AnyRef] supervised ::= Supervise(actor, component.lifeCycle) activeObjectRegistry.put(targetClass, (proxy, targetInstance, component)) new DependencyBinding(targetClass, proxy) diff --git a/akka-actors/src/main/scala/config/Config.scala b/akka-actors/src/main/scala/config/Config.scala index 39899b73d5..be6c9de707 100644 --- a/akka-actors/src/main/scala/config/Config.scala +++ b/akka-actors/src/main/scala/config/Config.scala @@ -44,6 +44,7 @@ object ScalaConfig { val target: Class[_], val lifeCycle: LifeCycle, val timeout: Int, + val transactionRequired: Boolean, _dispatcher: MessageDispatcher, // optional _remoteAddress: RemoteAddress // optional ) extends Server { @@ -53,28 +54,52 @@ object ScalaConfig { } object Component { def apply(intf: Class[_], target: Class[_], lifeCycle: LifeCycle, timeout: Int) = - new Component(intf, target, lifeCycle, timeout, null, null) + new Component(intf, target, lifeCycle, timeout, false, null, null) def apply(target: Class[_], lifeCycle: LifeCycle, timeout: Int) = - new Component(null, target, lifeCycle, timeout, null, null) + new Component(null, target, lifeCycle, timeout, false, null, null) def apply(intf: Class[_], target: Class[_], lifeCycle: LifeCycle, timeout: Int, dispatcher: MessageDispatcher) = - new Component(intf, target, lifeCycle, timeout, dispatcher, null) + new Component(intf, target, lifeCycle, timeout, false, dispatcher, null) def apply(target: Class[_], lifeCycle: LifeCycle, timeout: Int, dispatcher: MessageDispatcher) = - new Component(null, target, lifeCycle, timeout, dispatcher, null) + new Component(null, target, lifeCycle, timeout, false, dispatcher, null) def apply(intf: Class[_], target: Class[_], lifeCycle: LifeCycle, timeout: Int, remoteAddress: RemoteAddress) = - new Component(intf, target, lifeCycle, timeout, null, remoteAddress) + new Component(intf, target, lifeCycle, timeout, false, null, remoteAddress) def apply(target: Class[_], lifeCycle: LifeCycle, timeout: Int, remoteAddress: RemoteAddress) = - new Component(null, target, lifeCycle, timeout, null, remoteAddress) + new Component(null, target, lifeCycle, timeout, false, null, remoteAddress) def apply(intf: Class[_], target: Class[_], lifeCycle: LifeCycle, timeout: Int, dispatcher: MessageDispatcher, remoteAddress: RemoteAddress) = - new Component(intf, target, lifeCycle, timeout, dispatcher, remoteAddress) + new Component(intf, target, lifeCycle, timeout, false, dispatcher, remoteAddress) def apply(target: Class[_], lifeCycle: LifeCycle, timeout: Int, dispatcher: MessageDispatcher, remoteAddress: RemoteAddress) = - new Component(null, target, lifeCycle, timeout, dispatcher, remoteAddress) + new Component(null, target, lifeCycle, timeout, false, dispatcher, remoteAddress) + + def apply(intf: Class[_], target: Class[_], lifeCycle: LifeCycle, timeout: Int, transactionRequired: Boolean) = + new Component(intf, target, lifeCycle, timeout, transactionRequired, null, null) + + def apply(target: Class[_], lifeCycle: LifeCycle, timeout: Int, transactionRequired: Boolean) = + new Component(null, target, lifeCycle, timeout, transactionRequired, null, null) + + def apply(intf: Class[_], target: Class[_], lifeCycle: LifeCycle, timeout: Int, transactionRequired: Boolean, dispatcher: MessageDispatcher) = + new Component(intf, target, lifeCycle, timeout, transactionRequired, dispatcher, null) + + def apply(target: Class[_], lifeCycle: LifeCycle, timeout: Int, transactionRequired: Boolean, dispatcher: MessageDispatcher) = + new Component(null, target, lifeCycle, timeout, transactionRequired, dispatcher, null) + + def apply(intf: Class[_], target: Class[_], lifeCycle: LifeCycle, timeout: Int, transactionRequired: Boolean, remoteAddress: RemoteAddress) = + new Component(intf, target, lifeCycle, timeout, transactionRequired, null, remoteAddress) + + def apply(target: Class[_], lifeCycle: LifeCycle, timeout: Int, transactionRequired: Boolean, remoteAddress: RemoteAddress) = + new Component(null, target, lifeCycle, timeout, transactionRequired, null, remoteAddress) + + def apply(intf: Class[_], target: Class[_], lifeCycle: LifeCycle, timeout: Int, transactionRequired: Boolean, dispatcher: MessageDispatcher, remoteAddress: RemoteAddress) = + new Component(intf, target, lifeCycle, timeout, transactionRequired, dispatcher, remoteAddress) + + def apply(target: Class[_], lifeCycle: LifeCycle, timeout: Int, transactionRequired: Boolean, dispatcher: MessageDispatcher, remoteAddress: RemoteAddress) = + new Component(null, target, lifeCycle, timeout, transactionRequired, dispatcher, remoteAddress) } } @@ -133,33 +158,56 @@ object JavaConfig { @BeanProperty val target: Class[_], @BeanProperty val lifeCycle: LifeCycle, @BeanProperty val timeout: Int, + @BeanProperty val transactionRequired: Boolean, // optional @BeanProperty val dispatcher: MessageDispatcher, // optional @BeanProperty val remoteAddress: RemoteAddress // optional ) extends Server { def this(intf: Class[_], target: Class[_], lifeCycle: LifeCycle, timeout: Int) = - this(intf, target, lifeCycle, timeout, null, null) + this(intf, target, lifeCycle, timeout, false, null, null) def this(target: Class[_], lifeCycle: LifeCycle, timeout: Int) = - this(null, target, lifeCycle, timeout, null, null) + this(null, target, lifeCycle, timeout, false, null, null) def this(intf: Class[_], target: Class[_], lifeCycle: LifeCycle, timeout: Int, remoteAddress: RemoteAddress) = - this(intf, target, lifeCycle, timeout, null, remoteAddress) + this(intf, target, lifeCycle, timeout, false, null, remoteAddress) def this(target: Class[_], lifeCycle: LifeCycle, timeout: Int, remoteAddress: RemoteAddress) = - this(null, target, lifeCycle, timeout, null, remoteAddress) + this(null, target, lifeCycle, timeout, false, null, remoteAddress) def this(intf: Class[_], target: Class[_], lifeCycle: LifeCycle, timeout: Int, dispatcher: MessageDispatcher) = - this(intf, target, lifeCycle, timeout, dispatcher, null) + this(intf, target, lifeCycle, timeout, false, dispatcher, null) def this(target: Class[_], lifeCycle: LifeCycle, timeout: Int, dispatcher: MessageDispatcher) = - this(null, target, lifeCycle, timeout, dispatcher, null) + this(null, target, lifeCycle, timeout, false, dispatcher, null) def this(target: Class[_], lifeCycle: LifeCycle, timeout: Int, dispatcher: MessageDispatcher, remoteAddress: RemoteAddress) = - this(null, target, lifeCycle, timeout, dispatcher, remoteAddress) + this(null, target, lifeCycle, timeout, false, dispatcher, remoteAddress) + + def this(intf: Class[_], target: Class[_], lifeCycle: LifeCycle, timeout: Int, transactionRequired: Boolean) = + this(intf, target, lifeCycle, timeout, transactionRequired, null, null) + + def this(target: Class[_], lifeCycle: LifeCycle, timeout: Int, transactionRequired: Boolean) = + this(null, target, lifeCycle, timeout, transactionRequired, null, null) + + def this(intf: Class[_], target: Class[_], lifeCycle: LifeCycle, timeout: Int, transactionRequired: Boolean, remoteAddress: RemoteAddress) = + this(intf, target, lifeCycle, timeout, transactionRequired, null, remoteAddress) + + def this(target: Class[_], lifeCycle: LifeCycle, timeout: Int, transactionRequired: Boolean, remoteAddress: RemoteAddress) = + this(null, target, lifeCycle, timeout, transactionRequired, null, remoteAddress) + + def this(intf: Class[_], target: Class[_], lifeCycle: LifeCycle, timeout: Int, transactionRequired: Boolean, dispatcher: MessageDispatcher) = + this(intf, target, lifeCycle, timeout, transactionRequired, dispatcher, null) + + def this(target: Class[_], lifeCycle: LifeCycle, timeout: Int, transactionRequired: Boolean, dispatcher: MessageDispatcher) = + this(null, target, lifeCycle, timeout, transactionRequired, dispatcher, null) + + def this(target: Class[_], lifeCycle: LifeCycle, timeout: Int, transactionRequired: Boolean, dispatcher: MessageDispatcher, remoteAddress: RemoteAddress) = + this(null, target, lifeCycle, timeout, transactionRequired, dispatcher, remoteAddress) def transform = - se.scalablesolutions.akka.config.ScalaConfig.Component(intf, target, lifeCycle.transform, timeout, dispatcher, + se.scalablesolutions.akka.config.ScalaConfig.Component( + intf, target, lifeCycle.transform, timeout, transactionRequired, dispatcher, if (remoteAddress != null) se.scalablesolutions.akka.config.ScalaConfig.RemoteAddress(remoteAddress.hostname, remoteAddress.port) else null) def newSupervised(actor: Actor) = diff --git a/akka-actors/src/main/scala/config/Configurator.scala b/akka-actors/src/main/scala/config/Configurator.scala index c87138169d..3da41f2e94 100644 --- a/akka-actors/src/main/scala/config/Configurator.scala +++ b/akka-actors/src/main/scala/config/Configurator.scala @@ -6,7 +6,10 @@ package se.scalablesolutions.akka.config import ScalaConfig.{RestartStrategy, Component} -trait Configurator { +/** + * Manages the active abject or actor that has been put under supervision for the class specified. + */ +private[akka] trait Configurator { /** * Returns the active abject or actor that has been put under supervision for the class specified. * From 741a3c2b8cd7f0c21367ff3e2f212faa215a0fba Mon Sep 17 00:00:00 2001 From: jboner Date: Mon, 30 Nov 2009 21:22:24 +0100 Subject: [PATCH 5/8] Added trapExceptions to declarative supervisor configuration --- .../src/main/scala/actor/Supervisor.scala | 33 ++++++++++--------- .../src/main/scala/config/Config.scala | 11 +++++-- .../src/test/scala/RemoteSupervisorTest.scala | 12 +++---- .../src/test/scala/SupervisorTest.scala | 12 +++---- .../ActiveObjectGuiceConfiguratorTest.java | 3 +- .../akka/api/InMemNestedStateTest.java | 2 +- .../akka/api/InMemoryStateTest.java | 2 +- .../akka/api/PersistentNestedStateTest.java | 2 +- .../akka/api/PersistentStateTest.java | 2 +- .../akka/api/RemotePersistentStateTest.java | 2 +- .../scalablesolutions/akka/api/RestTest.java | 2 +- .../src/main/java/sample/java/Boot.java | 2 +- .../main/scala/bootstrap/liftweb/Boot.scala | 2 +- .../src/main/scala/SimpleService.scala | 2 +- .../src/main/scala/SimpleService.scala | 2 +- 15 files changed, 50 insertions(+), 41 deletions(-) diff --git a/akka-actors/src/main/scala/actor/Supervisor.scala b/akka-actors/src/main/scala/actor/Supervisor.scala index a84779a917..e2c5e92ac2 100644 --- a/akka-actors/src/main/scala/actor/Supervisor.scala +++ b/akka-actors/src/main/scala/actor/Supervisor.scala @@ -23,7 +23,7 @@ case class OneForOneStrategy(maxNrOfRetries: Int, withinTimeRange: Int) extends *
  *  val factory = SupervisorFactory(
  *    SupervisorConfig(
- *      RestartStrategy(OneForOne, 3, 10),
+ *      RestartStrategy(OneForOne, 3, 10, List(classOf[Exception]),
  *      Supervise(
  *        myFirstActor,
  *        LifeCycle(Permanent)) ::
@@ -43,6 +43,7 @@ case class OneForOneStrategy(maxNrOfRetries: Int, withinTimeRange: Int) extends
  * @author Jonas Bonér
  */
 class SupervisorFactory(val config: SupervisorConfig) extends Logging {
+  type ExceptionList = List[Class[_ <: Throwable]]
 
   def newInstance: Supervisor = newInstanceFor(config)
 
@@ -55,10 +56,10 @@ class SupervisorFactory(val config: SupervisorConfig) extends Logging {
   }
 
   protected def create(strategy: RestartStrategy): Supervisor = strategy match {
-    case RestartStrategy(scheme, maxNrOfRetries, timeRange) =>
+    case RestartStrategy(scheme, maxNrOfRetries, timeRange, trapExceptions: ExceptionList) =>
       scheme match {
-        case AllForOne => new Supervisor(AllForOneStrategy(maxNrOfRetries, timeRange))
-        case OneForOne => new Supervisor(OneForOneStrategy(maxNrOfRetries, timeRange))
+        case AllForOne => new Supervisor(AllForOneStrategy(maxNrOfRetries, timeRange), trapExceptions)
+        case OneForOne => new Supervisor(OneForOneStrategy(maxNrOfRetries, timeRange), trapExceptions)
       }
   }
 }
@@ -79,21 +80,21 @@ object SupervisorFactory {
  *
  * @author Jonas Bonér
  */                                  
-sealed class Supervisor private[akka] (handler: FaultHandlingStrategy)
-  extends Actor with Logging with Configurator {  
-  trapExit = List(classOf[Throwable])
+sealed class Supervisor private[akka] (handler: FaultHandlingStrategy, trapExceptions: List[Class[_ <: Throwable]])
+  extends Actor with Logging with Configurator {
+  
+  trapExit = trapExceptions
   faultHandler = Some(handler)
   dispatcher = Dispatchers.newThreadBasedDispatcher(this)
 
-  val actors = new ConcurrentHashMap[String, Actor]
+  private val actors = new ConcurrentHashMap[String, Actor]
   
+  // Cheating, should really go through the dispatcher rather than direct access to a CHM
   def getInstance[T](clazz: Class[T]) = actors.get(clazz.getName).asInstanceOf[T]
-
   def getComponentInterfaces: List[Class[_]] = actors.values.toArray.toList.map(_.getClass)
-
   def isDefined(clazz: Class[_]): Boolean = actors.containsKey(clazz.getName)
 
-  override def start = synchronized {
+  override def start: Actor = synchronized {
     ConfiguratorRepository.registerConfigurator(this)
     getLinkedActors.toArray.toList.asInstanceOf[List[Actor]].foreach { actor =>
       actor.start
@@ -112,7 +113,7 @@ sealed class Supervisor private[akka] (handler: FaultHandlingStrategy)
   }
 
   def receive = {
-    case unknown => throw new IllegalArgumentException("Supervisor does not respond to any messages. Unknown message [" + unknown + "]")
+    case unknown => throw new IllegalArgumentException("Supervisor " + toString + " does not respond to any messages. Unknown message [" + unknown + "]")
   }
 
   def configure(config: SupervisorConfig, factory: SupervisorFactory) = config match {
@@ -124,9 +125,11 @@ sealed class Supervisor private[akka] (handler: FaultHandlingStrategy)
             actor.lifeCycle = Some(lifeCycle)
             startLink(actor)
 
-           case SupervisorConfig(_, _) => // recursive configuration
-             factory.newInstanceFor(server.asInstanceOf[SupervisorConfig]).start
-             // FIXME what to do with recursively supervisors?
+           case supervisorConfig @ SupervisorConfig(_, _) => // recursive supervisor configuration
+             val supervisor = factory.newInstanceFor(supervisorConfig).start
+             supervisor.lifeCycle = Some(LifeCycle(Permanent))
+             actors.put(supervisor.getClass.getName, supervisor)
+             link(supervisor)
         })
   }
 }
diff --git a/akka-actors/src/main/scala/config/Config.scala b/akka-actors/src/main/scala/config/Config.scala
index be6c9de707..136725cadd 100644
--- a/akka-actors/src/main/scala/config/Config.scala
+++ b/akka-actors/src/main/scala/config/Config.scala
@@ -22,7 +22,11 @@ object ScalaConfig {
   case class SupervisorConfig(restartStrategy: RestartStrategy, worker: List[Server]) extends Server
   case class Supervise(actor: Actor, lifeCycle: LifeCycle) extends Server
 
-  case class RestartStrategy(scheme: FailOverScheme, maxNrOfRetries: Int, withinTimeRange: Int) extends ConfigElement
+  case class RestartStrategy(
+      scheme: FailOverScheme,
+      maxNrOfRetries: Int,
+      withinTimeRange: Int,
+      trapExceptions: List[Class[_ <: Throwable]]) extends ConfigElement
 
   case object AllForOne extends FailOverScheme
   case object OneForOne extends FailOverScheme
@@ -114,9 +118,10 @@ object JavaConfig {
   class RestartStrategy(
       @BeanProperty val scheme: FailOverScheme,
       @BeanProperty val maxNrOfRetries: Int,
-      @BeanProperty val withinTimeRange: Int) extends ConfigElement {
+      @BeanProperty val withinTimeRange: Int,
+      @BeanProperty val trapExceptions: Array[Class[_ <: Throwable]]) extends ConfigElement {
     def transform = se.scalablesolutions.akka.config.ScalaConfig.RestartStrategy(
-      scheme.transform, maxNrOfRetries, withinTimeRange)
+      scheme.transform, maxNrOfRetries, withinTimeRange, trapExceptions.toList)
   }
   
   class LifeCycle(@BeanProperty val scope: Scope, @BeanProperty val callbacks: RestartCallbacks) extends ConfigElement {
diff --git a/akka-actors/src/test/scala/RemoteSupervisorTest.scala b/akka-actors/src/test/scala/RemoteSupervisorTest.scala
index 0fef2a2e6e..719c88359f 100644
--- a/akka-actors/src/test/scala/RemoteSupervisorTest.scala
+++ b/akka-actors/src/test/scala/RemoteSupervisorTest.scala
@@ -471,7 +471,7 @@ class RemoteSupervisorTest extends JUnitSuite {
 
     val factory = SupervisorFactory(
       SupervisorConfig(
-        RestartStrategy(AllForOne, 3, 100),
+        RestartStrategy(AllForOne, 3, 100, List(classOf[Exception])),
         Supervise(
           pingpong1,
           LifeCycle(Permanent))
@@ -486,7 +486,7 @@ class RemoteSupervisorTest extends JUnitSuite {
 
     val factory = SupervisorFactory(
       SupervisorConfig(
-        RestartStrategy(OneForOne, 3, 100),
+        RestartStrategy(OneForOne, 3, 100, List(classOf[Exception])),
         Supervise(
           pingpong1,
           LifeCycle(Permanent))
@@ -504,7 +504,7 @@ class RemoteSupervisorTest extends JUnitSuite {
 
     val factory = SupervisorFactory(
       SupervisorConfig(
-        RestartStrategy(AllForOne, 3, 100),
+        RestartStrategy(AllForOne, 3, 100, List(classOf[Exception])),
         Supervise(
           pingpong1,
           LifeCycle(Permanent))
@@ -530,7 +530,7 @@ class RemoteSupervisorTest extends JUnitSuite {
 
     val factory = SupervisorFactory(
       SupervisorConfig(
-        RestartStrategy(OneForOne, 3, 100),
+        RestartStrategy(OneForOne, 3, 100, List(classOf[Exception])),
         Supervise(
           pingpong1,
           LifeCycle(Permanent))
@@ -556,13 +556,13 @@ class RemoteSupervisorTest extends JUnitSuite {
 
     val factory = SupervisorFactory(
       SupervisorConfig(
-        RestartStrategy(AllForOne, 3, 100),
+        RestartStrategy(AllForOne, 3, 100, List(classOf[Exception])),
         Supervise(
           pingpong1,
           LifeCycle(Permanent))
             ::
             SupervisorConfig(
-              RestartStrategy(AllForOne, 3, 100),
+              RestartStrategy(AllForOne, 3, 100, List(classOf[Exception])),
               Supervise(
                 pingpong2,
                 LifeCycle(Permanent))
diff --git a/akka-actors/src/test/scala/SupervisorTest.scala b/akka-actors/src/test/scala/SupervisorTest.scala
index b143ef21e7..699b260301 100644
--- a/akka-actors/src/test/scala/SupervisorTest.scala
+++ b/akka-actors/src/test/scala/SupervisorTest.scala
@@ -457,7 +457,7 @@ class SupervisorTest extends JUnitSuite {
     
     val factory = SupervisorFactory(
         SupervisorConfig(
-          RestartStrategy(AllForOne, 3, 100),
+          RestartStrategy(AllForOne, 3, 100, List(classOf[Exception])),
           Supervise(
             pingpong1,
             LifeCycle(Permanent))
@@ -470,7 +470,7 @@ class SupervisorTest extends JUnitSuite {
 
     val factory = SupervisorFactory(
         SupervisorConfig(
-          RestartStrategy(OneForOne, 3, 100),
+          RestartStrategy(OneForOne, 3, 100, List(classOf[Exception])),
           Supervise(
             pingpong1,
             LifeCycle(Permanent))
@@ -485,7 +485,7 @@ class SupervisorTest extends JUnitSuite {
 
     val factory = SupervisorFactory(
         SupervisorConfig(
-          RestartStrategy(AllForOne, 3, 100),
+          RestartStrategy(AllForOne, 3, 100, List(classOf[Exception])),
           Supervise(
             pingpong1,
             LifeCycle(Permanent))
@@ -508,7 +508,7 @@ class SupervisorTest extends JUnitSuite {
 
     val factory = SupervisorFactory(
         SupervisorConfig(
-          RestartStrategy(OneForOne, 3, 100),
+          RestartStrategy(OneForOne, 3, 100, List(classOf[Exception])),
           Supervise(
             pingpong1,
             LifeCycle(Permanent))
@@ -531,13 +531,13 @@ class SupervisorTest extends JUnitSuite {
 
     val factory = SupervisorFactory(
         SupervisorConfig(
-          RestartStrategy(AllForOne, 3, 100),
+          RestartStrategy(AllForOne, 3, 100, List(classOf[Exception])),
           Supervise(
             pingpong1,
             LifeCycle(Permanent))
           ::
           SupervisorConfig(
-            RestartStrategy(AllForOne, 3, 100),
+            RestartStrategy(AllForOne, 3, 100, List(classOf[Exception])),
             Supervise(
               pingpong2,
               LifeCycle(Permanent))
diff --git a/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/ActiveObjectGuiceConfiguratorTest.java b/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/ActiveObjectGuiceConfiguratorTest.java
index 82347669c1..61ef403f7b 100644
--- a/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/ActiveObjectGuiceConfiguratorTest.java
+++ b/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/ActiveObjectGuiceConfiguratorTest.java
@@ -37,7 +37,8 @@ public class ActiveObjectGuiceConfiguratorTest extends TestCase {
         bind(Ext.class).to(ExtImpl.class).in(Scopes.SINGLETON);
       }
     }).configure(
-        new RestartStrategy(new AllForOne(), 3, 5000), new Component[]{
+        new RestartStrategy(new AllForOne(), 3, 5000, new Class[]{Exception.class}),
+        new Component[]{
              new Component(
                 Foo.class,
                 new LifeCycle(new Permanent()),
diff --git a/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/InMemNestedStateTest.java b/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/InMemNestedStateTest.java
index 26c6747eca..825d8f39fa 100644
--- a/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/InMemNestedStateTest.java
+++ b/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/InMemNestedStateTest.java
@@ -19,7 +19,7 @@ public class InMemNestedStateTest extends TestCase {
 
   public InMemNestedStateTest() {
     conf.configure(
-        new RestartStrategy(new AllForOne(), 3, 5000),
+        new RestartStrategy(new AllForOne(), 3, 5000, new Class[]{Exception.class}),
         new Component[]{
             // FIXME: remove string-name, add ctor to only accept target class
             new Component(InMemStateful.class, new LifeCycle(new Permanent()), 10000000),
diff --git a/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/InMemoryStateTest.java b/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/InMemoryStateTest.java
index e29e8ef81f..973ac14b6b 100644
--- a/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/InMemoryStateTest.java
+++ b/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/InMemoryStateTest.java
@@ -23,7 +23,7 @@ public class InMemoryStateTest extends TestCase {
   public InMemoryStateTest() {
     Config.config();
     conf.configure(
-        new RestartStrategy(new AllForOne(), 3, 5000),
+        new RestartStrategy(new AllForOne(), 3, 5000, new Class[] {Exception.class}),
         new Component[]{
             new Component(InMemStateful.class,
                 new LifeCycle(new Permanent()),
diff --git a/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/PersistentNestedStateTest.java b/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/PersistentNestedStateTest.java
index 0dcb4ec992..4c74a8b1a2 100644
--- a/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/PersistentNestedStateTest.java
+++ b/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/PersistentNestedStateTest.java
@@ -20,7 +20,7 @@ public class PersistentNestedStateTest extends TestCase {
   protected void setUp() {
       PersistenceManager.init();
     conf.configure(
-        new RestartStrategy(new AllForOne(), 3, 5000),
+        new RestartStrategy(new AllForOne(), 3, 5000, new Class[] {Exception.class}),
         new Component[]{
             // FIXME: remove string-name, add ctor to only accept target class
             new Component(PersistentStateful.class, new LifeCycle(new Permanent()), 10000000),
diff --git a/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/PersistentStateTest.java b/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/PersistentStateTest.java
index 23f8eb1070..b8f6d7eb3e 100644
--- a/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/PersistentStateTest.java
+++ b/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/PersistentStateTest.java
@@ -17,7 +17,7 @@ public class PersistentStateTest extends TestCase {
   protected void setUp() {
     PersistenceManager.init();
     conf.configure(
-        new RestartStrategy(new AllForOne(), 3, 5000),
+        new RestartStrategy(new AllForOne(), 3, 5000, new Class[] {Exception.class}),
         new Component[] {
           new Component(PersistentStateful.class, new LifeCycle(new Permanent()), 10000000),
           new Component(PersistentFailer.class, new LifeCycle(new Permanent()), 1000)
diff --git a/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/RemotePersistentStateTest.java b/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/RemotePersistentStateTest.java
index 9568d6a6f1..06573759f1 100644
--- a/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/RemotePersistentStateTest.java
+++ b/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/RemotePersistentStateTest.java
@@ -17,7 +17,7 @@ public class RemotePersistentStateTest extends TestCase {
   protected void setUp() {
     PersistenceManager.init();
     conf.configure(
-        new RestartStrategy(new AllForOne(), 3, 5000),
+        new RestartStrategy(new AllForOne(), 3, 5000, new Class[]{Exception.class}),
         new Component[] {
           new Component(PersistentStateful.class, new LifeCycle(new Permanent()), 1000000, new RemoteAddress("localhost", 9999)),
           new Component(PersistentFailer.class, new LifeCycle(new Permanent()), 1000000, new RemoteAddress("localhost", 9999))
diff --git a/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/RestTest.java b/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/RestTest.java
index b6d6ef06dc..4eb17ce7e6 100644
--- a/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/RestTest.java
+++ b/akka-fun-test-java/src/test/java/se/scalablesolutions/akka/api/RestTest.java
@@ -32,7 +32,7 @@ public class RestTest extends TestCase {
   @BeforeClass
   protected void setUp() {
     conf.configure(
-        new RestartStrategy(new AllForOne(), 3, 5000),
+        new RestartStrategy(new AllForOne(), 3, 5000, new Class[]{Exception.class}),
         new Component[] {
           new Component(
               JerseyFoo.class,
diff --git a/akka-samples-java/src/main/java/sample/java/Boot.java b/akka-samples-java/src/main/java/sample/java/Boot.java
index 55a3de1c1f..888344013d 100644
--- a/akka-samples-java/src/main/java/sample/java/Boot.java
+++ b/akka-samples-java/src/main/java/sample/java/Boot.java
@@ -8,7 +8,7 @@ public class Boot {
 
   public Boot() throws Exception  {
     manager.configure(
-      new RestartStrategy(new OneForOne(), 3, 5000),
+      new RestartStrategy(new OneForOne(), 3, 5000, new Class[]{Exception.class}),
         new Component[] {
           new Component(
             sample.java.SimpleService.class,
diff --git a/akka-samples-lift/src/main/scala/bootstrap/liftweb/Boot.scala b/akka-samples-lift/src/main/scala/bootstrap/liftweb/Boot.scala
index 553d90b277..b6098cfb3c 100644
--- a/akka-samples-lift/src/main/scala/bootstrap/liftweb/Boot.scala
+++ b/akka-samples-lift/src/main/scala/bootstrap/liftweb/Boot.scala
@@ -38,7 +38,7 @@ class Boot {
     
     val factory = SupervisorFactory(
       SupervisorConfig(
-        RestartStrategy(OneForOne, 3, 100),
+        RestartStrategy(OneForOne, 3, 100, List(classOf[Exception])),
         Supervise(
           new SimpleService,
           LifeCycle(Permanent)) ::
diff --git a/akka-samples-scala/src/main/scala/SimpleService.scala b/akka-samples-scala/src/main/scala/SimpleService.scala
index e5642171b7..a1f5e87575 100644
--- a/akka-samples-scala/src/main/scala/SimpleService.scala
+++ b/akka-samples-scala/src/main/scala/SimpleService.scala
@@ -20,7 +20,7 @@ import org.atmosphere.cpr.BroadcastFilter
 class Boot {
   val factory = SupervisorFactory(
     SupervisorConfig(
-      RestartStrategy(OneForOne, 3, 100),
+      RestartStrategy(OneForOne, 3, 100, List(classOf[Exception])),
       Supervise(
         new SimpleService,
         LifeCycle(Permanent)) ::
diff --git a/akka-samples-security/src/main/scala/SimpleService.scala b/akka-samples-security/src/main/scala/SimpleService.scala
index cca4246933..fc8b18367a 100644
--- a/akka-samples-security/src/main/scala/SimpleService.scala
+++ b/akka-samples-security/src/main/scala/SimpleService.scala
@@ -13,7 +13,7 @@ import se.scalablesolutions.akka.state.TransactionalState
 class Boot {
   val factory = SupervisorFactory(
     SupervisorConfig(
-      RestartStrategy(OneForOne, 3, 100),
+      RestartStrategy(OneForOne, 3, 100, List(classOf[Exception])),
       // Dummy implementations of all authentication actors
       // see akka.conf to enable one of these for the AkkaSecurityFilterFactory
       Supervise(

From c89d1ecad7f8314abaa497cbcbfa15787254cc1d Mon Sep 17 00:00:00 2001
From: jboner 
Date: Tue, 1 Dec 2009 10:09:29 +0100
Subject: [PATCH 6/8] added memory footprint test

---
 akka-actors/src/main/scala/actor/Actor.scala  | 34 +++++++++----------
 akka-actors/src/test/scala/MemoryTest.scala   | 32 +++++++++++++++++
 akka-amqp/src/main/scala/ExampleSession.scala | 20 ++++-------
 3 files changed, 56 insertions(+), 30 deletions(-)
 create mode 100644 akka-actors/src/test/scala/MemoryTest.scala

diff --git a/akka-actors/src/main/scala/actor/Actor.scala b/akka-actors/src/main/scala/actor/Actor.scala
index a63af38fc9..ed021c1e16 100644
--- a/akka-actors/src/main/scala/actor/Actor.scala
+++ b/akka-actors/src/main/scala/actor/Actor.scala
@@ -66,7 +66,7 @@ class ActorMessageInvoker(val actor: Actor) extends MessageInvoker {
 /**
  * @author Jonas Bonér
  */
-object Actor extends Logging {  
+object Actor extends Logging {
   val TIMEOUT = config.getInt("akka.actor.timeout", 5000)
   val SERIALIZE_MESSAGES = config.getBool("akka.actor.serialize-messages", false)
 
@@ -115,7 +115,7 @@ object Actor extends Logging {
    * 
* */ - def actor[A](body: => Unit) = { + def actor[A](body: => Unit) = { def handler[A](body: Unit) = new { def receive(handler: PartialFunction[Any, Unit]) = new Actor() { start @@ -129,7 +129,7 @@ object Actor extends Logging { /** * Use to create an anonymous event-driven actor with a body but no message loop block. *

- * This actor can not respond to any messages but can be used as a simple way to + * This actor can not respond to any messages but can be used as a simple way to * spawn a lightweight thread to process some task. *

* The actor is started when created. @@ -183,7 +183,7 @@ object Actor extends Logging { * } * */ - def actor[A](lifeCycleConfig: LifeCycle)(body: => Unit) = { + def actor[A](lifeCycleConfig: LifeCycle)(body: => Unit) = { def handler[A](body: Unit) = new { def receive(handler: PartialFunction[Any, Unit]) = new Actor() { lifeCycle = Some(lifeCycleConfig) @@ -213,11 +213,11 @@ trait Actor extends TransactionManagement { ActorRegistry.register(this) implicit protected val self: Actor = this - + // FIXME http://www.assembla.com/spaces/akka/tickets/56-Change-UUID-generation-for-the-TransactionManagement-trait private[akka] var _uuid = Uuid.newUuid.toString def uuid = _uuid - + // ==================================== // private fields // ==================================== @@ -226,7 +226,7 @@ trait Actor extends TransactionManagement { @volatile private var _isShutDown: Boolean = false private var _hotswap: Option[PartialFunction[Any, Unit]] = None private var _config: Option[AnyRef] = None - private val _remoteFlagLock = new ReadWriteLock + private val _remoteFlagLock = new ReadWriteLock private[akka] var _remoteAddress: Option[InetSocketAddress] = None private[akka] var _linkedActors: Option[HashSet[Actor]] = None private[akka] var _mailbox: MessageQueue = _ @@ -244,7 +244,7 @@ trait Actor extends TransactionManagement { *

* This sender reference can be used together with the '!' method for request/reply * message exchanges and which is in many ways better than using the '!!' method - * which will make the sender wait for a reply using a *blocking* future. + * which will make the sender wait for a reply using a *blocking* future. */ protected[this] var sender: Option[Actor] = None @@ -284,7 +284,7 @@ trait Actor extends TransactionManagement { *

* You can override it so it fits the specific use-case that the actor is used for. * See the se.scalablesolutions.akka.dispatch.Dispatchers class for the different - * dispatchers available. + * dispatchers available. *

* The default is also that all actors that are created and spawned from within this actor * is sharing the same dispatcher as its creator. @@ -301,7 +301,7 @@ trait Actor extends TransactionManagement { * Set trapExit to the list of exception classes that the actor should be able to trap * from the actor it is supervising. When the supervising actor throws these exceptions * then they will trigger a restart. - *

+ *

*

    * // trap all exceptions
    * trapExit = List(classOf[Throwable])
@@ -448,7 +448,7 @@ trait Actor extends TransactionManagement {
    *
    * If invoked from within an actor then the actor reference is implicitly passed on as the implicit 'sender' argument.
    * 

- * + * * This actor 'sender' reference is then available in the receiving actor in the 'sender' member variable. *

    *   actor ! message
@@ -514,7 +514,7 @@ trait Actor extends TransactionManagement {
     getResultOrThrowException(future)
   } else throw new IllegalStateException(
     "Actor has not been started, you need to invoke 'actor.start' before using it")
-  
+
   /**
    * Sends a message asynchronously and waits on a future for a reply message.
    * 

@@ -530,7 +530,7 @@ trait Actor extends TransactionManagement { def !![T](message: AnyRef): Option[T] = !![T](message, timeout) /** - * This method is evil and has been removed. Use '!!' with a timeout instead. + * This method is evil and has been removed. Use '!!' with a timeout instead. */ def !?[T](message: AnyRef): T = throw new UnsupportedOperationException( "'!?' is evil and has been removed. Use '!!' with a timeout instead") @@ -576,7 +576,7 @@ trait Actor extends TransactionManagement { } else throw new IllegalArgumentException( "Can not swap dispatcher for " + toString + " after it has been started") } - + /** * Invoking 'makeRemote' means that an actor will be moved to and invoked on a remote host. */ @@ -744,7 +744,7 @@ trait Actor extends TransactionManagement { private def postMessageToMailboxAndCreateFutureResultWithTimeout(message: AnyRef, timeout: Long): CompletableFutureResult = _remoteFlagLock.withReadLock { // the price you pay for being able to make an actor remote at runtime if (_remoteAddress.isDefined) { - val requestBuilder = RemoteRequest.newBuilder + val requestBuilder = RemoteRequest.newBuilder .setId(RemoteRequestIdFactory.nextId) .setTarget(this.getClass.getName) .setTimeout(timeout) @@ -804,7 +804,7 @@ trait Actor extends TransactionManagement { private def transactionalDispatch[T](messageHandle: MessageInvocation) = { setTransaction(messageHandle.tx) - + val message = messageHandle.message //serializeMessage(messageHandle.message) senderFuture = messageHandle.future sender = messageHandle.sender @@ -820,7 +820,7 @@ trait Actor extends TransactionManagement { decrementTransaction } } - + try { if (isTransactionRequiresNew && !isTransactionInScope) { if (senderFuture.isEmpty) throw new StmException( diff --git a/akka-actors/src/test/scala/MemoryTest.scala b/akka-actors/src/test/scala/MemoryTest.scala new file mode 100644 index 0000000000..083b964bc7 --- /dev/null +++ b/akka-actors/src/test/scala/MemoryTest.scala @@ -0,0 +1,32 @@ +package se.scalablesolutions.akka.actor + +import junit.framework.TestCase + +import org.scalatest.junit.JUnitSuite +import org.junit.Test +import scala.collection.mutable.HashSet + +class MemoryFootprintTest extends JUnitSuite { + class Mem extends Actor { + def receive = { + case _ => {} + } + } + + @Test + def shouldCreateManyActors = { + /* println("============== MEMORY TEST ==============") + val actors = new HashSet[Actor] + println("Total memory: " + Runtime.getRuntime.totalMemory) + (1 until 1000000).foreach {i => + val mem = new Mem + actors += mem + if ((i % 100000) == 0) { + println("Nr actors: " + i) + println("Total memory: " + (Runtime.getRuntime.totalMemory - Runtime.getRuntime.freeMemory)) + } + } + */ + assert(true) + } +} diff --git a/akka-amqp/src/main/scala/ExampleSession.scala b/akka-amqp/src/main/scala/ExampleSession.scala index 158dbe46d0..998c520620 100644 --- a/akka-amqp/src/main/scala/ExampleSession.scala +++ b/akka-amqp/src/main/scala/ExampleSession.scala @@ -4,7 +4,7 @@ package se.scalablesolutions.akka.amqp -import se.scalablesolutions.akka.actor.Actor +import se.scalablesolutions.akka.actor.Actor._ import se.scalablesolutions.akka.actor.Actor.Sender.Self import com.rabbitmq.client.ConnectionParameters @@ -30,10 +30,8 @@ object ExampleSession { def direct = { val consumer = AMQP.newConsumer(CONFIG, HOSTNAME, PORT, IM, ExchangeType.Direct, None, 100, false, false, Map[String, AnyRef]()) - consumer ! MessageConsumerListener("@george_bush", "direct", new Actor() { - def receive = { - case Message(payload, _, _, _, _) => log.info("@george_bush received message from: %s", new String(payload.asInstanceOf[Array[Byte]])) - } + consumer ! MessageConsumerListener("@george_bush", "direct", actor { + case Message(payload, _, _, _, _) => log.info("@george_bush received message from: %s", new String(payload.asInstanceOf[Array[Byte]])) }) val producer = AMQP.newProducer(CONFIG, HOSTNAME, PORT, IM, None, None, 100) producer ! Message("@jonas_boner: You sucked!!".getBytes, "direct") @@ -41,15 +39,11 @@ object ExampleSession { def fanout = { val consumer = AMQP.newConsumer(CONFIG, HOSTNAME, PORT, CHAT, ExchangeType.Fanout, None, 100, false, false, Map[String, AnyRef]()) - consumer ! MessageConsumerListener("@george_bush", "", new Actor() { - def receive = { - case Message(payload, _, _, _, _) => log.info("@george_bush received message from: %s", new String(payload.asInstanceOf[Array[Byte]])) - } + consumer ! MessageConsumerListener("@george_bush", "", actor { + case Message(payload, _, _, _, _) => log.info("@george_bush received message from: %s", new String(payload.asInstanceOf[Array[Byte]])) }) - consumer ! MessageConsumerListener("@barack_obama", "", new Actor() { - def receive = { - case Message(payload, _, _, _, _) => log.info("@barack_obama received message from: %s", new String(payload.asInstanceOf[Array[Byte]])) - } + consumer ! MessageConsumerListener("@barack_obama", "", actor { + case Message(payload, _, _, _, _) => log.info("@barack_obama received message from: %s", new String(payload.asInstanceOf[Array[Byte]])) }) val producer = AMQP.newProducer(CONFIG, HOSTNAME, PORT, CHAT, None, None, 100) producer ! Message("@jonas_boner: I'm going surfing".getBytes, "") From 5c33398d7994344e18d01f50fabf28493f612eff Mon Sep 17 00:00:00 2001 From: jboner Date: Wed, 2 Dec 2009 09:33:41 +0100 Subject: [PATCH 7/8] fixed type in rabbitmq pom file in embedded repo --- .../rabbitmq/rabbitmq-client/0.9.1/rabbitmq-client-0.9.1.pom | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embedded-repo/com/rabbitmq/rabbitmq-client/0.9.1/rabbitmq-client-0.9.1.pom b/embedded-repo/com/rabbitmq/rabbitmq-client/0.9.1/rabbitmq-client-0.9.1.pom index 905b5e83dc..c78d868476 100644 --- a/embedded-repo/com/rabbitmq/rabbitmq-client/0.9.1/rabbitmq-client-0.9.1.pom +++ b/embedded-repo/com/rabbitmq/rabbitmq-client/0.9.1/rabbitmq-client-0.9.1.pom @@ -1,8 +1,8 @@ 4.0.0 - com.rabbitmg - rabbitmg-client + com.rabbitmq + rabbitmq-client 0.9.1 jar \ No newline at end of file From 2bec67210e2aa379bb97c857a6bdcd4b0c462bf4 Mon Sep 17 00:00:00 2001 From: jboner Date: Wed, 2 Dec 2009 10:44:31 +0100 Subject: [PATCH 8/8] removed unused jars in embedded repo, added to changes.xml --- akka-kernel/src/main/scala/Kernel.scala | 144 +++--------------- changes.xml | 1 + .../com/facebook/fb303/1.0/fb303-1.0.jar | Bin 62870 -> 0 bytes .../com/facebook/fb303/1.0/fb303-1.0.pom | 8 - .../scala-stats/1.0/scala-stats-1.0.jar | Bin 48694 -> 0 bytes .../scala-stats/1.0/scala-stats-1.0.pom | 8 - 6 files changed, 24 insertions(+), 137 deletions(-) delete mode 100644 embedded-repo/com/facebook/fb303/1.0/fb303-1.0.jar delete mode 100644 embedded-repo/com/facebook/fb303/1.0/fb303-1.0.pom delete mode 100755 embedded-repo/com/twitter/scala-stats/1.0/scala-stats-1.0.jar delete mode 100755 embedded-repo/com/twitter/scala-stats/1.0/scala-stats-1.0.pom diff --git a/akka-kernel/src/main/scala/Kernel.scala b/akka-kernel/src/main/scala/Kernel.scala index 8514198bc1..aaf1246995 100644 --- a/akka-kernel/src/main/scala/Kernel.scala +++ b/akka-kernel/src/main/scala/Kernel.scala @@ -16,6 +16,8 @@ import se.scalablesolutions.akka.nio.RemoteNode import se.scalablesolutions.akka.util.Logging /** + * The Akka Kernel. + * * @author Jonas Bonér */ object Kernel extends Logging { @@ -36,9 +38,18 @@ object Kernel extends Logging { def main(args: Array[String]) = boot - def boot = synchronized { + /** + * Boots up the Kernel. + */ + def boot: Unit = boot(true) + + /** + * Boots up the Kernel. + * If you pass in false as parameter then the Akka banner is not printed out. + */ + def boot(withBanner: Boolean): Unit = synchronized { if (!hasBooted) { - printBanner + if (withBanner) printBanner log.info("Starting Akka...") runApplicationBootClasses @@ -50,7 +61,7 @@ object Kernel extends Logging { hasBooted = true } } - + def startRemoteService = { // FIXME manage remote serve thread for graceful shutdown val remoteServerThread = new Thread(new Runnable() { @@ -112,125 +123,16 @@ object Kernel extends Logging { private def printBanner = { log.info( -"""============================== - __ __ - _____ | | _| | _______ - \__ \ | |/ / |/ /\__ \ - / __ \| <| < / __ \_ - (____ /__|_ \__|_ \(____ / - \/ \/ \/ \/ +""" +============================== + __ __ + _____ | | _| | _______ + \__ \ | |/ / |/ /\__ \ + / __ \| <| < / __ \_ + (____ /__|_ \__|_ \(____ / + \/ \/ \/ \/ """) log.info(" Running version " + VERSION) log.info("==============================") } - - private def cassandraBenchmark = { - import se.scalablesolutions.akka.state.CassandraStorage - val NR_ENTRIES = 100000 - - println("=================================================") - var start = System.currentTimeMillis - for (i <- 1 to NR_ENTRIES) CassandraStorage.insertMapStorageEntryFor("test", i.toString, "data") - var end = System.currentTimeMillis - println("Writes per second: " + NR_ENTRIES / ((end - start).toDouble / 1000)) - - println("=================================================") - start = System.currentTimeMillis - val entries = new scala.collection.mutable.ArrayBuffer[Tuple2[String, String]] - for (i <- 1 to NR_ENTRIES) entries += (i.toString, "data") - CassandraStorage.insertMapStorageEntriesFor("test", entries.toList) - end = System.currentTimeMillis - println("Writes per second - batch: " + NR_ENTRIES / ((end - start).toDouble / 1000)) - - println("=================================================") - start = System.currentTimeMillis - for (i <- 1 to NR_ENTRIES) CassandraStorage.getMapStorageEntryFor("test", i.toString) - end = System.currentTimeMillis - println("Reads per second: " + NR_ENTRIES / ((end - start).toDouble / 1000)) - - System.exit(0) - } -} - - - - -/* -//import voldemort.client.{SocketStoreClientFactory, StoreClient, StoreClientFactory} -//import voldemort.server.{VoldemortConfig, VoldemortServer} -//import voldemort.versioning.Versioned - - private[this] var storageFactory: StoreClientFactory = _ - private[this] var storageServer: VoldemortServer = _ -*/ - -// private[akka] def startVoldemort = { -// val VOLDEMORT_SERVER_URL = "tcp://" + SERVER_URL -// val VOLDEMORT_SERVER_PORT = 6666 -// val VOLDEMORT_BOOTSTRAP_URL = VOLDEMORT_SERVER_URL + ":" + VOLDEMORT_SERVER_PORT -// // Start Voldemort server -// val config = VoldemortConfig.loadFromVoldemortHome(Boot.HOME) -// storageServer = new VoldemortServer(config) -// storageServer.start -// log.info("Replicated persistent storage server started at %s", VOLDEMORT_BOOTSTRAP_URL) -// -// // Create Voldemort client factory -// val numThreads = 10 -// val maxQueuedRequests = 10 -// val maxConnectionsPerNode = 10 -// val maxTotalConnections = 100 -// storageFactory = new SocketStoreClientFactory( -// numThreads, -// numThreads, -// maxQueuedRequests, -// maxConnectionsPerNode, -// maxTotalConnections, -// VOLDEMORT_BOOTSTRAP_URL) -// -// val name = this.getClass.getName -// val storage = getStorageFor("actors") -//// val value = storage.get(name) -// val value = new Versioned("state") -// //value.setObject("state") -// storage.put(name, value) -// } -// -// private[akka] def getStorageFor(storageName: String): StoreClient[String, String] = -// storageFactory.getStoreClient(storageName) - -// private[akka] def startZooKeeper = { -//import org.apache.zookeeper.jmx.ManagedUtil -//import org.apache.zookeeper.server.persistence.FileTxnSnapLog -//import org.apache.zookeeper.server.ServerConfig -//import org.apache.zookeeper.server.NIOServerCnxn -// val ZOO_KEEPER_SERVER_URL = SERVER_URL -// val ZOO_KEEPER_SERVER_PORT = 9898 -// try { -// ManagedUtil.registerLog4jMBeans -// ServerConfig.parse(args) -// } catch { -// case e: JMException => log.warning("Unable to register log4j JMX control: s%", e) -// case e => log.fatal("Error in ZooKeeper config: s%", e) -// } -// val factory = new ZooKeeperServer.Factory() { -// override def createConnectionFactory = new NIOServerCnxn.Factory(ServerConfig.getClientPort) -// override def createServer = { -// val server = new ZooKeeperServer -// val txLog = new FileTxnSnapLog( -// new File(ServerConfig.getDataLogDir), -// new File(ServerConfig.getDataDir)) -// server.setTxnLogFactory(txLog) -// server -// } -// } -// try { -// val zooKeeper = factory.createServer -// zooKeeper.startup -// log.info("ZooKeeper started") -// // TODO: handle clean shutdown as below in separate thread -// // val cnxnFactory = serverFactory.createConnectionFactory -// // cnxnFactory.setZooKeeperServer(zooKeeper) -// // cnxnFactory.join -// // if (zooKeeper.isRunning) zooKeeper.shutdown -// } catch { case e => log.fatal("Unexpected exception: s%",e) } -// } +} \ No newline at end of file diff --git a/changes.xml b/changes.xml index 658b8ab550..dd7514bbec 100644 --- a/changes.xml +++ b/changes.xml @@ -62,6 +62,7 @@ see http://maven.apache.org/plugins/maven-changes-plugin/usage.html for full gui New URL: http://akkasource.org Enhanced trapping of failures: 'trapExit = List(classOf[..], classOf[..])' Upgraded to Netty 3.2, Protobuf 2.2, ScalaTest 1.0, Jersey 1.1.3, Atmosphere 0.4.1, Cassandra 0.4.1, Configgy 1.4 + Lowered actor memory footprint; now an actor consumes ~625 bytes, which mean that you can create 6.5 million on 4 G RAM Concurrent mode is now per actor basis Remote actors are now defined by their UUID (not class name) Fixed dispatcher bug diff --git a/embedded-repo/com/facebook/fb303/1.0/fb303-1.0.jar b/embedded-repo/com/facebook/fb303/1.0/fb303-1.0.jar deleted file mode 100644 index 129328deff1eec85845c62c7dc44894f35d5d2ee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 62870 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

OKE&f#yL^fpM*H2+KWML~H zrbMj?5P%N;tDrVyy<_d7E+Yp2&tLeTI7c<+OVS7EaLb-r@M%&_%*>i=(ibdTv5HrA zw$(PtNzNaS9LSTr^s%|e%T#tZPo)2myT>Eg{>k$1?Kqh8dmqPaWjWWTgvF29l6Rkv zeaLd~!aM8UsKa@>3H~j?FS{=J_Z9DY==95IUy6n9|K$HK+7z$yykm7 z=h?XqtC?{IoUs=taf#F$%JTo1GCQI%Gl{oa?a~FwbJOaaR{Fk5X3L$Zdo;U$$NQVH z=?Zruj@vocX2umQTysVC-`-BEnad|G=7b(4W%Wd9<>{a^f~zjMG!?B2n%fu}H(`ZJ zx`*9)cHJ(?(lxaQF4(O+bzYM@Vrk5RQwR8bSIkdJ;Qk3dr0?Uu@?d911_pO(G+WbQ zmxY023sShw4TByfHDT}U95Y2v%`ICNP3doIF=^VWS& z4@*1kUzy}~^fu4JIWPT0Vo&Rxk?>o0WI?|O*D~V?=3c6k+fH$0PG6XHFeb61@0|2$ zH?4e;qLo`-N3_P6H(MDe=j!e_8 zr+1{dTF(#%-^8?lD$hOIabemFwA$OG(E{mi73|OWV_zdB#X3sk(UQcG>K6 zzM`_Xw{9-8Gc}FexXX1*!Y$KH+{tc%Y>IZOHO)6tF0j2%^NkGfbZry3U#K%(=x0nd zx018(nq2z_QMclXHa(l5`f61r%X7(x3l__IwsrrXEcS5TRYCWruB(RJ!N+Batnv$i)sOsE%DlTc=c|6?&&bOQdGB@`yGeV^y}I-crU^r{0{@Dvhoj>vPo;zu{w|9N>QS%2g)fQ**-UE&ND@i(uF8IT- z{uA?|Q~oB^)9%<@`dfV|?$S;d$x{}bcGv3UU#UM>y~AtTd+rnQ+k3Wsz0x82@WApF zy_1{kd87W=?YU>l5*9dHK!1PJzODn?JiD7#^V_M5?ot=*T(oP2j)uK+U|r*~KV2Q4 zq_d{nzqsyCBloHKJJ$SZO?;Z~qxD~5ZO$VxcB4DZmT|7}aRTAz)qpmW5Q{EL%% zO@%z)+kRa9K~>C%SBP!1aGO#d>$)jTR_k`z%(8Hv&aK~d zZ_dK&IVN+zF@1Bj`MPt%^vJxI)2!{kOs;Nw{mP3c-JfS?n27+-(RK1&?In*oe_Z^^ zbV}q`pj7e2Z=x%73g`CUU74N4yR4H}X4ZuT#&_0y;MnbKykO!J@q0mM{2sI^FMr<4 z>R%#bXcC@~b|P%*p~?TN3msRVxm;(Q;Kh{?=_QkzF@H(HWW=#FJZrvn`si9ae@l+b zn5erV`K?G>T5!m$;AtEE_W4X~tX&oG|JVUNFYsJV`ls0T3vEg(k&lT|f9Dnn-_}6Oj*LtQMC^_XL|NFxH z3;!oAOK)v-m~mi%-SogVeXWZGEuJ%F*jj2&afep;cY6kPNGhha zg7$PAnjWWfVn-LJzF2GAr$-Yn^sDN4|L8h6-)s)}9EQ}}C&Z2TnvG_imHHOocKUg* zjq_2BOe61~P3xp9H?cg*zO_v3Y{tzJlb1Kr%w!ioeVSTapRBVkTKZzBuX)h4t#Yxx zrRAmW?p~LdB<9cBb+O1Ow|jQ$qYrh)*;dRvPqU88G^d}4GL*=Aly=QS#4M=IcJWf9 zl#e&swjB}(>Q678ck9_I;j=fVCBF<)voem9I_k1z)sn?8Uq6mI$Lq9bmr2GEt!A4) zG3IwBeG&?4`8_k&YRZY%5x*5AUtQ_Dyx_Fw>V((FIy7IcvTocGY@xxSeCR@TVv-9( ztfPRUR`@|K9@fE2c@owrU(QtSmfNn%NfZkR>ZZ>&81Oy)Al{{HJXAi+;u5A za`ydw>m;d}qO5#eTxPDP(ks?IVEx3kPw?kH(MQ%3w>(sdZ)P>#oOFX{tNO%MM@m;7 z|0Pn>FE1g{`p((sP(ROIafSY0zcv25WSzZm@=Dphw!|G}w~oy`Y?k;UQ2)}aJoRfG z-|jB2x!^Hd#AoRzQdz=1i*Y1;7AMZI4IDM02o6+Qb^3#_5)4lrW zn?-aA$GrZ9k;hf0+59XuJ}zMQz1>3NgLb<>+vX6rtAeuc{!IGyu3hcUpLgz+J=^;> z3r)``&Y!$yn_`}@`KjA1tI}C-KKDQJL3YZ6OQEGAr*!xH%9vNO=1${7-He#iPk9VG z=Cpm34Srd@aB;TP?&}vk{!bA5^?6ET=k5l#t&c7#yjA3mbyBg;EW11Ra#n%3&W`p? ztWs0nANbtW!xK2^ss?+7wap&Rx^}Zs4l? z{(Zsx8Pd7`R|;GI*%u!uuhM=>_Qb*53LEPWxeM)7#QryIV!eNGf>~(p-k-f8U$sHU z(e$5U;$Ph4uJ~E+%BR;W9^d8o9KGXY{$sxP2bu4+d*16;kv|}`zgtB9kk)?p`eXt7 zOW7d~PT!@wo=hxoKIF@}{RD$a%tY0`+p3$YUc9w+`7`N;K*!|j6_Ff2$^)(UwI4X7 zXXnv!$n^@R&g~C>dklJ??7t|*8FS0A_Q?C&jUtL^dlz~L@+xkOI?~?qN*O%Bud?fR z%Ns_f8WG+>Mpld2E0C@Riep$FVWp?M(AUKEAA3X(GiU6&vbu`Sjtu73$Xxh_BqDs`OV- z@AL7HTf$ve-%qP&&t1Z7l66dY%c4uNTNi%=mum-R)j1ZjFfefA9mODii4CM&L*2yz zJ&z{mJaiC)OKHoN02WcvJ)#Gr8Mnr`_@3Ejd!=>L?wfiVo!4FdvfBM*ule9A%Eto6J6RLSxXfgL^$%lQ?Gnpbq!X+%*B2=bseJ*V57M7Azt@rS5`B_Q* zhdZ{Vr@wVd`csv8Rey8nGFxS9^CXKpA+2lfvWtQww=8Urd|0t8S2UEzm_=^KGIs~Z z^M2LqGM`FjDPO#@W@Cm5SKCzoHIctHjdJyOL>lIt+LhJry>v}B&MRwvafNcPTidn&-(5~{NA^dY%)Q{lE;H$%UGCBw-*S^{^SMIzsJ1U_Qk6XAGb?;r+KU^J;llGg=V~6c zyqwtazT({Eq6=TYcD3s`t-bT&-u>&Y|K=r2hP^%iM{U-k+u*~n747e|`&MuJeES2t zfw_$P3D@WQwSJrqndSIsW9n~4XJe@svnKU3sr|Q@^gH9a&#Z}jC2JaL7qA|#n6~HO*}Oa`J}JDL2n4{YUJbDw+R@>2BfL^V#r4-ePq%`&uS-^RI8u z=PzjzT6o4iV{x^>9hV021s^M~6mW07!c5^T;?8fKDp(mu*rwzH;&JLs8GL;v-#f}p;~p0<{3_ZwX&8Sekl6J@93eer&r8g zbmr^(>&ERT`2Vn`)_Km|w`j(S^DgXcwV<;MSx<$1q5n|3}HF72+L{M zkf}I$oAF`8gb0!3NA7zjOqd{GnP5|4m>XHJam%vXpUl6kuTX%VMWgd@3A?bK@#nPk zd+%o7T>rk`pF#bG`GkW}e34T^wyaBbJ}%a*Cw%^KkkN)}Hr+arO)=Lu9uAQBwBxr- zx4{H{!Rejy#xve3JP5p8zU0Z3qH7-yZL}@0dDr%EvTcF%*S5Q}4$Jkc9eVuK-eh{o z`KcT(HD?RrB6}Wv=u^DR^LviseL=?kp2zh1^JK3t_gN>dHt~40Q{yH5O^YWQ7y9TN zG}+h`D=byg*6kV>n0HwsL+j?w?IK&>S|7adZkO`AqgLM}{KOZgd4x|n*8G2Vq0jF# zmnH=#c=04edclq}oEOlm74+ou)mtKKe)WZz+PePA4a=B#c4hKg*0yh6fr)OBM~r?d zxw36r=~OGnJX_-r11Q=|v(9YtWTf7ChN#g7Z8?T@76+#a{NHQ#Gj7(tFCDgP*rN_k zGSdxom?9R?71EXK7<}MSVEpCl-!4u#@}%{)bUv#~;Laxk8cbRlvx8poE_!TgwfJ1c zU*$6l@9I3Gt9epA)PC=~`{v#D-?#6+uf88|@zt_n<&SHfk{KZzk93;ooIQ{m@$3k5 zM$#r5=J3akYW#-3H*~oh88Dvpv-qg7`jt*zp;ALwoTTKF#b-OqN({1%A{Q>Y+<1HL z3HN}bUh0weT zD(o{a<&((d<)Jo@4{Y`eQFw8{tig&x*d096fzcy>C2>aK7-RJXN&jwUq%{VFZX{nj{?2~iTud*J}uFb7Fkipq* zU7M?WIdA5()t(#cly{xtk(lhJYUFv$x9^CKaY|IN$dYQW=~^4ka&Hf+xLKNZBBNt{ zj^U!-D(?v@+g2>xuJxg+EkC`~<*eCh@y@oj1qw1>O!fTMuDUV%bpFdmzf;~;3x&K> z;+HZ7tBP7YU(YFVazn@-w}f?lv&2^B20hqt=wy!QlS(i5WQSw_3T&hdvV8jV@?8!E z-*7k_J7e{NPp3X6^3OIsb8xQ6);8UW*u!Ca7C!XNx%@%w-n9>W+kzMKh!!`>y`8EGS3jP3ozX6|z~n%B!Liz4Dhm z?_vu*7ih*GzvwFTKU3#dU7a)2tYgQWtEM5gC!bfl%}>vn zrrf_jF;!1C|8dCFrx#@}g$o^ew~_C3&dXo_eIH1kFW$s{!|*Ooi0Q+X>!y_!d&WD< z1{lp#&totXnR_hCK0b0Mv-++z+vD#!uS;Z-swplg;%ZyT?;{f5BwMxSU_|msf$7Ff zlO*dBdCHugG3?p&@Y3zd>5~klUJD&#u6-ia6#OaDdCz?=cQ%&)t9M>d7Hk$5O%|=6 zqEV_5)_Xx-`Ow5)=DqbN7R-UDd4lll3Cj0WUf!MIuXi$LCbzZBlHwDy8}>GK ztk8eowu^ZYcXY;63$CA$>U&k~E7weXe5+e^$^5{~#j$gJzbQqV8(CK^{CZ%j-Qjuj zMc%j@YNm#Ad0yR=x1-Bt;w*=6n|jNZzJ7FH<-Fp`v)7vM=!sO^{O-A9_XNugD!r?B z>215L{Jy27sW{3@f3d*(1A1kLG|Lpj-?+`Y(Ok4qetReL3L*ADeZIt<7ESI)1GjW0 zcL?owtLflsb#AcIP2&6EU-9v z=Sq9$6_ssD(ei4VH~Na=?ykA8H7+RgyVyX`Tt4OO^h{Xe?XDl(wx?b^UmE{Y zUwSfH!4*Of8Yg(NOrH(%0v3VrzBbaU&Thl%Bk@XqD`-=nrI3)b*P(R{-L#6JR z*+=bd-S;;{|M5%sr`TAc{Ff<;!;JIZqT(5|?09sm{5?twnYU(0*?Rv9y!d3^CGPmS z*K56*w(EUXE1tXS%SI+$}k|j{s*xKaArgJ%I>{s4DoE(3EJ>JAHq3?;^fxY+D zFR)ME-QC%F(WP~@T)2SAA(h~(vB9DHSH)ld5`Vh>59b2*>%MOsPPs_kjgnc_*xDo3 z?knTizwK+*$HfOOYV^%q;W+<5;bfabD}qQYFiC2|N|SlNRbNkFm5W->vZ1aCd-8_e1aMF2$)QEbqNNv*qoHrsrqV znr82t#b=~?pWEiRcG@w$kg&g2(YbaT=H3+CEuywC$@z+-*3^SCdtRRiT41wX$KZ&- z&c~}88WuH9=dXEs&cH-%($45_d**81dgt?O^49rEpYP3ie?oET>nxd7QzlLSx2Ncd zqHIE`|LeX?m~>Q=d%9s>qLXvn#R+GnrB9z*`Dn@)$yeqJR3suU9a32r zWzo@cz_e{%>4eLz_YUu!$?H;*<8e5FclWw4>|JF$buy#(haLQRNOz_5n>)8|8f~dN zU6}LLrBlmRZ+^w;Q!> zg{@oH>9KcN8K2s`>d1t9pXQ{0T@bxmlz&%C)b4AwJMz71Y>!*5v77U=)I`;sdEJI3 zhm#X4IA-(jxs-lb{JQ^_d_n9iGB6r(d-eAkZnd>zFN+kU1SKirOmb*mq zrN?!p8^TcrZ`3juaXmPn_(447W^>rB?C-yq@LoC|%)LTNHPCia9oJ*VAI@7YYkkr< zvS4@byea>_@XWb$x|EVo#0v3{G(xT1UE;!D>UtE|Jb&n~oDQ+i)0OYQM9r8-_YK`*Zl7dSM70*<{5{+ zshap4d)$3vn)gv@@e3x7Gq>Bvot06x@5q{Q$f3C-z{e$x%lyR|jEl&C|ISSOCy~fvfreO#8kV_en0#Pb=2dB z|Ib=1tbLYwQqn+|Z9}eZztNVEOA$)hf>}YXZF{bQPPu%4!eoyx{%+?_b?fV;br__VH6`E@bv#GWa9V5zM-HK?)0YeE5N^^%?VjUHWukdK#P0@-tu9AqNcIJlZHA zk?^7C+&jzN&p*{#?fwK=iSGAj#UfT`nd_lHKExT$GF+3yV%{R5+tz2Oc&xQ5c#WUP z<$a!_+YMB6E<2qmxbtmssH8{|1BtVuW;cR&cg7HYNs>Y9~qA~$$t;M zl6bA3J?T$CNB^H65k1{9Z0=194|&{@4!h$w^V*{9)J>lKjXfTwrWl2_Ei7nq zGy3dv&15Z4U}uDfl{i(OYlrBAOeJbibA@9Li(v(hBD z&R>{u!0+Zg1!qTtl72_Y!f85fpERvg&!$`#o@Sk{GASi6=5$0-2Mho5&vLuIZ4&q1 z-S>QkpOKmQ?D=22GnN*fH@Lp6cMEtWx?17M1$}mAYqz9ZujFBO)vI}OOHTDuwcnlM zw^z8FQw>bEX5~n1Trx4L^KInH6w`Mpv6rPbyT(pk@Ay`LPioPNgcsKK#!5{~6`RUn zE78}2R-#XexIUq2v0}>xfy_RC(;X)=K3rI+sC~(N{uz;nCubR5WOKfJvif+A_Rb{_ z1?93Un$DZl^y!<_bgnnC5&gMO?2+`uEx$?+wQVjdI$0$7MLD4PNZG#Czf5Yn-?#jj zC#ADwp**vUy+O(RcIUPOj*{DjS5Na?c5SmMpYz{B>F3{Ww=OiVST}FFZlvC?ivC}T z*+-XUIKJAnd5`9+Jw^|8?z`UG{x&3j=j<5K_nxzEP31NIk&{&}w%l3gknfk0(}&&L zXWdQbnBTi}_dH)8&6%dwXD`$}bGFpcxbQ8oXW5ELmzdp_)EQQMxxl%-!Dd1G3huen zEY8o_6B%^ON^pUE`J&UQFTy){=ZRJJhYQ}&pR3yIRS*P^&fW;{@;u}6flu5r!um%%S4zx#h_meXS|mG(oDLavwJ zMnAA$oFQDE@$A3sr|bHQ-~QD)+Sl-ld)1*Q0eg5&_prL&bUUfGN-621f5vQ$O3S6b zOK0oXEnfI$ri)6~tHqlRtPVVpz2H++$Oo&CPgT1jr9bH9A2GexGJ8*}-NxLG&jNBE z%2X=Yr&aRAKDp2EPp0+3i#o@NB7S}^9`0~rTd*tasq2ne>Z_;E+gE#J|1&}Vw~J~V z`QI!^suKToh)?f~%dO%SA`#mHJ_$!H`gJrn#FhD#S;Z8MukMR1L) z8FPASiBD#3W=U#FP-3S5z`q2T^BD>NOEFw{J?jw>49#i z*A9uLr*7q_B`UmGX4XCZKiaWF$Gy)>Iqq>>wXJ&D<-5;I{Lk0?`t?w`K~U#~MMF!U z3fokPtj5MELWiyV5?yY(O|>{%sMfOCDypFG@g6_9x+|=zdRm6Z4CM}~%F0@ZA4*-i zUZZfT^4Y?XkElk7fC!W}mHIwsnqacAb#Y>&1RTp=`CEW~ye* zD|useT*UdoN^M&vu1ddq#Ys5PckJ9IJtFk*aS5}nznXY)! z`r9Qc$%9qGqCRFw9dm=;6^%BFcxwNz@0<{>+y5}Z zwL)^IlZp4`MKPk&lK$T)(Jp1RI9%}Of90|zE2iD#!^yfy3I zXQ{J1-o_@Lv(l!eOWcSJ-8^r}sV%=Ytua(7ujRhWk-g-+`n3yFlrPTl z-Pin0=wSGZrJ)bD_B-m!{}p<*{yWDc>H4p4jaN=^%J?Ms>*Z9I`ECv8ot_uJc<}kf z6V@*uSyg@}_Y_TzyQtJRDc^jHK1ajj8|E#Y!c`VkmVJ{MGq@M854^_t>zDb?vK{a>W($1IzDji`k};E*txhSQ=0AW zN4MYSgxE^Cew$wi>~OiZ(R^}8$-2b*HmUdirx_Q|_;Vm!W3%s6D-q%E)`kt7`)_}F z_dqH&`zIeL(>~v!XyD4sz);GDZ^OM81(_DJiMcdrw;z+Ei0$FSg@sdDKX#h6F)0=X zdhr?_oG?Ma_ejKz8Fv#8985L8$$s(tCIvOIx(4~wJAlg7)O?&R6Y(;MA81&q2RZZIGA`m-*53dy3^ojkU<=K4! z`?{ie-oDzDa{N2b%rb)sJU{1sdRl5!m|F3Chg@mVUj@$AHyW{1>MqXfnY%JMNpx9f z=@j2J4aPCL-{*TxpXOqHT5r+P_8apa_rH-Y_X+4@Zo5|GEO9Ax?e7=$QgbFTZ%XMF znIXmzF>RWU>?X#S_ZArYht3ty?D`p1%NADczG~V$#lL3kQ69hmbbs+R)#@(xD>%^jPvX=?Elo zWyyPaD=Km>ycEWIgh_Rp)C=V;Q=`1iPq*o*+$`DL7#6*C-!Vz~#}?--u73P`VCE|x z4HoybKNscy`2SJPvMt~2lqq>&rFHRp+wX5IpVvL#{rukV=lA#j<$GYbM{gnPUYS~< zQy1Pl8uNKeIQW#DuXu1=@FH)K%+v>t>kTTxJPP@5@_R}gGfb?CDN(oZ+a)+5pq=G- zhfCjHr}|U96FQ2be9m#af8JuEwQKXD>UodnNb7stXl;>xe$+zkjNXog9Vc1&rY6rx z{N0jv^lMLE=417(AyL7)cTe=qjM_J0o5YiYIbp`XFMHXoe=4cPmZ@TTUOXi9^yFo> z>!fC8cm-}s=Vm<4^natR$yG~T*_~^HGt}XRbwZ3J&$T0nt zg-LG1`jc(WirTxsuF3mqFonHoxn#`WV>^xoNMGN4t3Yw`l{12>Gu3)eUlBQFDH0)G zdd@`0+4R!IiI4lPs4fas*KwUI6;xCva7$pem5`gnlE%}krU_5@B%`U6aZF_iPu^*d zh-LHUCVXIT`skS&)wyiy8<#ChR8IsQ(wMPI>@us~|5(rMoa~Z;Ta0D?*;@#0R7-KW z;C3Q4rbRDVDA?%Ii4!LdC1m{0m)2Bn+0euHMm(tR@gyGMN=dO>sUj?&mi2n7X>qOU z&6$;W{@6CdSnvMRGY+OohJRSpGrb_xZF|I@SrPA3FYZ+m%iS^i^}eQga@T#@WTiKV zEYK~^+7*0k^$xwqngO;O6^>`~*nZ#6&T}s`u$$&%qzUH+?S$~=9!e-VT^XTHf6=8F8|Cp}++>-j_U+A5QiAyJ)&UETn zGyRpV)^iQPb9ZNp%SgRU%w8zIk;mtbsLIt&?hZHc%oll!>*UXVyIK6}_AZudyLvVS z3Y`*vI7?l1F}vsrN6Q224;@W^@btQe_jf*4v3K&?pw(79`g6Th< z=RB8JJZkUOcK?8CQ&mHfNz;8NRtvs+%W7g}`ipH2epJzHXiMu1Uv&B5y6&j&T#Uth zjGd`hdVke;S0rRe)_G;!F3^Z^*?S_L@v6CinB>34y@K(FmE?LVp1OYE5PZw$+EsDF z^M7L2?UipAY%4ZB?01OepJeKH%bGvjCLh*cII-WYq24+F)b<D2D@0t5Y+~gxG*Y_=R4=S=`ewlcsM}_IbjUeq; z{}@5_+$|k{o=q$a3|sN8q9F3pvZBKRlF&K(bf0NHkl6|Z_REWz5V{fNzi?evm^{AWGp)7l5FyE){6S0r{^qfY7jKL zIkPw|{n_udb8jmD7Qf?c;ETDokuy$}3`LIVE?mdqsnzu)%Eh+9;Xdoe#c%f>I;lTi* z>5_&9rM8-H6pd%9b*FI`_bAHrEMN2bVxh6>q-my-rR#1L-RVrrJ-sm~%*x7SMtteY zoTHq_eSE*ojx^_-SQ=Q}snvY1T3dBf-xedwK0CJazR^}JPm0&HB%eOR;#_GUvOn#f z!QxC~W5L)BWq~P&W^D>y88T{x@Q+I#cCBp%jD%ciMHL|qHNxMsW}b$-Z7U2DJt zC6kM}9REb*{_$AV_Zj_TdiqCI>Zi8L59yLm+e@PNIqUws=J1=5-{Mu>LH{`c=Pw@E zIG4wvQ@;1-rm_pSx12ETbDExg*QU#j`InB_m-B}u=DL1#urOk_|ERfed&$aISrwg^ zs~>%4Wc()>`bT)%hx03*#!pMUuzzm;eYrym{1z6;r7mtfpksFIaN{S*kU7iGOyw6d z{(X}Fk9O)mx2bi@XH2-=DfVT@-DTBm?wZjT!TSq#&Fbd|-Rl#Jw`podT(hP)qqHO? zzZ|s>3CXU0yWeWQ4q8wY7&4{%!X+ocJu{K@5@{_ez$<_$d@w^}mv8=F=L z$Qt!62)?na#o|=qnfAvKiTrOwjl&a0Yc`}n4vP>P&2D~*Hwv1YNJ)yidCmSmoD zdzrXW@O>IfLdpS62 zH%Gt*@vSUN9w_N)N*qaL4HpPEXi4l7WL>;t)dQ(4QI&wx7q*o8w#@Or8RC~`mB0M# z?_;r7XPx4lVAytSZ8Cd_?&PonS#yyd?gO)#Hl!6tZrn4^Gh3{AKZo*(15R9O1>TO_ zO)}dht-2W0C&$XhUi9_N(DFL8fJdq=?Q80l7{A52KiPhH6uAj6HGTgkMDo?Y=N8-Q zrkPkJ1zfWdyS%Jq6U$49@=FO;QTsW{qQW|IZ<<~ExGdmg-HfG`35IOb{U)Ch;#q6G z`qi$r!Kp!cVdsrp%4{AQ8a_H@^|-D%z}tLP`M1!6_39BVQ>`z@U0HUa>_DqtXTg5q zcL&sRjDH{hAig2|Y?|rDjNkIj^**gX7u%WT*vGAK=Zy_`H1WWZ{cc6_Z(n&DUz&H# zbwm1=gd6@rZQKv?6+f1zST#TVeSIn$p!qb^PH=A-rGoJJgt0`aAB>R ze?(0cqyEm1Kd+iEsbM`I!*9X2_7Eh)Ui4sFaHfBmQ)K(g+_>jb?YAFRWpJtrGgb=jZkx8iM`uxqg-m3_ z{2x;;M(+zO)!lRCCHu#poeck5rS|pI*08ew%o1e#d%g9WtUAvtkyXU}5wMbo8w`<-_|GE!56@K4Y@xfC>xX9{am)-K)CHo)Pq-y`<1=X<&c83-EGBYp) zvf=AXY7v)V4I#aa)*f%JLkQs!>r>#;JL2kRAZcxAc+SDC*g{_M_a$5hMiH?zefcg@i~>Tf$w*nwkvRPo+bOSa~4UX<3-T3Ni&-#bkF z&=Y%YDeEBa`I*)SE%{}?+m_sYyPG$r?VjGNz2Fi5?!Y%+RxmIyykfxTe+{Di5Aprn zX}^OmJBS=R|4^*!4y)in?hdXF77Y!hrYM&{mL(nKhP=@{%Q`17v3MN)bGq@rhs;03 zekt_DM|fPGc2W1NPuAoIG4`hZTmW!KL`b%@8g)Zc8+Mr+tP_! zTO}jbZGOsWpU*C3oAk;qNa1h)McrSwg)>hZx;}|Y%j#@h`i*nTi>$A~FTN|k<=V1w z!^gQOro-!Lu*P4br&d$yI*oKcFTb-#m_vV3-ibf$i7RW5U5VomW81BH zT=eMDUzWk*i(Ve!`1G%dgXgqfM4UnCG*hqp-Zy9Gbn&cz5-jJk^wUy6^SBYofN#3F|cz56=k6HB`N3b6sTL`zoou>8reNPAgC_n~^nrQ=6v1Y~JZ- zWP-mw5SX`D?P;F!txY+WNviWtbL1aBaihaz$=yBaU9Q@DUPiQ-Ki(yO`OxjnK8Cxp z-$?eB%)a2i|K+nUZya~eJF9YhQdOsnzN*QKZ4ckPSUodV$6{II|KDuKW*!qsakXyF z3_2LJt$4;Wk(~cGB7HU=f9p_tBh`9x<|3onRqHm*T{~@c%5!5?Z9~_U$Fz%9rfaR$ z$(s3Rl26zB^*f9-_wTQGnlx+GiI5pON598~{G5??CB{9}ZQ0AmGqj^rU8jatPCcTv z{?i@N@U*8pyTkLIemtsWJvpw?JxwyOz$Kn-nIh}XKSc(-S{dK>>s)aU{UI&^`aw?YBYjYzk(u-H z%Y7yWhTnJ_=1SNzOQRZ z&LEB4OmEv$YI!QAz6*T+#LZ*juVb*EVjsv zICnk1#na^{Ol~k;|VXwQ$bu zQjyYUlWisQHnAPt!~NJ`uX={~^x}Uzr|R=PXYBM;^JeQncgkTDZ<0 zsD8HWQcmq&f%l90WZww+{Y}YaJv2RT(w@l1>w8~D{cmmArnOZ`aDS9?zT#hz=NgV% z6BjYdvhk;_5<@+z{ z?zM4+{j@nTUl!5{`toK;y$mA*!#qY%0maB9!T>q2dQFrPXcs&K69WWrGO$1xaMIT` z#8KDN&rSc|DNL;|^*4X$W?*1g!oa{F0@ng!fVS$wwfZ{xdAhj25%rr2)o*l1|!Kp=M znaQato**l+o1K1W-y2DO1_mKL1_phwnK0rmCsAfQ=VYelm0&k~hlRki9}El(_Zb-& zKvP99qZt^2C5bXTpeR2%wYWIHNCnDrE6oGX9$~j{Q$fP{3Cs)(GdLI+tPqwlFfi%b4w+eE*5q6ta%}#EZ%*?>>fP;a-8O5eKYUJ7ky#))qg&{HTH_c{dU^v9V zzyLY~7-8oEEz&K79_@!CSL)>!s?B3&U^s;lW6Sl(whOzrF7upU8o|uKAcPrXMkHEQ z4BJPK-KPB&cNAtaGccUTu&Kz5M4R9{_OaWvbd$*0smu%vyD);U)QVi2aKx16_r}+t zJluzAl^uyzA=cSo_my0%2HR3*1_m2W1_pOT>SJJFC~zXtDr_^{*e%_X7PvZziGkr1 zD+2>)!!g3%E;kY_MIO1tZrR7xD`P>|S?pqEU;tfQfv_ynlSIp4V=mY&QV=$Y2CYS% zF2KNGgs_EyfkDxSG>fpCU-#%=qz5wtgC83MgDHynEWt#X4=vA;26)kH*%Ed=dlyCq z25%d|e+~u)&`EFz55+~0VHNfui)o+e?f_k72wDV; zu*4&lSWBQ)6P{3e*57#)wlEHKbS}b{cL}80LO9@FX7!|0urM$Pa-vu83zNvR4SU!j z-$ITWL5=Ce+5@R;@dO?6&Dp3Wfnhd@mJkj(R{o&L6v zG;5$u2Rz|thjjI$8{9h}#^O@)>>?bD$k(u;Cild0O6U+YP>hHw}nUkia+DXnQF(>m=_p#%?v(vR@@&KIE94_nQM*${(}=PM z-cBYMO`1rj2%;A3pQe*x6?Xq1pL~XzZN27_XbB{euv>$CWEX0%{a!$nHSk71!C?E3 zbbbzMu&rD~hE>@8gM8)-YJJ$goJ30?!GqxT( z`HTnj!UuWNGitH0Ya^+)5Dq%zeP^h}Lg8leY{MRQ$lGL4!!BkQQT8DEf8Yd;-4^7X z9jIX^x{p*_2!|c=vTD?@JF%ZU+pzlzc_k?7$lJ~%MA?I_LyIRAkykB()|Wz>4)Vh`C}NDCQIV=(MIQ8ps?+VO-a^871kSp>vaAd>Sk zQTD((?0D=zp5p|~ - - 4.0.0 - com.facebook - fb303 - 1.0 - jar - \ No newline at end of file diff --git a/embedded-repo/com/twitter/scala-stats/1.0/scala-stats-1.0.jar b/embedded-repo/com/twitter/scala-stats/1.0/scala-stats-1.0.jar deleted file mode 100755 index 6b1b43bf7b9db2c3329cfbd34737395efc3a3a4b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 48694 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 diff --git a/embedded-repo/com/twitter/scala-stats/1.0/scala-stats-1.0.pom b/embedded-repo/com/twitter/scala-stats/1.0/scala-stats-1.0.pom deleted file mode 100755 index d35560379a..0000000000 --- a/embedded-repo/com/twitter/scala-stats/1.0/scala-stats-1.0.pom +++ /dev/null @@ -1,8 +0,0 @@ - - - 4.0.0 - com.twitter - scala-stats - 1.0 - jar - \ No newline at end of file