From 5aa8c58f2ba18b21b7e2593b26aae5908607a1e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Bon=C3=A9r?= Date: Sun, 4 Apr 2010 18:55:40 +0200 Subject: [PATCH 1/4] fixed broken "sbt dist" --- project/build/AkkaProject.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build/AkkaProject.scala b/project/build/AkkaProject.scala index 7a8b1037ba..e3a43ad75d 100644 --- a/project/build/AkkaProject.scala +++ b/project/build/AkkaProject.scala @@ -449,7 +449,7 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { // docs if (genDocs) { - val DOC_FILE_NAME = moduleName + "_%s-%s-%s.jar".format(buildScalaVersion, version, "doc") + val DOC_FILE_NAME = moduleName + "_%s-%s-%s.jar".format(buildScalaVersion, version, "docs") val DOC_FILE_PATH = projectPath + "/target/scala_%s/".format(buildScalaVersion) + DOC_FILE_NAME val fromDoc = Path.fromFile(new java.io.File(DOC_FILE_PATH)) val toDoc = Path.fromFile(new java.io.File(toDir + "/" + DOC_FILE_NAME)) From 0d95b097637cc60cd13281ec10a46e79a8dd2a45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Bon=C3=A9r?= Date: Mon, 5 Apr 2010 11:53:43 +0200 Subject: [PATCH 2/4] Refactored STM API into Transaction.Global and Transaction.Local, fixes issues with "atomic" outside actors --- akka-core/src/main/scala/actor/Actor.scala | 2 +- .../src/main/scala/stm/Transaction.scala | 116 ++++++++++++------ .../scala/stm/TransactionManagement.scala | 11 +- .../main/scala/stm/TransactionalState.scala | 1 - akka-core/src/test/scala/AgentTest.scala | 2 +- akka-core/src/test/scala/StmSpec.scala | 81 ++++++++++++ .../src/main/scala/ChatServer.scala | 2 +- 7 files changed, 171 insertions(+), 44 deletions(-) create mode 100644 akka-core/src/test/scala/StmSpec.scala diff --git a/akka-core/src/main/scala/actor/Actor.scala b/akka-core/src/main/scala/actor/Actor.scala index efd635c21a..f466333388 100644 --- a/akka-core/src/main/scala/actor/Actor.scala +++ b/akka-core/src/main/scala/actor/Actor.scala @@ -8,7 +8,7 @@ import se.scalablesolutions.akka.dispatch._ import se.scalablesolutions.akka.config.Config._ import se.scalablesolutions.akka.config.{AllForOneStrategy, OneForOneStrategy, FaultHandlingStrategy} import se.scalablesolutions.akka.config.ScalaConfig._ -import se.scalablesolutions.akka.stm.Transaction._ +import se.scalablesolutions.akka.stm.Transaction.Global._ import se.scalablesolutions.akka.stm.TransactionManagement._ import se.scalablesolutions.akka.stm.TransactionManagement import se.scalablesolutions.akka.remote.protobuf.RemoteProtocol.RemoteRequest diff --git a/akka-core/src/main/scala/stm/Transaction.scala b/akka-core/src/main/scala/stm/Transaction.scala index 29d4c586e9..221ab86bd6 100644 --- a/akka-core/src/main/scala/stm/Transaction.scala +++ b/akka-core/src/main/scala/stm/Transaction.scala @@ -12,7 +12,7 @@ import scala.collection.mutable.HashMap import se.scalablesolutions.akka.util.Logging -import org.multiverse.api.{Transaction => MultiverseTransaction} +import org.multiverse.api.{Transaction => MultiverseTransaction, TransactionLifecycleListener, TransactionLifecycleEvent} import org.multiverse.api.GlobalStmInstance.getGlobalStmInstance import org.multiverse.api.ThreadLocalTransaction._ import org.multiverse.templates.{TransactionTemplate, OrElseTemplate} @@ -97,9 +97,21 @@ class TransactionRetryException(message: String) extends RuntimeException(messag * * @author Jonas Bonér */ -object Transaction extends TransactionManagement with Logging { +object Transaction { val idFactory = new AtomicLong(-1L) + /** + * Creates a STM atomic transaction and by-passes all transactions hooks + * such as persistence etc. + * + * Only for internal usage. + */ + private[akka] def atomic0[T](body: => T): T = new TransactionTemplate[T]() { + def execute(mtx: MultiverseTransaction): T = body + }.execute() + + object Local extends TransactionManagement with Logging { + /** * See ScalaDoc on Transaction class. */ @@ -116,40 +128,22 @@ object Transaction extends TransactionManagement with Logging { def foreach(f: => Unit): Unit = atomic {f} /** - * See ScalaDoc on Transaction class. + * See ScalaDoc on class. */ def atomic[T](body: => T): T = { - var isTopLevelTransaction = true new TransactionTemplate[T]() { - def execute(mtx: MultiverseTransaction): T = { - val result = body - - val txSet = getTransactionSetInScope - log.trace("Committing transaction [%s]\n\tby joining transaction set [%s]", mtx, txSet) - txSet.joinCommit(mtx) - - // FIXME tryJoinCommit(mtx, TransactionManagement.TRANSACTION_TIMEOUT, TimeUnit.MILLISECONDS) - //getTransactionSetInScope.tryJoinCommit(mtx, TransactionManagement.TRANSACTION_TIMEOUT, TimeUnit.MILLISECONDS) - - clearTransaction - result - } + def execute(mtx: MultiverseTransaction): T = body override def onStart(mtx: MultiverseTransaction) = { - val txSet = - if (!isTransactionSetInScope) { - isTopLevelTransaction = true - createNewTransactionSet - } else getTransactionSetInScope val tx = new Transaction tx.transaction = Some(mtx) setTransaction(Some(tx)) - - txSet.registerOnCommitTask(new Runnable() { - def run = tx.commit - }) - txSet.registerOnAbortTask(new Runnable() { - def run = tx.abort + mtx.registerLifecycleListener(new TransactionLifecycleListener() { + def notify(tx: MultiverseTransaction, event: TransactionLifecycleEvent) = event.name match { + case "postCommit" => tx.commit + case "postAbort" => tx.abort + case _ => {} + } }) } }.execute() @@ -170,24 +164,70 @@ object Transaction extends TransactionManagement with Logging { def orelserun(t: MultiverseTransaction) = secondBody }.execute() } + } + + object Global extends TransactionManagement with Logging { + /** + * See ScalaDoc on Transaction class. + */ + def map[T](f: => T): T = atomic {f} /** - * Creates a STM atomic transaction and by-passes all transactions hooks - * such as persistence etc. - * - * Only for internal usage. + * See ScalaDoc on Transaction class. */ - private[akka] def atomic0[T](body: => T): T = new TransactionTemplate[T]() { - def execute(mtx: MultiverseTransaction): T = body - }.execute() + def flatMap[T](f: => T): T = atomic {f} + + /** + * See ScalaDoc on Transaction class. + */ + def foreach(f: => Unit): Unit = atomic {f} + + /** + * See ScalaDoc on Transaction class. + */ + def atomic[T](body: => T): T = { + var isTopLevelTransaction = false + new TransactionTemplate[T]() { + def execute(mtx: MultiverseTransaction): T = { + val result = body + + val txSet = getTransactionSetInScope + log.trace("Committing transaction [%s]\n\tby joining transaction set [%s]", mtx, txSet) + txSet.joinCommit(mtx) + + // FIXME tryJoinCommit(mtx, TransactionManagement.TRANSACTION_TIMEOUT, TimeUnit.MILLISECONDS) + //getTransactionSetInScope.tryJoinCommit(mtx, TransactionManagement.TRANSACTION_TIMEOUT, TimeUnit.MILLISECONDS) + + clearTransaction + result + } + + override def onStart(mtx: MultiverseTransaction) = { + val txSet = + if (!isTransactionSetInScope) { + isTopLevelTransaction = true + createNewTransactionSet + } else getTransactionSetInScope + val tx = new Transaction + tx.transaction = Some(mtx) + setTransaction(Some(tx)) + + txSet.registerOnCommitTask(new Runnable() { + def run = tx.commit + }) + txSet.registerOnAbortTask(new Runnable() { + def run = tx.abort + }) + } + }.execute() + } + } } /** * @author Jonas Bonér */ @serializable class Transaction extends Logging { - import Transaction._ - val id = Transaction.idFactory.incrementAndGet @volatile private[this] var status: TransactionStatus = TransactionStatus.New private[akka] var transaction: Option[MultiverseTransaction] = None @@ -200,7 +240,7 @@ object Transaction extends TransactionManagement with Logging { def commit = synchronized { log.trace("Committing transaction %s", toString) - atomic0 { + Transaction.atomic0 { persistentStateMap.valuesIterator.foreach(_.commit) } status = TransactionStatus.Completed diff --git a/akka-core/src/main/scala/stm/TransactionManagement.scala b/akka-core/src/main/scala/stm/TransactionManagement.scala index 48c8c7dd95..401c2379ee 100644 --- a/akka-core/src/main/scala/stm/TransactionManagement.scala +++ b/akka-core/src/main/scala/stm/TransactionManagement.scala @@ -4,6 +4,8 @@ package se.scalablesolutions.akka.stm +import se.scalablesolutions.akka.util.Logging + import java.util.concurrent.atomic.AtomicBoolean import org.multiverse.api.ThreadLocalTransaction._ @@ -49,9 +51,10 @@ object TransactionManagement extends TransactionManagement { } } -trait TransactionManagement { +trait TransactionManagement extends Logging { private[akka] def createNewTransactionSet: CountDownCommitBarrier = { + log.trace("Creating new transaction set") val txSet = new CountDownCommitBarrier(1, TransactionManagement.FAIR_TRANSACTIONS) TransactionManagement.transactionSet.set(Some(txSet)) txSet @@ -63,9 +66,13 @@ trait TransactionManagement { private[akka] def setTransaction(tx: Option[Transaction]) = if (tx.isDefined) TransactionManagement.transaction.set(tx) - private[akka] def clearTransactionSet = TransactionManagement.transactionSet.set(None) + private[akka] def clearTransactionSet = { + log.trace("Clearing transaction set") + TransactionManagement.transactionSet.set(None) + } private[akka] def clearTransaction = { + log.trace("Clearing transaction") TransactionManagement.transaction.set(None) setThreadLocalTransaction(null) } diff --git a/akka-core/src/main/scala/stm/TransactionalState.scala b/akka-core/src/main/scala/stm/TransactionalState.scala index a8b5da83b9..7afb3fb6bb 100644 --- a/akka-core/src/main/scala/stm/TransactionalState.scala +++ b/akka-core/src/main/scala/stm/TransactionalState.scala @@ -4,7 +4,6 @@ package se.scalablesolutions.akka.stm -import se.scalablesolutions.akka.stm.Transaction.atomic import se.scalablesolutions.akka.util.UUID import org.multiverse.stms.alpha.AlphaRef diff --git a/akka-core/src/test/scala/AgentTest.scala b/akka-core/src/test/scala/AgentTest.scala index 01818e1938..b378b67207 100644 --- a/akka-core/src/test/scala/AgentTest.scala +++ b/akka-core/src/test/scala/AgentTest.scala @@ -2,7 +2,7 @@ package se.scalablesolutions.akka.actor import _root_.java.util.concurrent.TimeUnit import se.scalablesolutions.akka.actor.Actor.transactor -import se.scalablesolutions.akka.stm.Transaction.atomic +import se.scalablesolutions.akka.stm.Transaction.Global.atomic import se.scalablesolutions.akka.util.Logging import org.scalatest.Suite diff --git a/akka-core/src/test/scala/StmSpec.scala b/akka-core/src/test/scala/StmSpec.scala new file mode 100644 index 0000000000..121407426a --- /dev/null +++ b/akka-core/src/test/scala/StmSpec.scala @@ -0,0 +1,81 @@ +package se.scalablesolutions.akka.actor + +import se.scalablesolutions.akka.stm.Transaction.Local._ +import se.scalablesolutions.akka.stm._ + +import org.scalatest.Spec +import org.scalatest.Assertions +import org.scalatest.matchers.ShouldMatchers +import org.scalatest.BeforeAndAfterAll +import org.scalatest.junit.JUnitRunner +import org.junit.runner.RunWith + +@RunWith(classOf[JUnitRunner]) +class StmSpec extends + Spec with + ShouldMatchers with + BeforeAndAfterAll { + + describe("STM outside actors") { + it("should be able to do multiple consecutive atomic {..} statements") { + + lazy val ref = TransactionalState.newRef[Int] + + def increment = atomic { + ref.swap(ref.get.getOrElse(0) + 1) + } + + def total: Int = atomic { + ref.get.getOrElse(0) + } + + increment + increment + increment + total should equal(3) + } + + it("should be able to do nested atomic {..} statements") { + + lazy val ref = TransactionalState.newRef[Int] + + def increment = atomic { + ref.swap(ref.get.getOrElse(0) + 1) + } + def total: Int = atomic { + ref.get.getOrElse(0) + } + + atomic { + increment + increment + } + atomic { + increment + total should equal(3) + } + } + + it("should roll back failing nested atomic {..} statements") { + + lazy val ref = TransactionalState.newRef[Int] + + def increment = atomic { + ref.swap(ref.get.getOrElse(0) + 1) + } + def total: Int = atomic { + ref.get.getOrElse(0) + } + try { + atomic { + increment + increment + throw new Exception + } + } catch { + case e => {} + } + total should equal(0) + } + } +} diff --git a/akka-samples/akka-sample-chat/src/main/scala/ChatServer.scala b/akka-samples/akka-sample-chat/src/main/scala/ChatServer.scala index 6afd7baaf2..6f1d93feb6 100644 --- a/akka-samples/akka-sample-chat/src/main/scala/ChatServer.scala +++ b/akka-samples/akka-sample-chat/src/main/scala/ChatServer.scala @@ -10,7 +10,7 @@ import se.scalablesolutions.akka.actor.{SupervisorFactory, Actor, RemoteActor} import se.scalablesolutions.akka.remote.{RemoteNode, RemoteClient} import se.scalablesolutions.akka.persistence.common.PersistentVector import se.scalablesolutions.akka.persistence.redis.RedisStorage -import se.scalablesolutions.akka.stm.Transaction._ +import se.scalablesolutions.akka.stm.Transaction.Global._ import se.scalablesolutions.akka.config.ScalaConfig._ import se.scalablesolutions.akka.config.OneForOneStrategy import se.scalablesolutions.akka.util.Logging From c382e449a0becff26918354af2c378e2572237d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Bon=C3=A9r?= Date: Mon, 5 Apr 2010 12:32:15 +0200 Subject: [PATCH 3/4] cleaned up packaging in samples to all be "sample.x" --- .../src/main/scala/stm/Transaction.scala | 193 +++++++++++------- akka-kernel/src/main/scala/Kernel.scala | 4 +- .../src/main/scala/ChatServer.scala | 2 +- .../java/sample/{ => rest}/java/Boot.java | 6 +- .../java/PersistentSimpleService.java | 2 +- .../sample/{ => rest}/java/SimpleService.java | 2 +- .../src/main/scala/SimpleService.scala | 2 +- .../src/main/scala/SimpleService.scala | 2 +- config/akka-reference.conf | 10 +- 9 files changed, 133 insertions(+), 90 deletions(-) rename akka-samples/akka-sample-rest-java/src/main/java/sample/{ => rest}/java/Boot.java (83%) rename akka-samples/akka-sample-rest-java/src/main/java/sample/{ => rest}/java/PersistentSimpleService.java (98%) rename akka-samples/akka-sample-rest-java/src/main/java/sample/{ => rest}/java/SimpleService.java (98%) diff --git a/akka-core/src/main/scala/stm/Transaction.scala b/akka-core/src/main/scala/stm/Transaction.scala index 221ab86bd6..9581d46546 100644 --- a/akka-core/src/main/scala/stm/Transaction.scala +++ b/akka-core/src/main/scala/stm/Transaction.scala @@ -22,81 +22,6 @@ import org.multiverse.stms.alpha.AlphaStm class NoTransactionInScopeException extends RuntimeException class TransactionRetryException(message: String) extends RuntimeException(message) -/** - * Example of atomic transaction management using the atomic block. - * These blocks takes an implicit argument String defining the transaction family name. - * If these blocks are used from within an Actor then the name is automatically resolved, if not either: - * 1. define an implicit String with the name in the same scope - * 2. pass in the name explicitly - * - * Here are some examples (assuming implicit transaction family name in scope): - *
- * import se.scalablesolutions.akka.stm.Transaction._
- *
- * atomic  {
- *   .. // do something within a transaction
- * }
- * 
- * - * Example of atomic transaction management using atomic block with retry count: - *
- * import se.scalablesolutions.akka.stm.Transaction._
- *
- * atomic(maxNrOfRetries)  {
- *   .. // do something within a transaction
- * }
- * 
- * - * Example of atomically-orElse transaction management. - * Which is a good way to reduce contention and transaction collisions. - *
- * import se.scalablesolutions.akka.stm.Transaction._
- *
- * atomically  {
- *   .. // try to do something
- * } orElse  {
- *   .. // if transaction clashes try do do something else to minimize contention
- * }
- * 
- * - * Example of atomic transaction management using for comprehensions (monadic): - * - *
- * import se.scalablesolutions.akka.stm.Transaction._
- * for (tx <- Transaction)  {
- *   ... // do transactional stuff
- * }
- *
- * val result = for (tx <- Transaction) yield  {
- *   ... // do transactional stuff yielding a result
- * }
- * 
- * - * Example of using Transaction and TransactionalRef in for comprehensions (monadic): - * - *
- * // 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
- * for  {
- *   tx <- Transaction
- *   ref <- refs
- * } {
- *   ... // use the ref inside a transaction
- * }
- *
- * val result = for  {
- *   tx <- Transaction
- *   ref <- refs
- * } yield  {
- *   ... // use the ref inside a transaction, yield a result
- * }
- * 
- * - * @author Jonas Bonér - */ object Transaction { val idFactory = new AtomicLong(-1L) @@ -110,6 +35,71 @@ object Transaction { def execute(mtx: MultiverseTransaction): T = body }.execute() + /** + * Module for "local" transaction management, local in the context of threads. + * You should only use these if you do not need to have one transaction span + * multiple threads (or Actors). + *

+ * Example of atomic transaction management using the atomic block. + *

+ *

+   * import se.scalablesolutions.akka.stm.Transaction.Local._
+   *
+   * atomic  {
+   *   .. // do something within a transaction
+   * }
+   * 
+ * + * Example of atomically-orElse transaction management. + * Which is a good way to reduce contention and transaction collisions. + *
+   * import se.scalablesolutions.akka.stm.Transaction.Local._
+   *
+   * atomically  {
+   *   .. // try to do something
+   * } orElse  {
+   *   .. // if transaction clashes try do do something else to minimize contention
+   * }
+   * 
+ * + * Example of atomic transaction management using for comprehensions (monadic): + * + *
+   * import se.scalablesolutions.akka.stm.Transaction.Local._
+   * for (tx <- Transaction)  {
+   *   ... // do transactional stuff
+   * }
+   *
+   * val result = for (tx <- Transaction) yield  {
+   *   ... // do transactional stuff yielding a result
+   * }
+   * 
+ * + * Example of using Transaction and TransactionalRef in for comprehensions (monadic): + * + *
+   * // 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
+   * for  {
+   *   tx <- Transaction
+   *   ref <- refs
+   * } {
+   *   ... // use the ref inside a transaction
+   * }
+   *
+   * val result = for  {
+   *   tx <- Transaction
+   *   ref <- refs
+   * } yield  {
+   *   ... // use the ref inside a transaction, yield a result
+   * }
+   * 
+ * + * @author Jonas Bonér + */ object Local extends TransactionManagement with Logging { /** @@ -166,6 +156,59 @@ object Transaction { } } + /** + * Module for "global" transaction management, global in the context of multiple threads. + * You have to use these if you do need to have one transaction span multiple threads (or Actors). + *

+ * Example of atomic transaction management using the atomic block. + *

+ * Here are some examples (assuming implicit transaction family name in scope): + *

+   * import se.scalablesolutions.akka.stm.Transaction.Global._
+   *
+   * atomic  {
+   *   .. // do something within a transaction
+   * }
+   * 
+ * + * Example of atomic transaction management using for comprehensions (monadic): + * + *
+   * import se.scalablesolutions.akka.stm.Transaction.Global_
+   * for (tx <- Transaction)  {
+   *   ... // do transactional stuff
+   * }
+   *
+   * val result = for (tx <- Transaction) yield  {
+   *   ... // do transactional stuff yielding a result
+   * }
+   * 
+ * + * Example of using Transaction and TransactionalRef in for comprehensions (monadic): + * + *
+   * // 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
+   * for  {
+   *   tx <- Transaction
+   *   ref <- refs
+   * } {
+   *   ... // use the ref inside a transaction
+   * }
+   *
+   * val result = for  {
+   *   tx <- Transaction
+   *   ref <- refs
+   * } yield  {
+   *   ... // use the ref inside a transaction, yield a result
+   * }
+   * 
+ * + * @author Jonas Bonér + */ object Global extends TransactionManagement with Logging { /** * See ScalaDoc on Transaction class. diff --git a/akka-kernel/src/main/scala/Kernel.scala b/akka-kernel/src/main/scala/Kernel.scala index 6c0cd87058..6154e26ab2 100644 --- a/akka-kernel/src/main/scala/Kernel.scala +++ b/akka-kernel/src/main/scala/Kernel.scala @@ -79,14 +79,14 @@ object Kernel extends Logging { log.info( """ ============================== - __ __ + __ __ _____ | | _| | _______ \__ \ | |/ / |/ /\__ \ / __ \| <| < / __ \_ (____ /__|_ \__|_ \(____ / \/ \/ \/ \/ """) - log.info(" Running version %s", Config.VERSION) + log.info(" Running version %s", Config.VERSION) log.info("==============================") } } diff --git a/akka-samples/akka-sample-chat/src/main/scala/ChatServer.scala b/akka-samples/akka-sample-chat/src/main/scala/ChatServer.scala index 6f1d93feb6..6d4bf9679e 100644 --- a/akka-samples/akka-sample-chat/src/main/scala/ChatServer.scala +++ b/akka-samples/akka-sample-chat/src/main/scala/ChatServer.scala @@ -2,7 +2,7 @@ * Copyright (C) 2009-2010 Scalable Solutions AB . */ -package se.scalablesolutions.akka.sample.chat +package sample.chat import scala.collection.mutable.HashMap diff --git a/akka-samples/akka-sample-rest-java/src/main/java/sample/java/Boot.java b/akka-samples/akka-sample-rest-java/src/main/java/sample/rest/java/Boot.java similarity index 83% rename from akka-samples/akka-sample-rest-java/src/main/java/sample/java/Boot.java rename to akka-samples/akka-sample-rest-java/src/main/java/sample/rest/java/Boot.java index 888344013d..2f97b4ce92 100644 --- a/akka-samples/akka-sample-rest-java/src/main/java/sample/java/Boot.java +++ b/akka-samples/akka-sample-rest-java/src/main/java/sample/rest/java/Boot.java @@ -1,4 +1,4 @@ -package sample.java; +package sample.rest.java; import se.scalablesolutions.akka.config.ActiveObjectConfigurator; import static se.scalablesolutions.akka.config.JavaConfig.*; @@ -11,11 +11,11 @@ public class Boot { new RestartStrategy(new OneForOne(), 3, 5000, new Class[]{Exception.class}), new Component[] { new Component( - sample.java.SimpleService.class, + SimpleService.class, new LifeCycle(new Permanent()), 1000), new Component( - sample.java.PersistentSimpleService.class, + PersistentSimpleService.class, new LifeCycle(new Permanent()), 1000) }).supervise(); diff --git a/akka-samples/akka-sample-rest-java/src/main/java/sample/java/PersistentSimpleService.java b/akka-samples/akka-sample-rest-java/src/main/java/sample/rest/java/PersistentSimpleService.java similarity index 98% rename from akka-samples/akka-sample-rest-java/src/main/java/sample/java/PersistentSimpleService.java rename to akka-samples/akka-sample-rest-java/src/main/java/sample/rest/java/PersistentSimpleService.java index 221b5613b8..2a2abf2443 100644 --- a/akka-samples/akka-sample-rest-java/src/main/java/sample/java/PersistentSimpleService.java +++ b/akka-samples/akka-sample-rest-java/src/main/java/sample/rest/java/PersistentSimpleService.java @@ -2,7 +2,7 @@ * Copyright (C) 2009-2010 Scalable Solutions AB */ -package sample.java; +package sample.rest.java; import javax.ws.rs.Path; import javax.ws.rs.GET; diff --git a/akka-samples/akka-sample-rest-java/src/main/java/sample/java/SimpleService.java b/akka-samples/akka-sample-rest-java/src/main/java/sample/rest/java/SimpleService.java similarity index 98% rename from akka-samples/akka-sample-rest-java/src/main/java/sample/java/SimpleService.java rename to akka-samples/akka-sample-rest-java/src/main/java/sample/rest/java/SimpleService.java index b10bcdaea4..19d5cab8f9 100644 --- a/akka-samples/akka-sample-rest-java/src/main/java/sample/java/SimpleService.java +++ b/akka-samples/akka-sample-rest-java/src/main/java/sample/rest/java/SimpleService.java @@ -2,7 +2,7 @@ * Copyright (C) 2009-2010 Scalable Solutions AB */ -package sample.java; +package sample.rest.java; import javax.ws.rs.Path; import javax.ws.rs.GET; diff --git a/akka-samples/akka-sample-rest-scala/src/main/scala/SimpleService.scala b/akka-samples/akka-sample-rest-scala/src/main/scala/SimpleService.scala index 9422283baf..7f1070ec7a 100644 --- a/akka-samples/akka-sample-rest-scala/src/main/scala/SimpleService.scala +++ b/akka-samples/akka-sample-rest-scala/src/main/scala/SimpleService.scala @@ -2,7 +2,7 @@ * Copyright (C) 2009-2010 Scalable Solutions AB */ -package sample.scala +package sample.rest.scala import se.scalablesolutions.akka.actor.{Transactor, SupervisorFactory, Actor} import se.scalablesolutions.akka.stm.TransactionalState diff --git a/akka-samples/akka-sample-security/src/main/scala/SimpleService.scala b/akka-samples/akka-sample-security/src/main/scala/SimpleService.scala index 92b742ab8b..6dfd405621 100644 --- a/akka-samples/akka-sample-security/src/main/scala/SimpleService.scala +++ b/akka-samples/akka-sample-security/src/main/scala/SimpleService.scala @@ -2,7 +2,7 @@ * Copyright (C) 2009-2010 Scalable Solutions AB */ -package se.scalablesolutions.akka.security.samples +package sample.security import se.scalablesolutions.akka.actor.{SupervisorFactory, Actor} import se.scalablesolutions.akka.config.ScalaConfig._ diff --git a/config/akka-reference.conf b/config/akka-reference.conf index c539ff1951..25981591af 100644 --- a/config/akka-reference.conf +++ b/config/akka-reference.conf @@ -20,9 +20,9 @@ # FQN to the class doing initial active object/actor # supervisor bootstrap, should be defined in default constructor boot = ["sample.camel.Boot", - "sample.java.Boot", - "sample.scala.Boot", - "se.scalablesolutions.akka.security.samples.Boot"] + "sample.rest.java.Boot", + "sample.rest.scala.Boot", + "sample.security.Boot"] timeout = 5000 # default timeout for future based invocations @@ -41,8 +41,8 @@ service = on hostname = "localhost" port = 9998 - filters = ["se.scalablesolutions.akka.security.AkkaSecurityFilterFactory"] # List with all jersey filters to use - authenticator = "se.scalablesolutions.akka.security.samples.BasicAuthenticationService" # The authentication service to use + filters = ["se.scalablesolutions.akka.security.AkkaSecurityFilterFactory"] # List with all jersey filters to use + authenticator = "sample.security.BasicAuthenticationService" # The authentication service to use. Need to be overridden (uses sample now) From 98f85a783eec9ef2c42ae55afd2cbdb0f8c5bf8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Bon=C3=A9r?= Date: Mon, 5 Apr 2010 13:04:18 +0200 Subject: [PATCH 4/4] Improved scaladoc for Transaction --- .../src/main/scala/stm/Transaction.scala | 219 +++++++++--------- ...wardActor.scala => ForwardActorSpec.scala} | 6 +- 2 files changed, 114 insertions(+), 111 deletions(-) rename akka-core/src/test/scala/{ForwardActor.scala => ForwardActorSpec.scala} (90%) diff --git a/akka-core/src/main/scala/stm/Transaction.scala b/akka-core/src/main/scala/stm/Transaction.scala index 9581d46546..16a3cd0e5f 100644 --- a/akka-core/src/main/scala/stm/Transaction.scala +++ b/akka-core/src/main/scala/stm/Transaction.scala @@ -28,7 +28,7 @@ object Transaction { /** * Creates a STM atomic transaction and by-passes all transactions hooks * such as persistence etc. - * + * * Only for internal usage. */ private[akka] def atomic0[T](body: => T): T = new TransactionTemplate[T]() { @@ -37,7 +37,7 @@ object Transaction { /** * Module for "local" transaction management, local in the context of threads. - * You should only use these if you do not need to have one transaction span + * You should only use these if you do not need to have one transaction span * multiple threads (or Actors). *

* Example of atomic transaction management using the atomic block. @@ -50,7 +50,7 @@ object Transaction { * } * * - * Example of atomically-orElse transaction management. + * Example of atomically-orElse transaction management. * Which is a good way to reduce contention and transaction collisions. *

    * import se.scalablesolutions.akka.stm.Transaction.Local._
@@ -66,11 +66,11 @@ object Transaction {
    *
    * 
    * import se.scalablesolutions.akka.stm.Transaction.Local._
-   * for (tx <- Transaction)  {
+   * for (tx <- Transaction.Local)  {
    *   ... // do transactional stuff
    * }
    *
-   * val result = for (tx <- Transaction) yield  {
+   * val result = for (tx <- Transaction.Local) yield  {
    *   ... // do transactional stuff yielding a result
    * }
    * 
@@ -84,14 +84,14 @@ object Transaction { * // You can use them together with Transaction in a for comprehension since * // TransactionalRef is also monadic * for { - * tx <- Transaction + * tx <- Transaction.Local * ref <- refs * } { * ... // use the ref inside a transaction * } * * val result = for { - * tx <- Transaction + * tx <- Transaction.Local * ref <- refs * } yield { * ... // use the ref inside a transaction, yield a result @@ -102,58 +102,58 @@ object Transaction { */ object Local extends TransactionManagement with Logging { - /** - * See ScalaDoc on Transaction class. - */ - def map[T](f: => T): T = atomic {f} + /** + * See ScalaDoc on Transaction.Local class. + */ + def map[T](f: => T): T = atomic {f} - /** - * See ScalaDoc on Transaction class. - */ - def flatMap[T](f: => T): T = atomic {f} + /** + * See ScalaDoc on Transaction.Local class. + */ + def flatMap[T](f: => T): T = atomic {f} - /** - * See ScalaDoc on Transaction class. - */ - def foreach(f: => Unit): Unit = atomic {f} + /** + * See ScalaDoc on Transaction.Local class. + */ + def foreach(f: => Unit): Unit = atomic {f} - /** - * See ScalaDoc on class. - */ - def atomic[T](body: => T): T = { - new TransactionTemplate[T]() { - def execute(mtx: MultiverseTransaction): T = body + /** + * See ScalaDoc on Transaction.Local class. + */ + def atomic[T](body: => T): T = { + new TransactionTemplate[T]() { + def execute(mtx: MultiverseTransaction): T = body - override def onStart(mtx: MultiverseTransaction) = { - val tx = new Transaction - tx.transaction = Some(mtx) - setTransaction(Some(tx)) - mtx.registerLifecycleListener(new TransactionLifecycleListener() { - def notify(tx: MultiverseTransaction, event: TransactionLifecycleEvent) = event.name match { - case "postCommit" => tx.commit - case "postAbort" => tx.abort - case _ => {} - } - }) - } - }.execute() - } + override def onStart(mtx: MultiverseTransaction) = { + val tx = new Transaction + tx.transaction = Some(mtx) + setTransaction(Some(tx)) + mtx.registerLifecycleListener(new TransactionLifecycleListener() { + def notify(tx: MultiverseTransaction, event: TransactionLifecycleEvent) = event.name match { + case "postCommit" => tx.commit + case "postAbort" => tx.abort + case _ => {} + } + }) + } + }.execute() + } - /** - * See ScalaDoc on class. - */ - def atomically[A](firstBody: => A) = elseBody(firstBody) + /** + * See ScalaDoc on Transaction.Local class. + */ + def atomically[A](firstBody: => A) = elseBody(firstBody) - /** - * Should only be used together with atomically to form atomically-orElse constructs. - * See ScalaDoc on class. - */ - def elseBody[A](firstBody: => A) = new { - def orElse(secondBody: => A) = new OrElseTemplate[A] { - def run(t: MultiverseTransaction) = firstBody - def orelserun(t: MultiverseTransaction) = secondBody - }.execute() - } + /** + * Should only be used together with atomically to form atomically-orElse constructs. + * See ScalaDoc on class. + */ + def elseBody[A](firstBody: => A) = new { + def orElse(secondBody: => A) = new OrElseTemplate[A] { + def run(t: MultiverseTransaction) = firstBody + def orelserun(t: MultiverseTransaction) = secondBody + }.execute() + } } /** @@ -162,7 +162,7 @@ object Transaction { *

* Example of atomic transaction management using the atomic block. *

- * Here are some examples (assuming implicit transaction family name in scope): + * Here are some examples (assuming implicit transaction family name in scope): *

    * import se.scalablesolutions.akka.stm.Transaction.Global._
    *
@@ -174,12 +174,12 @@ object Transaction {
    * Example of atomic transaction management using for comprehensions (monadic):
    *
    * 
-   * import se.scalablesolutions.akka.stm.Transaction.Global_
-   * for (tx <- Transaction)  {
+   * import se.scalablesolutions.akka.stm.Transaction
+   * for (tx <- Transaction.Global)  {
    *   ... // do transactional stuff
    * }
    *
-   * val result = for (tx <- Transaction) yield  {
+   * val result = for (tx <- Transaction.Global) yield  {
    *   ... // do transactional stuff yielding a result
    * }
    * 
@@ -193,14 +193,14 @@ object Transaction { * // You can use them together with Transaction in a for comprehension since * // TransactionalRef is also monadic * for { - * tx <- Transaction + * tx <- Transaction.Global * ref <- refs * } { * ... // use the ref inside a transaction * } * * val result = for { - * tx <- Transaction + * tx <- Transaction.Global * ref <- refs * } yield { * ... // use the ref inside a transaction, yield a result @@ -210,64 +210,67 @@ object Transaction { * @author Jonas Bonér */ object Global extends TransactionManagement with Logging { - /** - * See ScalaDoc on Transaction class. - */ - def map[T](f: => T): T = atomic {f} - /** - * See ScalaDoc on Transaction class. - */ - def flatMap[T](f: => T): T = atomic {f} + /** + * See ScalaDoc on Transaction.Global class. + */ + def map[T](f: => T): T = atomic {f} - /** - * See ScalaDoc on Transaction class. - */ - def foreach(f: => Unit): Unit = atomic {f} + /** + * See ScalaDoc on Transaction.Global class. + */ + def flatMap[T](f: => T): T = atomic {f} - /** - * See ScalaDoc on Transaction class. - */ - def atomic[T](body: => T): T = { - var isTopLevelTransaction = false - new TransactionTemplate[T]() { - def execute(mtx: MultiverseTransaction): T = { - val result = body + /** + * See ScalaDoc on Transaction.Global class. + */ + def foreach(f: => Unit): Unit = atomic {f} - val txSet = getTransactionSetInScope - log.trace("Committing transaction [%s]\n\tby joining transaction set [%s]", mtx, txSet) - txSet.joinCommit(mtx) + /** + * See ScalaDoc on Transaction.Global class. + */ + def atomic[T](body: => T): T = { + var isTopLevelTransaction = false + new TransactionTemplate[T]() { + def execute(mtx: MultiverseTransaction): T = { + val result = body - // FIXME tryJoinCommit(mtx, TransactionManagement.TRANSACTION_TIMEOUT, TimeUnit.MILLISECONDS) - //getTransactionSetInScope.tryJoinCommit(mtx, TransactionManagement.TRANSACTION_TIMEOUT, TimeUnit.MILLISECONDS) + val txSet = getTransactionSetInScope + log.trace("Committing transaction [%s]\n\tby joining transaction set [%s]", mtx, txSet) + txSet.joinCommit(mtx) - clearTransaction - result - } + // FIXME tryJoinCommit(mtx, TransactionManagement.TRANSACTION_TIMEOUT, TimeUnit.MILLISECONDS) + //getTransactionSetInScope.tryJoinCommit(mtx, TransactionManagement.TRANSACTION_TIMEOUT, TimeUnit.MILLISECONDS) - override def onStart(mtx: MultiverseTransaction) = { - val txSet = - if (!isTransactionSetInScope) { - isTopLevelTransaction = true - createNewTransactionSet - } else getTransactionSetInScope - val tx = new Transaction - tx.transaction = Some(mtx) - setTransaction(Some(tx)) + clearTransaction + result + } - txSet.registerOnCommitTask(new Runnable() { - def run = tx.commit - }) - txSet.registerOnAbortTask(new Runnable() { - def run = tx.abort - }) - } - }.execute() - } + override def onStart(mtx: MultiverseTransaction) = { + val txSet = + if (!isTransactionSetInScope) { + isTopLevelTransaction = true + createNewTransactionSet + } else getTransactionSetInScope + val tx = new Transaction + tx.transaction = Some(mtx) + setTransaction(Some(tx)) + + txSet.registerOnCommitTask(new Runnable() { + def run = tx.commit + }) + txSet.registerOnAbortTask(new Runnable() { + def run = tx.abort + }) + } + }.execute() + } } } /** + * The Akka specific Transaction class, keeping track of persistent data structures (as in on-disc). + * * @author Jonas Bonér */ @serializable class Transaction extends Logging { @@ -282,7 +285,7 @@ object Transaction { // --- public methods --------- def commit = synchronized { - log.trace("Committing transaction %s", toString) + log.trace("Committing transaction %s", toString) Transaction.atomic0 { persistentStateMap.valuesIterator.foreach(_.commit) } @@ -290,7 +293,7 @@ object Transaction { } def abort = synchronized { - log.trace("Aborting transaction %s", toString) + log.trace("Aborting transaction %s", toString) } def isNew = synchronized { status == TransactionStatus.New } @@ -327,7 +330,7 @@ object Transaction { throw new IllegalStateException( "Expected ACTIVE or NEW transaction - current status [" + status + "]: " + toString) - // For reinitialize transaction after sending it over the wire + // For reinitialize transaction after sending it over the wire /* private[akka] def reinit = synchronized { import net.lag.logging.{Logger, Level} if (log eq null) { diff --git a/akka-core/src/test/scala/ForwardActor.scala b/akka-core/src/test/scala/ForwardActorSpec.scala similarity index 90% rename from akka-core/src/test/scala/ForwardActor.scala rename to akka-core/src/test/scala/ForwardActorSpec.scala index 0e8f606b27..575bbab7dd 100644 --- a/akka-core/src/test/scala/ForwardActor.scala +++ b/akka-core/src/test/scala/ForwardActorSpec.scala @@ -5,7 +5,7 @@ import org.scalatest.junit.JUnitSuite import org.junit.Test -class ForwardActorTest extends JUnitSuite { +class ForwardActorSpec extends JUnitSuite { object ForwardState { var sender: Actor = null @@ -57,7 +57,7 @@ class ForwardActorTest extends JUnitSuite { def shouldForwardActorReferenceWhenInvokingForwardOnBang = { val senderActor = new BangSenderActor senderActor.start - assert(ForwardState.finished.await(1, TimeUnit.SECONDS)) + assert(ForwardState.finished.await(2, TimeUnit.SECONDS)) assert(ForwardState.sender ne null) assert(senderActor === ForwardState.sender) } @@ -66,6 +66,6 @@ class ForwardActorTest extends JUnitSuite { def shouldForwardActorReferenceWhenInvokingForwardOnBangBang = { val senderActor = new BangBangSenderActor senderActor.start - assert(ForwardState.finished.await(1, TimeUnit.SECONDS)) + assert(ForwardState.finished.await(2, TimeUnit.SECONDS)) } }