diff --git a/akka-tutorials/akka-tutorial-pi-sbt/project/build.properties b/akka-tutorials/akka-tutorial-first/project/build.properties similarity index 100% rename from akka-tutorials/akka-tutorial-pi-sbt/project/build.properties rename to akka-tutorials/akka-tutorial-first/project/build.properties diff --git a/akka-tutorials/akka-tutorial-pi-sbt/project/plugins/Plugins.scala b/akka-tutorials/akka-tutorial-first/project/plugins/Plugins.scala similarity index 100% rename from akka-tutorials/akka-tutorial-pi-sbt/project/plugins/Plugins.scala rename to akka-tutorials/akka-tutorial-first/project/plugins/Plugins.scala diff --git a/akka-tutorials/akka-tutorial-first/src/main/java/akka/tutorial/java/first/Pi.java b/akka-tutorials/akka-tutorial-first/src/main/java/akka/tutorial/java/first/Pi.java new file mode 100644 index 0000000000..45ac3fad9c --- /dev/null +++ b/akka-tutorials/akka-tutorial-first/src/main/java/akka/tutorial/java/first/Pi.java @@ -0,0 +1,208 @@ +/** + * Copyright (C) 2009-2011 Scalable Solutions AB + */ + +package akka.tutorial.java.first; + +import akka.actor.*; +import static akka.actor.Actors.*; + +import akka.routing.*; +import static akka.routing.Routing.Broadcast; + +import akka.dispatch.Dispatchers; + +import static java.util.Arrays.asList; +import java.util.concurrent.CountDownLatch; + +/** + * First part in Akka tutorial for Java. + *

+ * Calculates Pi. + *

+ * Run on command line: + *

+ *   $ cd akka-1.1
+ *   $ export AKKA_HOME=`pwd`
+ *   $ javac -cp dist/akka-actor-1.1-SNAPSHOT.jar:scala-library.jar akka/tutorial/java/first/Pi.java
+ *   $ java -cp dist/akka-actor-1.1-SNAPSHOT.jar:scala-library.jar:. akka.tutorial.java.first.Pi
+ *   $ ...
+ * 
+ *

+ * Run it in Maven: + *

+ *   $ mvn
+ *   > scala:console
+ *   > val pi = new akka.tutorial.java.first.Pi
+ *   > pi.calculate(4, 10000, 10000)
+ *   > ...
+ * 
+ * + * @author Jonas Bonér + */ +public class Pi { + + public static void main(String[] args) throws Exception { + Pi pi = new Pi(); + pi.calculate(4, 10000, 10000); + } + + // ==================== + // ===== Messages ===== + // ==================== + static class Calculate {} + + static class Work { + private final int arg; + private final int nrOfElements; + + public Work(int arg, int nrOfElements) { + this.arg = arg; + this.nrOfElements = nrOfElements; + } + + public int getArg() { return arg; } + public int getNrOfElements() { return nrOfElements; } + } + + static class Result { + private final double value; + + public Result(double value) { + this.value = value; + } + + public double getValue() { return value; } + } + + // ================== + // ===== Worker ===== + // ================== + static class Worker extends UntypedActor { + + // define the work + private double calculatePiFor(int arg, int nrOfElements) { + double acc = 0.0D; + for (int i = arg * nrOfElements; i <= ((arg + 1) * nrOfElements - 1); i++) { + acc += 4 * Math.pow(-1, i) / (2 * i + 1); + } + return acc; + } + + // message handler + public void onReceive(Object message) { + if (message instanceof Work) { + Work work = (Work)message; + getContext().replyUnsafe(new Result(calculatePiFor(work.getArg(), work.getNrOfElements()))); // perform the work + } else throw new IllegalArgumentException("Unknown message [" + message + "]"); + } + } + + // ================== + // ===== Master ===== + // ================== + static class Master extends UntypedActor { + private final int nrOfWorkers; + private final int nrOfMessages; + private final int nrOfElements; + private final CountDownLatch latch; + + private double pi; + private int nrOfResults; + private long start; + + private ActorRef router; + + static class PiRouter extends UntypedLoadBalancer { + private final InfiniteIterator workers; + + public PiRouter(ActorRef[] workers) { + this.workers = new CyclicIterator(asList(workers)); + } + + public InfiniteIterator seq() { + return workers; + } + } + + public Master(int nrOfWorkers, int nrOfMessages, int nrOfElements, CountDownLatch latch) { + this.nrOfWorkers = nrOfWorkers; + this.nrOfMessages = nrOfMessages; + this.nrOfElements = nrOfElements; + this.latch = latch; + + // create the workers + final ActorRef[] workers = new ActorRef[nrOfWorkers]; + for (int i = 0; i < nrOfWorkers; i++) { + workers[i] = actorOf(Worker.class).start(); + } + + // wrap them with a load-balancing router + router = actorOf(new UntypedActorFactory() { + public UntypedActor create() { + return new PiRouter(workers); + } + }).start(); + } + + // message handler + public void onReceive(Object message) { + + if (message instanceof Calculate) { + // schedule work + for (int arg = 0; arg < nrOfMessages; arg++) { + router.sendOneWay(new Work(arg, nrOfElements), getContext()); + } + + // send a PoisonPill to all workers telling them to shut down themselves + router.sendOneWay(new Broadcast(poisonPill())); + + // send a PoisonPill to the router, telling him to shut himself down + router.sendOneWay(poisonPill()); + + } else if (message instanceof Result) { + + // handle result from the worker + Result result = (Result)message; + pi += result.getValue(); + nrOfResults += 1; + if (nrOfResults == nrOfMessages) getContext().stop(); + + } else throw new IllegalArgumentException("Unknown message [" + message + "]"); + } + + @Override + public void preStart() { + start = System.currentTimeMillis(); + } + + @Override + public void postStop() { + // tell the world that the calculation is complete + System.out.println(String.format("\n\tPi estimate: \t\t%s\n\tCalculation time: \t%s millis", pi, (System.currentTimeMillis() - start))); + latch.countDown(); + } + } + + // ================== + // ===== Run it ===== + // ================== + public void calculate(final int nrOfWorkers, final int nrOfElements, final int nrOfMessages) throws Exception { + + // this latch is only plumbing to kSystem.currentTimeMillis(); when the calculation is completed + final CountDownLatch latch = new CountDownLatch(1); + + // create the master + ActorRef master = actorOf(new UntypedActorFactory() { + public UntypedActor create() { + return new Master(nrOfWorkers, nrOfMessages, nrOfElements, latch); + } + }).start(); + + // start the calculation + master.sendOneWay(new Calculate()); + + // wait for master to shut down + latch.await(); + } +} diff --git a/akka-tutorials/akka-tutorial-pi-sbt/src/main/scala/Pi.scala b/akka-tutorials/akka-tutorial-first/src/main/scala/Pi.scala similarity index 79% rename from akka-tutorials/akka-tutorial-pi-sbt/src/main/scala/Pi.scala rename to akka-tutorials/akka-tutorial-first/src/main/scala/Pi.scala index e97458a39d..5a2137e2c7 100644 --- a/akka-tutorials/akka-tutorial-pi-sbt/src/main/scala/Pi.scala +++ b/akka-tutorials/akka-tutorial-first/src/main/scala/Pi.scala @@ -2,7 +2,7 @@ * Copyright (C) 2009-2011 Scalable Solutions AB */ -package akka.tutorial.sbt.pi +package akka.tutorial.scala.first import akka.actor.{Actor, ActorRef, PoisonPill} import Actor._ @@ -14,23 +14,34 @@ import System.{currentTimeMillis => now} import java.util.concurrent.CountDownLatch /** - * Sample for Akka, SBT an Scala tutorial. + * First part in Akka tutorial. *

* Calculates Pi. *

+ * Run on command line: + *

+ *   $ cd akka-1.1
+ *   $ export AKKA_HOME=`pwd`
+ *   $ scalac -cp dist/akka-actor-1.1-SNAPSHOT.jar Pi.scala
+ *   $ java -cp dist/akka-actor-1.1-SNAPSHOT.jar:scala-library.jar:. akka.tutorial.scala.first.Pi
+ *   $ ...
+ * 
+ *

* Run it in SBT: *

  *   $ sbt
  *   > update
  *   > console
- *   > akka.tutorial.sbt.pi.Pi.calculate
+ *   > akka.tutorial.scala.first.Pi.calculate(nrOfWorkers = 4, nrOfElements = 10000, nrOfMessages = 10000)
  *   > ...
  *   > :quit
  * 
* * @author Jonas Bonér */ -object Pi { +object Pi extends App { + + calculate(nrOfWorkers = 4, nrOfElements = 10000, nrOfMessages = 10000) // ==================== // ===== Messages ===== @@ -47,7 +58,10 @@ object Pi { // define the work val calculatePiFor = (arg: Int, nrOfElements: Int) => { val range = (arg * nrOfElements) to ((arg + 1) * nrOfElements - 1) - range map (j => 4 * math.pow(-1, j) / (2 * j + 1)) sum + var acc = 0.0D + range foreach (i => acc += 4 * math.pow(-1, i) / (2 * i + 1)) + acc + //range map (j => 4 * math.pow(-1, j) / (2 * j + 1)) sum } def receive = { @@ -101,10 +115,7 @@ object Pi { // ================== // ===== Run it ===== // ================== - def calculate = { - val nrOfWorkers = 4 - val nrOfMessages = 10000 - val nrOfElements = 10000 + def calculate(nrOfWorkers: Int, nrOfElements: Int, nrOfMessages: Int) { // this latch is only plumbing to know when the calculation is completed val latch = new CountDownLatch(1) diff --git a/akka-tutorials/akka-tutorial-pi-sbt/project/build/Project.scala b/akka-tutorials/akka-tutorial-pi-sbt/project/build/Project.scala deleted file mode 100644 index 5c47e66970..0000000000 --- a/akka-tutorials/akka-tutorial-pi-sbt/project/build/Project.scala +++ /dev/null @@ -1,3 +0,0 @@ -import sbt._ - -class PiTutorialProject(info: ProjectInfo) extends DefaultProject(info) with AkkaProject diff --git a/akka-tutorials/akka-tutorial-pi-sbt/project/plugins/project/build.properties b/akka-tutorials/akka-tutorial-pi-sbt/project/plugins/project/build.properties deleted file mode 100644 index 1a423f3870..0000000000 --- a/akka-tutorials/akka-tutorial-pi-sbt/project/plugins/project/build.properties +++ /dev/null @@ -1,3 +0,0 @@ -#Project properties -#Fri Apr 01 14:48:23 CEST 2011 -plugin.uptodate=true diff --git a/akka-tutorials/akka-tutorial-second/project/build.properties b/akka-tutorials/akka-tutorial-second/project/build.properties new file mode 100644 index 0000000000..0441806bca --- /dev/null +++ b/akka-tutorials/akka-tutorial-second/project/build.properties @@ -0,0 +1,5 @@ +project.organization=se.scalablesolutions.akka +project.name=Akka Tutorial 1 SBT +project.version=1.0 +build.scala.versions=2.9.0.RC1 +sbt.version=0.7.6.RC0 diff --git a/akka-tutorials/akka-tutorial-second/project/plugins/Plugins.scala b/akka-tutorials/akka-tutorial-second/project/plugins/Plugins.scala new file mode 100644 index 0000000000..74a3d6b705 --- /dev/null +++ b/akka-tutorials/akka-tutorial-second/project/plugins/Plugins.scala @@ -0,0 +1,6 @@ +import sbt._ + +class Plugins(info: ProjectInfo) extends PluginDefinition(info) { + val akkaRepo = "Akka Repo" at "http://akka.io/repository" + val akkaPlugin = "se.scalablesolutions.akka" % "akka-sbt-plugin" % "1.1-SNAPSHOT" +} diff --git a/akka-tutorials/akka-tutorial-pi-sbt/src/main/scala/Pi2.scala b/akka-tutorials/akka-tutorial-second/src/main/scala/Pi.scala similarity index 83% rename from akka-tutorials/akka-tutorial-pi-sbt/src/main/scala/Pi2.scala rename to akka-tutorials/akka-tutorial-second/src/main/scala/Pi.scala index 7bbcba96d5..d183566b74 100644 --- a/akka-tutorials/akka-tutorial-pi-sbt/src/main/scala/Pi2.scala +++ b/akka-tutorials/akka-tutorial-second/src/main/scala/Pi.scala @@ -2,34 +2,46 @@ * Copyright (C) 2009-2011 Scalable Solutions AB */ -package akka.tutorial.sbt.pi +package akka.tutorial.second import akka.actor.Actor._ import akka.routing.{Routing, CyclicIterator} import Routing._ import akka.event.EventHandler -import System.{currentTimeMillis => now} import akka.actor.{Channel, Actor, PoisonPill} import akka.dispatch.Future +import System.{currentTimeMillis => now} + /** - * Sample for Akka, SBT an Scala tutorial. + * Second part in Akka tutorial. *

* Calculates Pi. *

+ * Run on command line: + *

+ *   $ cd akka-1.1
+ *   $ export AKKA_HOME=`pwd`
+ *   $ scalac -cp dist/akka-actor-1.1-SNAPSHOT.jar Pi.scala
+ *   $ java -cp dist/akka-actor-1.1-SNAPSHOT.jar:scala-library.jar:. akka.tutorial.second.Pi
+ *   $ ...
+ * 
+ *

* Run it in SBT: *

  *   $ sbt
  *   > update
  *   > console
- *   > akka.tutorial.sbt.pi.Pi.calculate
+ *   > akka.tutorial.second.Pi.calculate(nrOfWorkers = 4, nrOfElements = 10000, nrOfMessages = 10000)
  *   > ...
  *   > :quit
  * 
* * @author Jonas Bonér */ -object Pi2 { +object Pi extends App { + + calculate(nrOfWorkers = 4, nrOfElements = 10000, nrOfMessages = 10000) // ==================== // ===== Messages ===== @@ -46,7 +58,10 @@ object Pi2 { // define the work val calculatePiFor = (arg: Int, nrOfElements: Int) => { val range = (arg * nrOfElements) to ((arg + 1) * nrOfElements - 1) - range map (j => 4 * math.pow(-1, j) / (2 * j + 1)) sum + var acc = 0.0D + range foreach (i => acc += 4 * math.pow(-1, i) / (2 * i + 1)) + acc + //range map (j => 4 * math.pow(-1, j) / (2 * j + 1)) sum } def receive = { @@ -124,8 +139,3 @@ object Pi2 { } } } - -// To be able to run it as a main application -object Main extends App { - Pi2.calculate(nrOfWorkers = 4, nrOfElements = 10000, nrOfMessages = 10000) -} diff --git a/project/build/AkkaProject.scala b/project/build/AkkaProject.scala index 06e3651e28..712c2fbbdb 100644 --- a/project/build/AkkaProject.scala +++ b/project/build/AkkaProject.scala @@ -416,13 +416,18 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // Tutorials // ------------------------------------------------------------------------------------------------------------------- - class AkkaTutorialPiSbtProject(info: ProjectInfo) extends AkkaDefaultProject(info, deployPath) + class AkkaTutorialFirstProject(info: ProjectInfo) extends AkkaDefaultProject(info, deployPath) + + class AkkaTutorialSecondProject(info: ProjectInfo) extends AkkaDefaultProject(info, deployPath) class AkkaTutorialsParentProject(info: ProjectInfo) extends ParentProject(info) { override def disableCrossPaths = true - lazy val akka_tutorial_pi_sbt = project("akka-tutorial-pi-sbt", "akka-tutorial-pi-sbt", - new AkkaTutorialPiSbtProject(_), akka_actor) + lazy val akka_tutorial_first = project("akka-tutorial-first", "akka-tutorial-first", + new AkkaTutorialFirstProject(_), akka_actor) + + lazy val akka_tutorial_second = project("akka-tutorial-second", "akka-tutorial-second", + new AkkaTutorialSecondProject(_), akka_actor) lazy val publishRelease = { val releaseConfiguration = new DefaultPublishConfiguration(localReleaseRepository, "release", false) @@ -474,7 +479,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { def akkaArtifacts = descendents(info.projectPath / "dist", "*-" + version + ".jar") // ------------------------------------------------------------ - class AkkaDefaultProject(info: ProjectInfo, val deployPath: Path) extends DefaultProject(info) + class AkkaDefaultProject(info: ProjectInfo, val deployPath: Path) extends DefaultProject(info) with DeployProject with OSGiProject with McPom { override def disableCrossPaths = true @@ -543,12 +548,12 @@ trait McPom { self: DefaultProject => case u => u + "/" } - val oldRepos = - (node \\ "project" \ "repositories" \ "repository").map { n => + val oldRepos = + (node \\ "project" \ "repositories" \ "repository").map { n => cleanUrl((n \ "url").text) -> (n \ "name").text }.toList - val newRepos = + val newRepos = mcs.filter(_.resolver.isInstanceOf[MavenRepository]).map { m => val r = m.resolver.asInstanceOf[MavenRepository] cleanUrl(r.root) -> r.name