From abaed5e4415377b3a7f9407d8289d02d5750f901 Mon Sep 17 00:00:00 2001 From: Stefan Zeiger Date: Mon, 5 Dec 2011 12:33:24 +0100 Subject: Fix build on Windows. a289465c70630719cbd3a74edf5502a156ef83c4 broke get-scala-revision.bat. --- tools/get-scala-revision.bat | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/get-scala-revision.bat b/tools/get-scala-revision.bat index ed3ade8a3e..1b92e22dbf 100644 --- a/tools/get-scala-revision.bat +++ b/tools/get-scala-revision.bat @@ -16,7 +16,6 @@ cd %_DIR% if exist .git\NUL ( git describe head --abbrev=7 --match dev - echo 0 ) :end -- cgit v1.2.3 From 2393d7439903720e9ba5427d1351a3c158ef53e1 Mon Sep 17 00:00:00 2001 From: Stefan Zeiger Date: Mon, 5 Dec 2011 12:35:33 +0100 Subject: Fix path mangling for 'scala' shell script on MinGW/MSYS. --- .../scala/tools/ant/templates/tool-unix.tmpl | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/compiler/scala/tools/ant/templates/tool-unix.tmpl b/src/compiler/scala/tools/ant/templates/tool-unix.tmpl index 4275ef7ba1..7e51930fa4 100644 --- a/src/compiler/scala/tools/ant/templates/tool-unix.tmpl +++ b/src/compiler/scala/tools/ant/templates/tool-unix.tmpl @@ -58,12 +58,17 @@ if uname | grep -q ^CYGWIN; then cygwin="$(uname)" fi +unset mingw +if uname | grep -q ^MINGW; then + mingw="$(uname)" +fi + # Finding the root folder for this Scala distribution SCALA_HOME="$(findScalaHome)" SEP=":" # Possible additional command line options -CYGWIN_OPT="" +WINDOWS_OPT="" EMACS_OPT="" [[ -n "$EMACS" ]] && EMACS_OPT="-Denv.emacs=$EMACS" @@ -94,10 +99,16 @@ if [[ -n "$cygwin" ]]; then fi SCALA_HOME="$(cygpath --$format "$SCALA_HOME")" TOOL_CLASSPATH="$(cygpath --path --$format "$TOOL_CLASSPATH")" +elif [[ -n "$mingw" ]]; then + SCALA_HOME="$(cmd //c echo "$SCALA_HOME")" + TOOL_CLASSPATH="$(cmd //c echo "$TOOL_CLASSPATH")" +fi + +if [[ -n "$cygwin$mingw" ]]; then case "$TERM" in rxvt* | xterm*) stty -icanon min 1 -echo - CYGWIN_OPT="-Djline.terminal=scala.tools.jline.UnixTerminal" + WINDOWS_OPT="-Djline.terminal=scala.tools.jline.UnixTerminal" ;; esac fi @@ -110,9 +121,10 @@ fi declare -a java_args declare -a scala_args -# default to the boot classpath for speed, except on cygwin/mingw. +# default to the boot classpath for speed, except on cygwin/mingw because +# JLine on Windows requires a custom DLL to be loaded. unset usebootcp -if [[ -z $cygwin ]]; then +if [[ -z "$cygwin$mingw" ]]; then usebootcp="true" fi @@ -181,7 +193,7 @@ execCommand \ -Dscala.home="$SCALA_HOME" \ -Dscala.usejavacp=true \ $EMACS_OPT \ - $CYGWIN_OPT \ + $WINDOWS_OPT \ @properties@ @class@ @toolflags@ "$@@" # record the exit status lest it be overwritten: -- cgit v1.2.3 From 17e50bae3f6ba005d1c7c9edb9365312d521ec84 Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Mon, 5 Dec 2011 13:20:35 +0100 Subject: A minor fix to -Yreify-copypaste. Empty modifiers are now correctly printed out as "Modifiers()" instead of annoyingly verbose "Modifiers(Set(), newTermName(""), List())". No review. --- src/compiler/scala/tools/nsc/transform/LiftCode.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/scala/tools/nsc/transform/LiftCode.scala b/src/compiler/scala/tools/nsc/transform/LiftCode.scala index 68a53e57a1..f3f823d197 100644 --- a/src/compiler/scala/tools/nsc/transform/LiftCode.scala +++ b/src/compiler/scala/tools/nsc/transform/LiftCode.scala @@ -95,7 +95,7 @@ abstract class LiftCode extends Transform with TypingTransformers { buf.append(", " + "List(" + annotations + ")") var s = buf.toString - if (s.endsWith(", Map()")) s = s.substring(0, s.length - ", Map()".length) + if (s.endsWith(", List()")) s = s.substring(0, s.length - ", List()".length) if (s.endsWith(", newTypeName(\"\")")) s = s.substring(0, s.length - ", newTypeName(\"\")".length) if (s.endsWith("Set()")) s = s.substring(0, s.length - "Set()".length) "Modifiers(" + s + ")" -- cgit v1.2.3 From 340bb43e884319824c9f9c6234f0a17fd3b1bfe3 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Mon, 5 Dec 2011 07:12:31 -0800 Subject: Tweaks to get-scala-revision. Reference to git head is supposed to be HEAD, not head. Also apparently [[ ]] is a bashism so it's [ ]. Made name generation robust against the absence of the dev tag; it will generate a similar name even if it's not there, minus the part it can't determine without it. --- tools/get-scala-revision | 11 +++++++++-- tools/get-scala-revision.bat | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/tools/get-scala-revision b/tools/get-scala-revision index 23b216aa2b..e8597844cc 100755 --- a/tools/get-scala-revision +++ b/tools/get-scala-revision @@ -5,8 +5,15 @@ # # If no dir is given, current working dir is used. -[[ -n "$1" ]] && cd "$1" +[ -n "$1" ] && cd "$1" # dev should be a tag at the merge-base of master and the # most recent release. -git describe head --abbrev=7 --match dev +if [ -z $(git tag -l dev) ]; then + # no dev tag available - this will generate dev-g + echo "dev-g$(git describe HEAD --abbrev=7 --always)" +else + # dev tag exists - this generates dev-NNNN-g + # where NNNN is the number of commits since dev. + git describe HEAD --abbrev=7 --match dev +fi diff --git a/tools/get-scala-revision.bat b/tools/get-scala-revision.bat index ed3ade8a3e..1c2403da89 100644 --- a/tools/get-scala-revision.bat +++ b/tools/get-scala-revision.bat @@ -15,7 +15,7 @@ if "%*"=="" ( cd %_DIR% if exist .git\NUL ( - git describe head --abbrev=7 --match dev + git describe HEAD --abbrev=7 --match dev echo 0 ) -- cgit v1.2.3 From 6e9ae187a05b1ca4fe748d8a7b45440a55ceb589 Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Mon, 5 Dec 2011 17:00:55 +0100 Subject: Another test pack for reflection Also see https://github.com/scala/scala/pull/25. --- test/files/run/reify_for1.check | 0 test/files/run/reify_for1.scala | 16 ++++ test/files/run/reify_varargs.check | 1 + test/files/run/reify_varargs.scala | 17 ++++ test/pending/run/reify_addressbook.check | 30 +++++++ test/pending/run/reify_addressbook.scala | 71 ++++++++++++++++ test/pending/run/reify_brainf_ck.check | 4 + test/pending/run/reify_brainf_ck.scala | 85 ++++++++++++++++++++ test/pending/run/reify_callccinterpreter.check | 3 + test/pending/run/reify_callccinterpreter.scala | 94 ++++++++++++++++++++++ test/pending/run/reify_complex.check | 1 + test/pending/run/reify_complex.scala | 31 +++++++ test/pending/run/reify_extendbuiltins.check | 1 + test/pending/run/reify_extendbuiltins.scala | 21 +++++ test/pending/run/reify_fors.check | 5 ++ test/pending/run/reify_fors.scala | 107 +++++++++++++++++++++++++ test/pending/run/reify_gadts.check | 1 + test/pending/run/reify_gadts.scala | 45 +++++++++++ test/pending/run/reify_implicits.check | 1 + test/pending/run/reify_implicits.scala | 21 +++++ test/pending/run/reify_lazyevaluation.check | 8 ++ test/pending/run/reify_lazyevaluation.scala | 65 +++++++++++++++ test/pending/run/reify_maps.check | 4 + test/pending/run/reify_maps.scala | 26 ++++++ test/pending/run/reify_properties.check | 2 + test/pending/run/reify_properties.scala | 63 +++++++++++++++ test/pending/run/reify_simpleinterpreter.check | 2 + test/pending/run/reify_simpleinterpreter.scala | 82 +++++++++++++++++++ test/pending/run/reify_sort.check | 2 + test/pending/run/reify_sort.scala | 57 +++++++++++++ test/pending/run/reify_sort1.check | 2 + test/pending/run/reify_sort1.scala | 27 +++++++ test/pending/run/reify_timeofday.check | 1 + test/pending/run/reify_timeofday.scala | 48 +++++++++++ test/pending/run/t5229_1_nolift.scala | 1 + test/pending/run/t5271_1.check | 0 test/pending/run/t5271_1.scala | 14 ++++ test/pending/run/t5271_2.check | 1 + test/pending/run/t5271_2.scala | 16 ++++ test/pending/run/t5272.check | 1 + test/pending/run/t5272.scala | 17 ++++ test/pending/run/t5273_1.check | 1 + test/pending/run/t5273_1.scala | 16 ++++ test/pending/run/t5273_2.check | 1 + test/pending/run/t5273_2.scala | 17 ++++ test/pending/run/t5274_1.check | 3 + test/pending/run/t5274_1.scala | 20 +++++ test/pending/run/t5274_2.check | 2 + test/pending/run/t5274_2.scala | 57 +++++++++++++ test/pending/run/t5275.check | 1 + test/pending/run/t5275.scala | 15 ++++ test/pending/run/t5276.check | 1 + test/pending/run/t5276.scala | 15 ++++ test/pending/run/t5277_1.check | 1 + test/pending/run/t5277_1.scala | 21 +++++ test/pending/run/t5277_2.check | 2 + test/pending/run/t5277_2.scala | 18 +++++ test/pending/run/t5279.check | 1 + test/pending/run/t5279.scala | 14 ++++ 59 files changed, 1200 insertions(+) create mode 100644 test/files/run/reify_for1.check create mode 100644 test/files/run/reify_for1.scala create mode 100644 test/files/run/reify_varargs.check create mode 100644 test/files/run/reify_varargs.scala create mode 100644 test/pending/run/reify_addressbook.check create mode 100644 test/pending/run/reify_addressbook.scala create mode 100644 test/pending/run/reify_brainf_ck.check create mode 100644 test/pending/run/reify_brainf_ck.scala create mode 100644 test/pending/run/reify_callccinterpreter.check create mode 100644 test/pending/run/reify_callccinterpreter.scala create mode 100644 test/pending/run/reify_complex.check create mode 100644 test/pending/run/reify_complex.scala create mode 100644 test/pending/run/reify_extendbuiltins.check create mode 100644 test/pending/run/reify_extendbuiltins.scala create mode 100644 test/pending/run/reify_fors.check create mode 100644 test/pending/run/reify_fors.scala create mode 100644 test/pending/run/reify_gadts.check create mode 100644 test/pending/run/reify_gadts.scala create mode 100644 test/pending/run/reify_implicits.check create mode 100644 test/pending/run/reify_implicits.scala create mode 100644 test/pending/run/reify_lazyevaluation.check create mode 100644 test/pending/run/reify_lazyevaluation.scala create mode 100644 test/pending/run/reify_maps.check create mode 100644 test/pending/run/reify_maps.scala create mode 100644 test/pending/run/reify_properties.check create mode 100644 test/pending/run/reify_properties.scala create mode 100644 test/pending/run/reify_simpleinterpreter.check create mode 100644 test/pending/run/reify_simpleinterpreter.scala create mode 100644 test/pending/run/reify_sort.check create mode 100644 test/pending/run/reify_sort.scala create mode 100644 test/pending/run/reify_sort1.check create mode 100644 test/pending/run/reify_sort1.scala create mode 100644 test/pending/run/reify_timeofday.check create mode 100644 test/pending/run/reify_timeofday.scala create mode 100644 test/pending/run/t5229_1_nolift.scala create mode 100644 test/pending/run/t5271_1.check create mode 100644 test/pending/run/t5271_1.scala create mode 100644 test/pending/run/t5271_2.check create mode 100644 test/pending/run/t5271_2.scala create mode 100644 test/pending/run/t5272.check create mode 100644 test/pending/run/t5272.scala create mode 100644 test/pending/run/t5273_1.check create mode 100644 test/pending/run/t5273_1.scala create mode 100644 test/pending/run/t5273_2.check create mode 100644 test/pending/run/t5273_2.scala create mode 100644 test/pending/run/t5274_1.check create mode 100644 test/pending/run/t5274_1.scala create mode 100644 test/pending/run/t5274_2.check create mode 100644 test/pending/run/t5274_2.scala create mode 100644 test/pending/run/t5275.check create mode 100644 test/pending/run/t5275.scala create mode 100644 test/pending/run/t5276.check create mode 100644 test/pending/run/t5276.scala create mode 100644 test/pending/run/t5277_1.check create mode 100644 test/pending/run/t5277_1.scala create mode 100644 test/pending/run/t5277_2.check create mode 100644 test/pending/run/t5277_2.scala create mode 100644 test/pending/run/t5279.check create mode 100644 test/pending/run/t5279.scala diff --git a/test/files/run/reify_for1.check b/test/files/run/reify_for1.check new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/files/run/reify_for1.scala b/test/files/run/reify_for1.scala new file mode 100644 index 0000000000..4b03330293 --- /dev/null +++ b/test/files/run/reify_for1.scala @@ -0,0 +1,16 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + val sumOfSquares1 = (for (i <- 1 to 100; if (i % 3 == 0)) yield Math.pow(i, 2)).sum + val sumOfSquares2 = (1 to 100).filter(_ % 3 == 0).map(Math.pow(_, 2)).sum + assert(sumOfSquares1 == sumOfSquares2) + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} diff --git a/test/files/run/reify_varargs.check b/test/files/run/reify_varargs.check new file mode 100644 index 0000000000..e300a570a7 --- /dev/null +++ b/test/files/run/reify_varargs.check @@ -0,0 +1 @@ +Message=On the fifth of August there was a disturbance in the Force on planet Hoth. diff --git a/test/files/run/reify_varargs.scala b/test/files/run/reify_varargs.scala new file mode 100644 index 0000000000..d38cbf2aac --- /dev/null +++ b/test/files/run/reify_varargs.scala @@ -0,0 +1,17 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + val msg = java.text.MessageFormat.format( + "On {1} there was {2} on planet {0}.", + "Hoth", "the fifth of August", "a disturbance in the Force") + println("Message="+msg) + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} diff --git a/test/pending/run/reify_addressbook.check b/test/pending/run/reify_addressbook.check new file mode 100644 index 0000000000..4e12f87bdc --- /dev/null +++ b/test/pending/run/reify_addressbook.check @@ -0,0 +1,30 @@ + + + + My Address Book + + + + + + + + + + + + + + + + + + + +
NameAge
Tom 20
Bob 22
James 19
+ + diff --git a/test/pending/run/reify_addressbook.scala b/test/pending/run/reify_addressbook.scala new file mode 100644 index 0000000000..225f26b75e --- /dev/null +++ b/test/pending/run/reify_addressbook.scala @@ -0,0 +1,71 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + case class Person(name: String, age: Int) + + /** An AddressBook takes a variable number of arguments + * which are accessed as a Sequence + */ + class AddressBook(a: Person*) { + private val people: List[Person] = a.toList + + /** Serialize to XHTML. Scala supports XML literals + * which may contain Scala expressions between braces, + * which are replaced by their evaluation + */ + def toXHTML = + + + + + + { for (p <- people) yield + + + + + } +
NameAge
{ p.name } { p.age.toString() }
; + } + + /** We introduce CSS using raw strings (between triple + * quotes). Raw strings may contain newlines and special + * characters (like \) are not interpreted. + */ + val header = + + + { "My Address Book" } + + + ; + + val people = new AddressBook( + Person("Tom", 20), + Person("Bob", 22), + Person("James", 19)); + + val page = + + { header } + + { people.toXHTML } + + ; + + println(page) + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} diff --git a/test/pending/run/reify_brainf_ck.check b/test/pending/run/reify_brainf_ck.check new file mode 100644 index 0000000000..702bb18394 --- /dev/null +++ b/test/pending/run/reify_brainf_ck.check @@ -0,0 +1,4 @@ +---running--- +Hello World! + +---done--- diff --git a/test/pending/run/reify_brainf_ck.scala b/test/pending/run/reify_brainf_ck.scala new file mode 100644 index 0000000000..3bfb76c9ea --- /dev/null +++ b/test/pending/run/reify_brainf_ck.scala @@ -0,0 +1,85 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + import scala.annotation._ + + trait Func[T] { + val zero: T + def inc(t: T): T + def dec(t: T): T + def in: T + def out(t: T): Unit + } + + object ByteFunc extends Func[Byte] { + override val zero: Byte = 0 + override def inc(t: Byte) = ((t + 1) & 0xFF).toByte + override def dec(t: Byte) = ((t - 1) & 0xFF).toByte + override def in: Byte = readByte + override def out(t: Byte) { print(t.toChar) } + } + + case class Tape[T](left: List[T], cell: T, right: List[T])(implicit func: Func[T]) { + private def headOf(list:List[T]) = if (list.isEmpty) func.zero else list.head + private def tailOf(list:List[T]) = if (list.isEmpty) Nil else list.tail + def isZero = cell == func.zero + def execute(ch: Char) = (ch: @switch) match { + case '+' => copy(cell = func.inc(cell)) + case '-' => copy(cell = func.dec(cell)) + case '<' => Tape(tailOf(left), headOf(left), cell :: right) + case '>' => Tape(cell :: left, headOf(right), tailOf(right)) + case '.' => func.out(cell); this + case ',' => copy(cell = func.in) + case '[' | ']' => this + case _ => error("Unexpected token: " + ch) + } + } + + object Tape { + def empty[T](func: Func[T]) = Tape(Nil, func.zero, Nil)(func) + } + + class Brainfuck[T](func:Func[T]) { + + def execute(p: String) { + val prog = p.replaceAll("[^\\+\\-\\[\\]\\.\\,\\>\\<]", "") + + @tailrec def braceMatcher(pos: Int, stack: List[Int], o2c: Map[Int, Int]): Map[Int,Int] = + if(pos == prog.length) o2c else (prog(pos): @switch) match { + case '[' => braceMatcher(pos + 1, pos :: stack, o2c) + case ']' => braceMatcher(pos + 1, stack.tail, o2c + (stack.head -> pos)) + case _ => braceMatcher(pos + 1, stack, o2c) + } + + val open2close = braceMatcher(0, Nil, Map()) + val close2open = open2close.map(_.swap) + + @tailrec def ex(pos:Int, tape:Tape[T]): Unit = + if(pos < prog.length) ex((prog(pos): @switch) match { + case '[' if tape.isZero => open2close(pos) + case ']' if ! tape.isZero => close2open(pos) + case _ => pos + 1 + }, tape.execute(prog(pos))) + + println("---running---") + ex(0, Tape.empty(func)) + println("\n---done---") + } + } + + val bf = new Brainfuck(ByteFunc) + bf.execute(""">+++++++++[<++++++++>-]<.>+++++++[<++ + ++>-]<+.+++++++..+++.[-]>++++++++[<++++>-] + <.#>+++++++++++[<+++++>-]<.>++++++++[<++ + +>-]<.+++.------.--------.[-]>++++++++[<++++> + -]<+.[-]++++++++++.""") + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} diff --git a/test/pending/run/reify_callccinterpreter.check b/test/pending/run/reify_callccinterpreter.check new file mode 100644 index 0000000000..ef8fc121df --- /dev/null +++ b/test/pending/run/reify_callccinterpreter.check @@ -0,0 +1,3 @@ +42 +wrong +5 diff --git a/test/pending/run/reify_callccinterpreter.scala b/test/pending/run/reify_callccinterpreter.scala new file mode 100644 index 0000000000..c10f4f0b4e --- /dev/null +++ b/test/pending/run/reify_callccinterpreter.scala @@ -0,0 +1,94 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + type Answer = Value; + + /** + * A continuation monad. + */ + case class M[A](in: (A => Answer) => Answer) { + def bind[B](k: A => M[B]) = M[B](c => in (a => k(a) in c)) + def map[B](f: A => B): M[B] = bind(x => unitM(f(x))) + def flatMap[B](f: A => M[B]): M[B] = bind(f) + } + + def unitM[A](a: A) = M[A](c => c(a)) + + def id[A] = (x: A) => x + def showM(m: M[Value]): String = (m in id).toString() + + def callCC[A](h: (A => M[A]) => M[A]) = + M[A](c => h(a => M[A](d => c(a))) in c) + + type Name = String + + trait Term + case class Var(x: Name) extends Term + case class Con(n: Int) extends Term + case class Add(l: Term, r: Term) extends Term + case class Lam(x: Name, body: Term) extends Term + case class App(fun: Term, arg: Term) extends Term + case class Ccc(x: Name, t: Term) extends Term + + trait Value + case object Wrong extends Value { + override def toString() = "wrong" + } + case class Num(n: Int) extends Value { + override def toString() = n.toString() + } + case class Fun(f: Value => M[Value]) extends Value { + override def toString() = "" + } + + type Environment = List[Pair[Name, Value]]; + + def lookup(x: Name, e: Environment): M[Value] = e match { + case List() => unitM(Wrong) + case Pair(y, b) :: e1 => if (x == y) unitM(b) else lookup(x, e1) + } + + def add(a: Value, b: Value): M[Value] = Pair(a, b) match { + case Pair(Num(m), Num(n)) => unitM(Num(m + n)) + case _ => unitM(Wrong) + } + + def apply(a: Value, b: Value): M[Value] = a match { + case Fun(k) => k(b) + case _ => unitM(Wrong) + } + + def interp(t: Term, e: Environment): M[Value] = t match { + case Var(x) => lookup(x, e) + case Con(n) => unitM(Num(n)) + case Add(l, r) => for (a <- interp(l, e); + b <- interp(r, e); + c <- add(a, b)) + yield c + case Lam(x, t) => unitM(Fun(a => interp(t, Pair(x, a) :: e))) + case App(f, t) => for (a <- interp(f, e); + b <- interp(t, e); + c <- apply(a, b)) + yield c + case Ccc(x, t) => callCC(k => interp(t, Pair(x, Fun(k)) :: e)) + } + + def test(t: Term): String = showM(interp(t, List())) + + val term0 = App(Lam("x", Add(Var("x"), Var("x"))), Add(Con(10), Con(11))) + val term1 = App(Con(1), Con(2)) + val term2 = Add(Con(1), Ccc("k", Add(Con(2), App(Var("k"), Con(4))))) + + println(test(term0)) + println(test(term1)) + println(test(term2)) + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} diff --git a/test/pending/run/reify_complex.check b/test/pending/run/reify_complex.check new file mode 100644 index 0000000000..7df35e33a0 --- /dev/null +++ b/test/pending/run/reify_complex.check @@ -0,0 +1 @@ +3.0+4.0*i diff --git a/test/pending/run/reify_complex.scala b/test/pending/run/reify_complex.scala new file mode 100644 index 0000000000..aae4d558cf --- /dev/null +++ b/test/pending/run/reify_complex.scala @@ -0,0 +1,31 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + class Complex(val re: Double, val im: Double) { + def + (that: Complex) = + new Complex(re + that.re, im + that.im) + def - (that: Complex) = + new Complex(re - that.re, im - that.im) + def * (that: Complex) = + new Complex(re * that.re - im * that.im, + re * that.im + im * that.re) + def / (that: Complex) = { + val denom = that.re * that.re + that.im * that.im + new Complex((re * that.re + im * that.im) / denom, + (im * that.re - re * that.im) / denom) + } + override def toString = + re + (if (im < 0) "-" + (-im) else "+" + im) + "*i" + } + val x = new Complex(2, 1); val y = new Complex(1, 3) + println(x + y) + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} diff --git a/test/pending/run/reify_extendbuiltins.check b/test/pending/run/reify_extendbuiltins.check new file mode 100644 index 0000000000..a48033a30d --- /dev/null +++ b/test/pending/run/reify_extendbuiltins.check @@ -0,0 +1 @@ +10! = 3628800 diff --git a/test/pending/run/reify_extendbuiltins.scala b/test/pending/run/reify_extendbuiltins.scala new file mode 100644 index 0000000000..57acd699ff --- /dev/null +++ b/test/pending/run/reify_extendbuiltins.scala @@ -0,0 +1,21 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + def fact(n: Int): BigInt = + if (n == 0) 1 else fact(n-1) * n + class Factorizer(n: Int) { + def ! = fact(n) + } + implicit def int2fact(n: Int) = new Factorizer(n) + + println("10! = " + (10!)) + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} diff --git a/test/pending/run/reify_fors.check b/test/pending/run/reify_fors.check new file mode 100644 index 0000000000..eefddedc20 --- /dev/null +++ b/test/pending/run/reify_fors.check @@ -0,0 +1,5 @@ +Persons over 20: John Richard +divisors(34) = List(1, 2, 17, 34) +findNums(15) = (4,1) (5,2) (6,1) (7,4) (8,3) (8,5) (9,2) (9,4) (10,1) (10,3) (10,7) (11,2) (11,6) (11,8) (12,1) (12,5) (12,7) (13,4) (13,6) (13,10) (14,3) (14,5) (14,9) +average(List(3.5, 5.0, 4.5)) = 4.333333333333333 +scalProd(List(3.5, 5.0, 4.5), List(2.0, 1.0, 3.0)) = 25.5 diff --git a/test/pending/run/reify_fors.scala b/test/pending/run/reify_fors.scala new file mode 100644 index 0000000000..f3556514a9 --- /dev/null +++ b/test/pending/run/reify_fors.scala @@ -0,0 +1,107 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + object Persons { + /** A list of persons. To create a list, we use Predef.List + * which takes a variable number of arguments and constructs + * a list out of them. + */ + val persons = List( + new Person("Bob", 17), + new Person("John", 40), + new Person("Richard", 68) + ) + + /** A Person class. 'val' constructor parameters become + * public members of the class. + */ + class Person(val name: String, val age: Int) + + /** Return an iterator over persons that are older than 20. + */ + def olderThan20(xs: Seq[Person]): Iterator[String] = + olderThan20(xs.elements) + + /** Return an iterator over persons older than 20, given + * an iterator over persons. + */ + def olderThan20(xs: Iterator[Person]): Iterator[String] = { + + // The first expression is called a 'generator' and makes + // 'p' take values from 'xs'. The second expression is + // called a 'filter' and it is a boolean expression which + // selects only persons older than 20. There can be more than + // one generator and filter. The 'yield' expression is evaluated + // for each 'p' which satisfies the filters and used to assemble + // the resulting iterator + for (p <- xs if p.age > 20) yield p.name + } + } + + /** Some functions over lists of numbers which demonstrate + * the use of for comprehensions. + */ + object Numeric { + + /** Return the divisors of n. */ + def divisors(n: Int): List[Int] = + for (i <- List.range(1, n+1) if n % i == 0) yield i + + /** Is 'n' a prime number? */ + def isPrime(n: Int) = divisors(n).length == 2 + + /** Return pairs of numbers whose sum is prime. */ + def findNums(n: Int): Iterable[(Int, Int)] = { + + // a for comprehension using two generators + for (i <- 1 until n; + j <- 1 until (i-1); + if isPrime(i + j)) yield (i, j) + } + + /** Return the sum of the elements of 'xs'. */ + def sum(xs: List[Double]): Double = + xs.foldLeft(0.0) { (x, y) => x + y } + + /** Return the sum of pairwise product of the two lists. */ + def scalProd(xs: List[Double], ys: List[Double]) = + sum(for((x, y) <- xs zip ys) yield x * y); + + /** Remove duplicate elements in 'xs'. */ + def removeDuplicates[A](xs: List[A]): List[A] = + if (xs.isEmpty) + xs + else + xs.head :: removeDuplicates(for (x <- xs.tail if x != xs.head) yield x) + } + + // import all members of object 'persons' in the current scope + import Persons._ + + print("Persons over 20:") + olderThan20(persons) foreach { x => print(" " + x) } + println + + import Numeric._ + + println("divisors(34) = " + divisors(34)) + + print("findNums(15) =") + findNums(15) foreach { x => print(" " + x) } + println + + val xs = List(3.5, 5.0, 4.5) + println("average(" + xs + ") = " + sum(xs) / xs.length) + + val ys = List(2.0, 1.0, 3.0) + println("scalProd(" + xs + ", " + ys +") = " + scalProd(xs, ys)) + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} diff --git a/test/pending/run/reify_gadts.check b/test/pending/run/reify_gadts.check new file mode 100644 index 0000000000..d81cc0710e --- /dev/null +++ b/test/pending/run/reify_gadts.check @@ -0,0 +1 @@ +42 diff --git a/test/pending/run/reify_gadts.scala b/test/pending/run/reify_gadts.scala new file mode 100644 index 0000000000..7077de735c --- /dev/null +++ b/test/pending/run/reify_gadts.scala @@ -0,0 +1,45 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + /* The syntax tree of a toy language */ + abstract class Term[T] + + /* An integer literal */ + case class Lit(x: Int) extends Term[Int] + + /* Successor of a number */ + case class Succ(t: Term[Int]) extends Term[Int] + + /* Is 't' equal to zero? */ + case class IsZero(t: Term[Int]) extends Term[Boolean] + + /* An 'if' expression. */ + case class If[T](c: Term[Boolean], + t1: Term[T], + t2: Term[T]) extends Term[T] + + /** A type-safe eval function. The right-hand sides can + * make use of the fact that 'T' is a more precise type, + * constraint by the pattern type. + */ + def eval[T](t: Term[T]): T = t match { + case Lit(n) => n + + // the right hand side makes use of the fact + // that T = Int and so it can use '+' + case Succ(u) => eval(u) + 1 + case IsZero(u) => eval(u) == 0 + case If(c, u1, u2) => eval(if (eval(c)) u1 else u2) + } + println( + eval(If(IsZero(Lit(1)), Lit(41), Succ(Lit(41))))) + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} diff --git a/test/pending/run/reify_implicits.check b/test/pending/run/reify_implicits.check new file mode 100644 index 0000000000..e3aeb20f6b --- /dev/null +++ b/test/pending/run/reify_implicits.check @@ -0,0 +1 @@ +x = List(1, 2, 3, 4) diff --git a/test/pending/run/reify_implicits.scala b/test/pending/run/reify_implicits.scala new file mode 100644 index 0000000000..a15cef9c97 --- /dev/null +++ b/test/pending/run/reify_implicits.scala @@ -0,0 +1,21 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + implicit def arrayWrapper[A : ClassManifest](x: Array[A]) = + new { + def sort(p: (A, A) => Boolean) = { + util.Sorting.stableSort(x, p); x + } + } + val x = Array(2, 3, 1, 4) + println("x = "+ x.sort((x: Int, y: Int) => x < y).toList) + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} diff --git a/test/pending/run/reify_lazyevaluation.check b/test/pending/run/reify_lazyevaluation.check new file mode 100644 index 0000000000..1c7f96cd96 --- /dev/null +++ b/test/pending/run/reify_lazyevaluation.check @@ -0,0 +1,8 @@ +s = Susp(?) +evaluating... +s() = 3 +s = Susp(3) +2 + s = 5 +sl2 = Susp(?) +sl2() = Some(3) +sl2 = Susp(Some(3)) diff --git a/test/pending/run/reify_lazyevaluation.scala b/test/pending/run/reify_lazyevaluation.scala new file mode 100644 index 0000000000..f38af76751 --- /dev/null +++ b/test/pending/run/reify_lazyevaluation.scala @@ -0,0 +1,65 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + object lazyLib { + + /** Delay the evaluation of an expression until it is needed. */ + def delay[A](value: => A): Susp[A] = new SuspImpl[A](value) + + /** Get the value of a delayed expression. */ + implicit def force[A](s: Susp[A]): A = s() + + /** + * Data type of suspended computations. (The name froms from ML.) + */ + abstract class Susp[+A] extends Function0[A] + + /** + * Implementation of suspended computations, separated from the + * abstract class so that the type parameter can be invariant. + */ + class SuspImpl[A](lazyValue: => A) extends Susp[A] { + private var maybeValue: Option[A] = None + + override def apply() = maybeValue match { + case None => + val value = lazyValue + maybeValue = Some(value) + value + case Some(value) => + value + } + + override def toString() = maybeValue match { + case None => "Susp(?)" + case Some(value) => "Susp(" + value + ")" + } + } + } + + import lazyLib._ + + val s: Susp[Int] = delay { println("evaluating..."); 3 } + + println("s = " + s) // show that s is unevaluated + println("s() = " + s()) // evaluate s + println("s = " + s) // show that the value is saved + println("2 + s = " + (2 + s)) // implicit call to force() + + val sl = delay { Some(3) } + val sl1: Susp[Some[Int]] = sl + val sl2: Susp[Option[Int]] = sl1 // the type is covariant + + println("sl2 = " + sl2) + println("sl2() = " + sl2()) + println("sl2 = " + sl2) + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} diff --git a/test/pending/run/reify_maps.check b/test/pending/run/reify_maps.check new file mode 100644 index 0000000000..08cbbb1359 --- /dev/null +++ b/test/pending/run/reify_maps.check @@ -0,0 +1,4 @@ +red has code: 16711680 +Unknown color: green +Unknown color: blue +turquoise has code: 65535 diff --git a/test/pending/run/reify_maps.scala b/test/pending/run/reify_maps.scala new file mode 100644 index 0000000000..589b28d049 --- /dev/null +++ b/test/pending/run/reify_maps.scala @@ -0,0 +1,26 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + val colors = Map("red" -> 0xFF0000, + "turquoise" -> 0x00FFFF, + "black" -> 0x000000, + "orange" -> 0xFF8040, + "brown" -> 0x804000) + for (name <- List("red", "green", "blue", "turquoise")) println( + colors.get(name) match { + case Some(code) => + name + " has code: " + code + case None => + "Unknown color: " + name + } + ) + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} diff --git a/test/pending/run/reify_properties.check b/test/pending/run/reify_properties.check new file mode 100644 index 0000000000..d769bea4b0 --- /dev/null +++ b/test/pending/run/reify_properties.check @@ -0,0 +1,2 @@ +user1: MR. ROBERT +user2: MR. BOB KUZ diff --git a/test/pending/run/reify_properties.scala b/test/pending/run/reify_properties.scala new file mode 100644 index 0000000000..2115a96715 --- /dev/null +++ b/test/pending/run/reify_properties.scala @@ -0,0 +1,63 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + /** A mutable property whose getter and setter may be customized. */ + case class Property[T](init: T) { + private var value: T = init + + /** The getter function, defaults to identity. */ + private var setter: T => T = identity[T] + + /** The setter function, defaults to identity. */ + private var getter: T => T = identity[T] + + /** Retrive the value held in this property. */ + def apply(): T = getter(value) + + /** Update the value held in this property, through the setter. */ + def update(newValue: T) = value = setter(newValue) + + /** Change the getter. */ + def get(newGetter: T => T) = { getter = newGetter; this } + + /** Change the setter */ + def set(newSetter: T => T) = { setter = newSetter; this } + } + + class User { + // Create a property with custom getter and setter + val firstname = Property("") + .get { v => v.toUpperCase() } + .set { v => "Mr. " + v } + val lastname = Property("") + + /** Scala provides syntactic sugar for calling 'apply'. Simply + * adding a list of arguments between parenthesis (in this case, + * an empty list) is translated to a call to 'apply' with those + * arguments. + */ + override def toString() = firstname() + " " + lastname() + } + + val user1 = new User + + // Syntactic sugar for 'update': an assignment is translated to a + // call to method 'update' + user1.firstname() = "Robert" + + val user2 = new User + user2.firstname() = "bob" + user2.lastname() = "KUZ" + + println("user1: " + user1) + println("user2: " + user2) + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} diff --git a/test/pending/run/reify_simpleinterpreter.check b/test/pending/run/reify_simpleinterpreter.check new file mode 100644 index 0000000000..4344dc9009 --- /dev/null +++ b/test/pending/run/reify_simpleinterpreter.check @@ -0,0 +1,2 @@ +42 +wrong diff --git a/test/pending/run/reify_simpleinterpreter.scala b/test/pending/run/reify_simpleinterpreter.scala new file mode 100644 index 0000000000..b39f5583bb --- /dev/null +++ b/test/pending/run/reify_simpleinterpreter.scala @@ -0,0 +1,82 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + case class M[A](value: A) { + def bind[B](k: A => M[B]): M[B] = k(value) + def map[B](f: A => B): M[B] = bind(x => unitM(f(x))) + def flatMap[B](f: A => M[B]): M[B] = bind(f) + } + + def unitM[A](a: A): M[A] = M(a) + + def showM(m: M[Value]): String = m.value.toString(); + + type Name = String + + trait Term; + case class Var(x: Name) extends Term + case class Con(n: Int) extends Term + case class Add(l: Term, r: Term) extends Term + case class Lam(x: Name, body: Term) extends Term + case class App(fun: Term, arg: Term) extends Term + + trait Value + case object Wrong extends Value { + override def toString() = "wrong" + } + case class Num(n: Int) extends Value { + override def toString() = n.toString() + } + case class Fun(f: Value => M[Value]) extends Value { + override def toString() = "" + } + + type Environment = List[Pair[Name, Value]] + + def lookup(x: Name, e: Environment): M[Value] = e match { + case List() => unitM(Wrong) + case Pair(y, b) :: e1 => if (x == y) unitM(b) else lookup(x, e1) + } + + def add(a: Value, b: Value): M[Value] = Pair(a, b) match { + case Pair(Num(m), Num(n)) => unitM(Num(m + n)) + case _ => unitM(Wrong) + } + + def apply(a: Value, b: Value): M[Value] = a match { + case Fun(k) => k(b) + case _ => unitM(Wrong) + } + + def interp(t: Term, e: Environment): M[Value] = t match { + case Var(x) => lookup(x, e) + case Con(n) => unitM(Num(n)) + case Add(l, r) => for (a <- interp(l, e); + b <- interp(r, e); + c <- add(a, b)) + yield c + case Lam(x, t) => unitM(Fun(a => interp(t, Pair(x, a) :: e))) + case App(f, t) => for (a <- interp(f, e); + b <- interp(t, e); + c <- apply(a, b)) + yield c + } + + def test(t: Term): String = + showM(interp(t, List())) + + val term0 = App(Lam("x", Add(Var("x"), Var("x"))), Add(Con(10), Con(11))) + val term1 = App(Con(1), Con(2)) + + println(test(term0)) + println(test(term1)) + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} diff --git a/test/pending/run/reify_sort.check b/test/pending/run/reify_sort.check new file mode 100644 index 0000000000..375536cc29 --- /dev/null +++ b/test/pending/run/reify_sort.check @@ -0,0 +1,2 @@ +[6,2,8,5,1] +[1,2,5,6,8] diff --git a/test/pending/run/reify_sort.scala b/test/pending/run/reify_sort.scala new file mode 100644 index 0000000000..42991fe5d2 --- /dev/null +++ b/test/pending/run/reify_sort.scala @@ -0,0 +1,57 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + /** Nested methods can use and even update everything + * visible in their scope (including local variables or + * arguments of enclosing methods). + */ + def sort(a: Array[Int]) { + + def swap(i: Int, j: Int) { + val t = a(i); a(i) = a(j); a(j) = t + } + + def sort1(l: Int, r: Int) { + val pivot = a((l + r) / 2) + var i = l + var j = r + while (i <= j) { + while (a(i) < pivot) i += 1 + while (a(j) > pivot) j -= 1 + if (i <= j) { + swap(i, j) + i += 1 + j -= 1 + } + } + if (l < j) sort1(l, j) + if (j < r) sort1(i, r) + } + + if (a.length > 0) + sort1(0, a.length - 1) + } + + def println(ar: Array[Int]) { + def print1 = { + def iter(i: Int): String = + ar(i) + (if (i < ar.length-1) "," + iter(i+1) else "") + if (ar.length == 0) "" else iter(0) + } + Console.println("[" + print1 + "]") + } + + val ar = Array(6, 2, 8, 5, 1) + println(ar) + sort(ar) + println(ar) + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} diff --git a/test/pending/run/reify_sort1.check b/test/pending/run/reify_sort1.check new file mode 100644 index 0000000000..0d30805141 --- /dev/null +++ b/test/pending/run/reify_sort1.check @@ -0,0 +1,2 @@ +List(6, 2, 8, 5, 1) +List(1, 2, 5, 6, 8) diff --git a/test/pending/run/reify_sort1.scala b/test/pending/run/reify_sort1.scala new file mode 100644 index 0000000000..42f4c824a5 --- /dev/null +++ b/test/pending/run/reify_sort1.scala @@ -0,0 +1,27 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + def sort(a: List[Int]): List[Int] = { + if (a.length < 2) + a + else { + val pivot = a(a.length / 2) + sort(a.filter(_ < pivot)) ::: + a.filter(_ == pivot) ::: + sort(a.filter(_ > pivot)) + } + } + + val xs = List(6, 2, 8, 5, 1) + println(xs) + println(sort(xs)) + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} diff --git a/test/pending/run/reify_timeofday.check b/test/pending/run/reify_timeofday.check new file mode 100644 index 0000000000..3fd3b76a62 --- /dev/null +++ b/test/pending/run/reify_timeofday.check @@ -0,0 +1 @@ +DateError diff --git a/test/pending/run/reify_timeofday.scala b/test/pending/run/reify_timeofday.scala new file mode 100644 index 0000000000..6bd11b0d30 --- /dev/null +++ b/test/pending/run/reify_timeofday.scala @@ -0,0 +1,48 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + class DateError extends Exception + + /** Simulating properties in Scala + * (example 4.2.1 in ScalaReference.pdf) + */ + class TimeOfDayVar { + private var h, m, s: Int = 0 + + def hours = h + + /** A method 'ident_=' is a setter for 'ident'. 'code.ident = ...' will + * be translated to a call to 'ident_=' + */ + def hours_= (h: Int) = + if (0 <= h && h < 24) this.h = h + else throw new DateError() + + def minutes = m + def minutes_= (m: Int) = + if (0 <= m && m < 60) this.m = m + else throw new DateError() + + def seconds = s + def seconds_= (s: Int) = + if (0 <= s && s < 60) this.s = s + else throw new DateError() + } + + val d = new TimeOfDayVar + d.hours = 8; d.minutes = 30; d.seconds = 0 + try { d.hours = 25 // throws a DateError exception + } catch { + case de: DateError => println("DateError") + case e: Exception => println("Exception") + } + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} diff --git a/test/pending/run/t5229_1_nolift.scala b/test/pending/run/t5229_1_nolift.scala new file mode 100644 index 0000000000..33855d2e4f --- /dev/null +++ b/test/pending/run/t5229_1_nolift.scala @@ -0,0 +1 @@ +object C diff --git a/test/pending/run/t5271_1.check b/test/pending/run/t5271_1.check new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/pending/run/t5271_1.scala b/test/pending/run/t5271_1.scala new file mode 100644 index 0000000000..5f10e64528 --- /dev/null +++ b/test/pending/run/t5271_1.scala @@ -0,0 +1,14 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + case class C(foo: Int, bar: Int) + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} diff --git a/test/pending/run/t5271_2.check b/test/pending/run/t5271_2.check new file mode 100644 index 0000000000..b8626c4cff --- /dev/null +++ b/test/pending/run/t5271_2.check @@ -0,0 +1 @@ +4 diff --git a/test/pending/run/t5271_2.scala b/test/pending/run/t5271_2.scala new file mode 100644 index 0000000000..71967c04ed --- /dev/null +++ b/test/pending/run/t5271_2.scala @@ -0,0 +1,16 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + case class C(foo: Int, bar: Int) + val c = C(2, 2) + println(c.foo * c.bar) + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} diff --git a/test/pending/run/t5272.check b/test/pending/run/t5272.check new file mode 100644 index 0000000000..dcf02b2fb6 --- /dev/null +++ b/test/pending/run/t5272.check @@ -0,0 +1 @@ +okay diff --git a/test/pending/run/t5272.scala b/test/pending/run/t5272.scala new file mode 100644 index 0000000000..3f44d05fb3 --- /dev/null +++ b/test/pending/run/t5272.scala @@ -0,0 +1,17 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + 2 match { + case 2 => println("okay") + case _ => println("not okay") + } + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} diff --git a/test/pending/run/t5273_1.check b/test/pending/run/t5273_1.check new file mode 100644 index 0000000000..c551774ca5 --- /dev/null +++ b/test/pending/run/t5273_1.check @@ -0,0 +1 @@ +name = American Dollar, shortname = USD, value = 2,8567 diff --git a/test/pending/run/t5273_1.scala b/test/pending/run/t5273_1.scala new file mode 100644 index 0000000000..8b75084463 --- /dev/null +++ b/test/pending/run/t5273_1.scala @@ -0,0 +1,16 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + val RegexParser = """(.*) \d+([A-Z]+) \| (.*) \|.*""".r + val RegexParser(name, shortname, value) = "American Dollar 1USD | 2,8567 | sometext" + println("name = %s, shortname = %s, value = %s".format(name, shortname, value)) + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} diff --git a/test/pending/run/t5273_2.check b/test/pending/run/t5273_2.check new file mode 100644 index 0000000000..0cfbf08886 --- /dev/null +++ b/test/pending/run/t5273_2.check @@ -0,0 +1 @@ +2 diff --git a/test/pending/run/t5273_2.scala b/test/pending/run/t5273_2.scala new file mode 100644 index 0000000000..1175881c9f --- /dev/null +++ b/test/pending/run/t5273_2.scala @@ -0,0 +1,17 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + List(1, 2, 3) match { + case foo :: bar :: _ => println(foo * bar) + case _ => println("this is getting out of hand!") + } + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} diff --git a/test/pending/run/t5274_1.check b/test/pending/run/t5274_1.check new file mode 100644 index 0000000000..fca8bc3d3e --- /dev/null +++ b/test/pending/run/t5274_1.check @@ -0,0 +1,3 @@ +50! = 30414093201713378043612608166064768844377641568960512000000000000 +49! = 608281864034267560872252163321295376887552831379210240000000000 +50!/49! = 50 diff --git a/test/pending/run/t5274_1.scala b/test/pending/run/t5274_1.scala new file mode 100644 index 0000000000..c501172518 --- /dev/null +++ b/test/pending/run/t5274_1.scala @@ -0,0 +1,20 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + def factorial(n: BigInt): BigInt = + if (n == 0) 1 else n * factorial(n-1) + + val f50 = factorial(50); val f49 = factorial(49) + println("50! = " + f50) + println("49! = " + f49) + println("50!/49! = " + (f50 / f49)) + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} diff --git a/test/pending/run/t5274_2.check b/test/pending/run/t5274_2.check new file mode 100644 index 0000000000..375536cc29 --- /dev/null +++ b/test/pending/run/t5274_2.check @@ -0,0 +1,2 @@ +[6,2,8,5,1] +[1,2,5,6,8] diff --git a/test/pending/run/t5274_2.scala b/test/pending/run/t5274_2.scala new file mode 100644 index 0000000000..42991fe5d2 --- /dev/null +++ b/test/pending/run/t5274_2.scala @@ -0,0 +1,57 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + /** Nested methods can use and even update everything + * visible in their scope (including local variables or + * arguments of enclosing methods). + */ + def sort(a: Array[Int]) { + + def swap(i: Int, j: Int) { + val t = a(i); a(i) = a(j); a(j) = t + } + + def sort1(l: Int, r: Int) { + val pivot = a((l + r) / 2) + var i = l + var j = r + while (i <= j) { + while (a(i) < pivot) i += 1 + while (a(j) > pivot) j -= 1 + if (i <= j) { + swap(i, j) + i += 1 + j -= 1 + } + } + if (l < j) sort1(l, j) + if (j < r) sort1(i, r) + } + + if (a.length > 0) + sort1(0, a.length - 1) + } + + def println(ar: Array[Int]) { + def print1 = { + def iter(i: Int): String = + ar(i) + (if (i < ar.length-1) "," + iter(i+1) else "") + if (ar.length == 0) "" else iter(0) + } + Console.println("[" + print1 + "]") + } + + val ar = Array(6, 2, 8, 5, 1) + println(ar) + sort(ar) + println(ar) + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} diff --git a/test/pending/run/t5275.check b/test/pending/run/t5275.check new file mode 100644 index 0000000000..0cfbf08886 --- /dev/null +++ b/test/pending/run/t5275.check @@ -0,0 +1 @@ +2 diff --git a/test/pending/run/t5275.scala b/test/pending/run/t5275.scala new file mode 100644 index 0000000000..d419834ded --- /dev/null +++ b/test/pending/run/t5275.scala @@ -0,0 +1,15 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + class C(val foo: Int) + println(new C(2).foo) + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} diff --git a/test/pending/run/t5276.check b/test/pending/run/t5276.check new file mode 100644 index 0000000000..0cfbf08886 --- /dev/null +++ b/test/pending/run/t5276.check @@ -0,0 +1 @@ +2 diff --git a/test/pending/run/t5276.scala b/test/pending/run/t5276.scala new file mode 100644 index 0000000000..432fdb91e4 --- /dev/null +++ b/test/pending/run/t5276.scala @@ -0,0 +1,15 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + lazy x = 2 + println(x) + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} diff --git a/test/pending/run/t5277_1.check b/test/pending/run/t5277_1.check new file mode 100644 index 0000000000..a48033a30d --- /dev/null +++ b/test/pending/run/t5277_1.check @@ -0,0 +1 @@ +10! = 3628800 diff --git a/test/pending/run/t5277_1.scala b/test/pending/run/t5277_1.scala new file mode 100644 index 0000000000..57acd699ff --- /dev/null +++ b/test/pending/run/t5277_1.scala @@ -0,0 +1,21 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + def fact(n: Int): BigInt = + if (n == 0) 1 else fact(n-1) * n + class Factorizer(n: Int) { + def ! = fact(n) + } + implicit def int2fact(n: Int) = new Factorizer(n) + + println("10! = " + (10!)) + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} diff --git a/test/pending/run/t5277_2.check b/test/pending/run/t5277_2.check new file mode 100644 index 0000000000..5f1d0ecea5 --- /dev/null +++ b/test/pending/run/t5277_2.check @@ -0,0 +1,2 @@ +2 +1 diff --git a/test/pending/run/t5277_2.scala b/test/pending/run/t5277_2.scala new file mode 100644 index 0000000000..67b6b000bc --- /dev/null +++ b/test/pending/run/t5277_2.scala @@ -0,0 +1,18 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + def p(implicit i: Int) = print(i) + implicit val v = 2 + + println(p) + println(p(1)) + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} diff --git a/test/pending/run/t5279.check b/test/pending/run/t5279.check new file mode 100644 index 0000000000..f599e28b8a --- /dev/null +++ b/test/pending/run/t5279.check @@ -0,0 +1 @@ +10 diff --git a/test/pending/run/t5279.scala b/test/pending/run/t5279.scala new file mode 100644 index 0000000000..39e7dd2c66 --- /dev/null +++ b/test/pending/run/t5279.scala @@ -0,0 +1,14 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + println(new Integer(10)) + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} -- cgit v1.2.3 From 7a99c03da1d31ac5950eecb30f422f43c5e3d04e Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Mon, 5 Dec 2011 07:34:02 -0800 Subject: Don't generate redundant interfaces. Dropped redundant parents during bytecode generation to ease trouble on android. Closes SI-5278. --- src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala index 3fe5b83515..3fa5158a4a 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala @@ -308,6 +308,18 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with private var innerClassBuffer = mutable.LinkedHashSet[Symbol]() + /** Drop redundant interfaces (ones which are implemented by some + * other parent) from the immediate parents. This is important on + * android because there is otherwise an interface explosion. + */ + private def minimizeInterfaces(interfaces: List[Symbol]): List[Symbol] = ( + interfaces filterNot (int1 => + interfaces exists (int2 => + (int1 ne int2) && (int2 isSubClass int1) + ) + ) + ) + def genClass(c: IClass) { clasz = c innerClassBuffer.clear() @@ -322,7 +334,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with } val ifaces = superInterfaces match { case Nil => JClass.NO_INTERFACES - case _ => mkArray(superInterfaces map (x => javaName(x.typeSymbol))) + case _ => mkArray(minimizeInterfaces(superInterfaces map (_.typeSymbol)) map javaName) } jclass = fjbgContext.JClass(javaFlags(c.symbol), -- cgit v1.2.3 From 04dc2dbd0d9b3f8916b1256f9eaa0a27567eac38 Mon Sep 17 00:00:00 2001 From: Josh Marcus Date: Mon, 5 Dec 2011 12:50:58 -0500 Subject: Enhanced scaladoc of collection classes with links to the relevant pages of "The Scala 2.8 Collections API" overview. --- src/library/scala/collection/immutable/BitSet.scala | 3 +++ src/library/scala/collection/immutable/HashMap.scala | 2 ++ src/library/scala/collection/immutable/List.scala | 3 +++ src/library/scala/collection/immutable/ListMap.scala | 3 +++ src/library/scala/collection/immutable/Queue.scala | 3 +++ src/library/scala/collection/immutable/Range.scala | 3 +++ src/library/scala/collection/immutable/Stack.scala | 3 +++ src/library/scala/collection/immutable/Stream.scala | 3 +++ src/library/scala/collection/immutable/TreeMap.scala | 3 +++ src/library/scala/collection/immutable/TreeSet.scala | 3 +++ src/library/scala/collection/immutable/Vector.scala | 3 +++ src/library/scala/collection/mutable/ArrayBuffer.scala | 3 +++ src/library/scala/collection/mutable/ArraySeq.scala | 2 ++ src/library/scala/collection/mutable/ArrayStack.scala | 2 ++ src/library/scala/collection/mutable/BitSet.scala | 3 +++ src/library/scala/collection/mutable/ConcurrentMap.scala | 2 ++ src/library/scala/collection/mutable/DoubleLinkedList.scala | 3 +++ src/library/scala/collection/mutable/HashMap.scala | 2 ++ src/library/scala/collection/mutable/HashSet.scala | 2 ++ src/library/scala/collection/mutable/LinearSeq.scala | 2 ++ src/library/scala/collection/mutable/LinkedList.scala | 2 ++ src/library/scala/collection/mutable/ListBuffer.scala | 2 ++ src/library/scala/collection/mutable/MutableList.scala | 2 ++ src/library/scala/collection/mutable/Queue.scala | 2 ++ src/library/scala/collection/mutable/Stack.scala | 2 ++ src/library/scala/collection/mutable/StringBuilder.scala | 2 ++ src/library/scala/collection/mutable/WeakHashMap.scala | 3 +++ 27 files changed, 68 insertions(+) diff --git a/src/library/scala/collection/immutable/BitSet.scala b/src/library/scala/collection/immutable/BitSet.scala index ce4d688707..4e2f5e45b5 100644 --- a/src/library/scala/collection/immutable/BitSet.scala +++ b/src/library/scala/collection/immutable/BitSet.scala @@ -17,6 +17,9 @@ import mutable.{ Builder, SetBuilder } /** A class for immutable bitsets. * $bitsetinfo + * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_21.html "The Scala 2.8 Collections API"]] + * section on `Immutable BitSets` for more information. + * * @define Coll immutable.BitSet * @define coll immutable bitset */ diff --git a/src/library/scala/collection/immutable/HashMap.scala b/src/library/scala/collection/immutable/HashMap.scala index 79ee067d63..358a085e86 100644 --- a/src/library/scala/collection/immutable/HashMap.scala +++ b/src/library/scala/collection/immutable/HashMap.scala @@ -25,6 +25,8 @@ import parallel.immutable.ParHashMap * @author Tiark Rompf * @version 2.8 * @since 2.3 + * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_19.html "The Scala 2.8 Collections API"]] + * section on `Hash Tries` for more information. * @define Coll immutable.HashMap * @define coll immutable hash map * @define mayNotTerminateInf diff --git a/src/library/scala/collection/immutable/List.scala b/src/library/scala/collection/immutable/List.scala index d5e5f2aee0..b6714f9dde 100644 --- a/src/library/scala/collection/immutable/List.scala +++ b/src/library/scala/collection/immutable/List.scala @@ -57,6 +57,9 @@ import annotation.tailrec * @author Martin Odersky and others * @version 2.8 * @since 1.0 + * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_13.html "The Scala 2..8 Collections API"]] + * section on `Lists` for more information. + * * @tparam A the type of the list's elements * diff --git a/src/library/scala/collection/immutable/ListMap.scala b/src/library/scala/collection/immutable/ListMap.scala index b2b933c51a..2231da510a 100644 --- a/src/library/scala/collection/immutable/ListMap.scala +++ b/src/library/scala/collection/immutable/ListMap.scala @@ -16,6 +16,9 @@ import annotation.{tailrec, bridge} /** $factoryInfo * @since 1 + * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_22.html "The Scala 2.8 Collections API"]] + * section on `List Maps` for more information. + * * @define Coll immutable.ListMap * @define coll immutable list map */ diff --git a/src/library/scala/collection/immutable/Queue.scala b/src/library/scala/collection/immutable/Queue.scala index 6e73eef101..53ed227e51 100644 --- a/src/library/scala/collection/immutable/Queue.scala +++ b/src/library/scala/collection/immutable/Queue.scala @@ -27,6 +27,9 @@ import annotation.tailrec * @author Erik Stenman * @version 1.0, 08/07/2003 * @since 1 + * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_17.html "The Scala 2.8 Collections API"]] + * section on `Ummutable Queues` for more information. + * * @define Coll immutable.Queue * @define coll immutable queue * @define mayNotTerminateInf diff --git a/src/library/scala/collection/immutable/Range.scala b/src/library/scala/collection/immutable/Range.scala index 3736096f36..f089298350 100644 --- a/src/library/scala/collection/immutable/Range.scala +++ b/src/library/scala/collection/immutable/Range.scala @@ -31,6 +31,9 @@ import annotation.bridge * @author Paul Phillips * @version 2.8 * @since 2.5 + * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_18.html "The Scala 2.8 Collections API"]] + * section on `Ranges` for more information. + * * @define Coll Range * @define coll range * @define mayNotTerminateInf diff --git a/src/library/scala/collection/immutable/Stack.scala b/src/library/scala/collection/immutable/Stack.scala index d65300ecb7..4de0f9e8f4 100644 --- a/src/library/scala/collection/immutable/Stack.scala +++ b/src/library/scala/collection/immutable/Stack.scala @@ -34,6 +34,9 @@ object Stack extends SeqFactory[Stack] { * @author Matthias Zenger * @version 1.0, 10/07/2003 * @since 1 + * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_16.html "The Scala 2.8 Collections API"]] + * section on `Immutable stacks` for more information. + * * @define Coll immutable.Stack * @define coll immutable stack * @define orderDependent diff --git a/src/library/scala/collection/immutable/Stream.scala b/src/library/scala/collection/immutable/Stream.scala index 7bae387ad2..cb387c6316 100644 --- a/src/library/scala/collection/immutable/Stream.scala +++ b/src/library/scala/collection/immutable/Stream.scala @@ -172,6 +172,9 @@ import Stream.cons * @author Martin Odersky, Matthias Zenger * @version 1.1 08/08/03 * @since 2.8 + * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_14.html "The Scala 2.8 Collections API"]] + * section on `Streams` for more information. + * @define naturalsEx def naturalsFrom(i: Int): Stream[Int] = i #:: naturalsFrom(i + 1) * @define Coll Stream * @define coll stream diff --git a/src/library/scala/collection/immutable/TreeMap.scala b/src/library/scala/collection/immutable/TreeMap.scala index a46583c541..66f8763a8d 100644 --- a/src/library/scala/collection/immutable/TreeMap.scala +++ b/src/library/scala/collection/immutable/TreeMap.scala @@ -36,6 +36,9 @@ object TreeMap extends ImmutableSortedMapFactory[TreeMap] { * @author Matthias Zenger * @version 1.1, 03/05/2004 * @since 1 + * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_20.html "The Scala 2.8 Collections API"]] + * section on `Red-Black Trees` for more information. + * * @define Coll immutable.TreeMap * @define coll immutable tree map * @define orderDependent diff --git a/src/library/scala/collection/immutable/TreeSet.scala b/src/library/scala/collection/immutable/TreeSet.scala index 3fa1213359..966e03b984 100644 --- a/src/library/scala/collection/immutable/TreeSet.scala +++ b/src/library/scala/collection/immutable/TreeSet.scala @@ -36,6 +36,9 @@ object TreeSet extends ImmutableSortedSetFactory[TreeSet] { * @author Martin Odersky * @version 2.0, 02/01/2007 * @since 1 + * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_20.html "The Scala 2.8 Collections API"]] + * section on `Red-Black Trees` for more information. + * * @define Coll immutable.TreeSet * @define coll immutable tree set * @define orderDependent diff --git a/src/library/scala/collection/immutable/Vector.scala b/src/library/scala/collection/immutable/Vector.scala index ab12300097..03cd98d20e 100644 --- a/src/library/scala/collection/immutable/Vector.scala +++ b/src/library/scala/collection/immutable/Vector.scala @@ -35,6 +35,9 @@ object Vector extends SeqFactory[Vector] { * endian bit-mapped vector trie with a branching factor of 32. Locality is very good, but not * contiguous, which is good for very large sequences. * + * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_15.html "The Scala 2.8 Collections API"]] + * section on `Vectors` for more information. + * * @tparam A the element type * * @define Coll Vector diff --git a/src/library/scala/collection/mutable/ArrayBuffer.scala b/src/library/scala/collection/mutable/ArrayBuffer.scala index ea56eee395..503ada0153 100644 --- a/src/library/scala/collection/mutable/ArrayBuffer.scala +++ b/src/library/scala/collection/mutable/ArrayBuffer.scala @@ -23,6 +23,9 @@ import parallel.mutable.ParArray * @author Martin Odersky * @version 2.8 * @since 1 + * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_38.html "The Scala 2.8 Collections API"]] + * section on `Concrete Mutable Collection Classes` for more information. + * * @tparam A the type of this arraybuffer's elements. * diff --git a/src/library/scala/collection/mutable/ArraySeq.scala b/src/library/scala/collection/mutable/ArraySeq.scala index 414d80b462..3f7066b40f 100644 --- a/src/library/scala/collection/mutable/ArraySeq.scala +++ b/src/library/scala/collection/mutable/ArraySeq.scala @@ -21,6 +21,8 @@ import parallel.mutable.ParArray * @author Martin Odersky * @version 2.8 * @since 2.8 + * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_31.html "The Scala 2.8 Collections API"]] + * section on `Array Sequences` for more information. * * @tparam A type of the elements contained in this array sequence. * @param length the length of the underlying array. diff --git a/src/library/scala/collection/mutable/ArrayStack.scala b/src/library/scala/collection/mutable/ArrayStack.scala index c46955477b..faa22b948e 100644 --- a/src/library/scala/collection/mutable/ArrayStack.scala +++ b/src/library/scala/collection/mutable/ArrayStack.scala @@ -46,6 +46,8 @@ object ArrayStack extends SeqFactory[ArrayStack] { * * @author David MacIver * @since 2.7 + * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_33.html "The Scala 2.8 Collections API"]] + * section on `Array Stacks` for more information. * * @tparam T type of the elements contained in this array stack. * diff --git a/src/library/scala/collection/mutable/BitSet.scala b/src/library/scala/collection/mutable/BitSet.scala index 9dce3ff9e2..03228f91b1 100644 --- a/src/library/scala/collection/mutable/BitSet.scala +++ b/src/library/scala/collection/mutable/BitSet.scala @@ -18,6 +18,9 @@ import BitSetLike.{LogWL, updateArray} * * $bitsetinfo * + * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_37.html "The Scala 2.8 Collections API"]] + * section on `Mutable Bitsets` for more information. + * * @define Coll BitSet * @define coll bitset * @define thatinfo the class of the returned collection. In the standard library configuration, diff --git a/src/library/scala/collection/mutable/ConcurrentMap.scala b/src/library/scala/collection/mutable/ConcurrentMap.scala index 7e526fd4ea..be7718591b 100644 --- a/src/library/scala/collection/mutable/ConcurrentMap.scala +++ b/src/library/scala/collection/mutable/ConcurrentMap.scala @@ -14,6 +14,8 @@ package mutable * $concurrentmapinfo * * @since 2.8 + * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_36.html "The Scala 2.8 Collections API"]] + * section on `Concurrent Maps` for more information. * * @tparam A the key type of the map * @tparam B the value type of the map diff --git a/src/library/scala/collection/mutable/DoubleLinkedList.scala b/src/library/scala/collection/mutable/DoubleLinkedList.scala index dd111b3800..0934cfa081 100644 --- a/src/library/scala/collection/mutable/DoubleLinkedList.scala +++ b/src/library/scala/collection/mutable/DoubleLinkedList.scala @@ -20,6 +20,9 @@ import generic._ * @author Martin Odersky * @version 2.8 * @since 1 + * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_28.html "The Scala 2.8 Collections API"]] + * section on `Double Linked Lists` for more information. + * * @tparam A the type of the elements contained in this double linked list. * diff --git a/src/library/scala/collection/mutable/HashMap.scala b/src/library/scala/collection/mutable/HashMap.scala index c86ee39256..3c26ef0ab6 100644 --- a/src/library/scala/collection/mutable/HashMap.scala +++ b/src/library/scala/collection/mutable/HashMap.scala @@ -15,6 +15,8 @@ import scala.collection.parallel.mutable.ParHashMap /** This class implements mutable maps using a hashtable. * * @since 1 + * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_34.html "The Scala 2.8 Collections API"]] + * section on `Hash Tables` for more information. * * @tparam A the type of the keys contained in this hash map. * @tparam B the type of the values assigned to keys in this hash map. diff --git a/src/library/scala/collection/mutable/HashSet.scala b/src/library/scala/collection/mutable/HashSet.scala index 6a6964609c..7834c93ac4 100644 --- a/src/library/scala/collection/mutable/HashSet.scala +++ b/src/library/scala/collection/mutable/HashSet.scala @@ -22,6 +22,8 @@ import collection.parallel.mutable.ParHashSet * @author Martin Odersky * @version 2.0, 31/12/2006 * @since 1 + * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_34.html "The Scala 2.8 Collections API"]] + * section on `Hash Tables` for more information. * * @define Coll mutable.HashSet * @define coll mutable hash set diff --git a/src/library/scala/collection/mutable/LinearSeq.scala b/src/library/scala/collection/mutable/LinearSeq.scala index e29d6bf3e6..9f7443da0e 100644 --- a/src/library/scala/collection/mutable/LinearSeq.scala +++ b/src/library/scala/collection/mutable/LinearSeq.scala @@ -19,6 +19,8 @@ import generic._ * * @define Coll LinearSeq * @define coll linear sequence + * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_29.html "The Scala 2.8 Collections API"]] + * section on `Mutable Lists` for more information. */ trait LinearSeq[A] extends Seq[A] with scala.collection.LinearSeq[A] diff --git a/src/library/scala/collection/mutable/LinkedList.scala b/src/library/scala/collection/mutable/LinkedList.scala index 65391f5884..6311a01b65 100644 --- a/src/library/scala/collection/mutable/LinkedList.scala +++ b/src/library/scala/collection/mutable/LinkedList.scala @@ -33,6 +33,8 @@ import generic._ * @author Martin Odersky * @version 2.8 * @since 1 + * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_27.html "The Scala 2.8 Collections API"]] + * section on `Linked Lists` for more information. * * @tparam A the type of the elements contained in this linked list. * diff --git a/src/library/scala/collection/mutable/ListBuffer.scala b/src/library/scala/collection/mutable/ListBuffer.scala index 233544c4ca..812b4010b4 100644 --- a/src/library/scala/collection/mutable/ListBuffer.scala +++ b/src/library/scala/collection/mutable/ListBuffer.scala @@ -21,6 +21,8 @@ import immutable.{List, Nil, ::} * @author Martin Odersky * @version 2.8 * @since 1 + * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_25.html "The Scala 2.8 Collections API"]] + * section on `List Buffers` for more information. * * @tparam A the type of this list buffer's elements. * diff --git a/src/library/scala/collection/mutable/MutableList.scala b/src/library/scala/collection/mutable/MutableList.scala index 20910e48f4..de7f82095e 100644 --- a/src/library/scala/collection/mutable/MutableList.scala +++ b/src/library/scala/collection/mutable/MutableList.scala @@ -23,6 +23,8 @@ import immutable.{List, Nil} * @author Martin Odersky * @version 2.8 * @since 1 + * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_29.html "The Scala 2.8 Collections API"]] + * section on `Mutable Lists` for more information. */ @SerialVersionUID(5938451523372603072L) class MutableList[A] diff --git a/src/library/scala/collection/mutable/Queue.scala b/src/library/scala/collection/mutable/Queue.scala index e1723241f5..875ad12363 100644 --- a/src/library/scala/collection/mutable/Queue.scala +++ b/src/library/scala/collection/mutable/Queue.scala @@ -20,6 +20,8 @@ import generic._ * @author Martin Odersky * @version 2.8 * @since 1 + * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_30.html "The Scala 2.8 Collections API"]] + * section on `Queues` for more information. * * @define Coll mutable.Queue * @define coll mutable queue diff --git a/src/library/scala/collection/mutable/Stack.scala b/src/library/scala/collection/mutable/Stack.scala index c795609b67..0b4578dcc9 100644 --- a/src/library/scala/collection/mutable/Stack.scala +++ b/src/library/scala/collection/mutable/Stack.scala @@ -44,6 +44,8 @@ object Stack extends SeqFactory[Stack] { * @author Martin Odersky * @version 2.8 * @since 1 + * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_32.html "The Scala 2.8 Collections API"]] + * section on `Array Sequences` for more information. * @define Coll Stack * @define coll stack * @define orderDependent diff --git a/src/library/scala/collection/mutable/StringBuilder.scala b/src/library/scala/collection/mutable/StringBuilder.scala index 6fb4b839ef..27c1404e3e 100644 --- a/src/library/scala/collection/mutable/StringBuilder.scala +++ b/src/library/scala/collection/mutable/StringBuilder.scala @@ -21,6 +21,8 @@ import immutable.StringLike * @author Martin Odersky * @version 2.8 * @since 2.7 + * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_26.html "The Scala 2.8 Collections API"]] + * section on `StringBuilders` for more information. */ @SerialVersionUID(0 - 8525408645367278351L) final class StringBuilder(private val underlying: JavaStringBuilder) diff --git a/src/library/scala/collection/mutable/WeakHashMap.scala b/src/library/scala/collection/mutable/WeakHashMap.scala index be2daa05ce..188cca2917 100644 --- a/src/library/scala/collection/mutable/WeakHashMap.scala +++ b/src/library/scala/collection/mutable/WeakHashMap.scala @@ -23,6 +23,9 @@ import generic._ * @tparam B type of values associated with the keys * * @since 2.8 + * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_34.html "The Scala 2.8 Collections API"]] + * section on `Hash Tables` for more information. + * * @define Coll WeakHashMap * @define coll weak hash map * @define thatinfo the class of the returned collection. In the standard library configuration, -- cgit v1.2.3 From 09ba583b1e08b96d9b1d703a1c0c6bdaa55ae7f7 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Mon, 5 Dec 2011 10:05:01 -0800 Subject: Disabled non-deterministic tests. Everyone's favorite "will they or won't they" tests, akka and timeofday. They will be welcomed back into the fold once they can stick to a decision on whether to pass or fail. --- test/disabled/presentation/akka.check | 492 +++++++ test/disabled/presentation/akka.flags | 18 + test/disabled/presentation/akka/Runner.scala | 3 + .../presentation/akka/src/akka/AkkaException.scala | 40 + .../presentation/akka/src/akka/actor/Actor.scala | 503 +++++++ .../akka/src/akka/actor/ActorRef.scala | 1433 ++++++++++++++++++++ .../akka/src/akka/actor/ActorRegistry.scala | 389 ++++++ .../presentation/akka/src/akka/actor/Actors.java | 108 ++ .../akka/actor/BootableActorLoaderService.scala | 60 + .../presentation/akka/src/akka/actor/FSM.scala | 527 +++++++ .../akka/src/akka/actor/Scheduler.scala | 133 ++ .../akka/src/akka/actor/Supervisor.scala | 176 +++ .../akka/src/akka/actor/UntypedActor.scala | 134 ++ .../presentation/akka/src/akka/actor/package.scala | 23 + .../presentation/akka/src/akka/config/Config.scala | 93 ++ .../akka/src/akka/config/ConfigParser.scala | 74 + .../akka/src/akka/config/Configuration.scala | 166 +++ .../akka/src/akka/config/Configurator.scala | 21 + .../akka/src/akka/config/Importer.scala | 64 + .../akka/src/akka/config/SupervisionConfig.scala | 134 ++ .../akka/src/akka/dataflow/DataFlow.scala | 165 +++ .../akka/src/akka/dispatch/Dispatchers.scala | 227 ++++ .../ExecutorBasedEventDrivenDispatcher.scala | 305 +++++ ...torBasedEventDrivenWorkStealingDispatcher.scala | 165 +++ .../akka/src/akka/dispatch/Future.scala | 832 ++++++++++++ .../akka/src/akka/dispatch/MailboxHandling.scala | 68 + .../akka/src/akka/dispatch/MessageHandling.scala | 260 ++++ .../src/akka/dispatch/ThreadBasedDispatcher.scala | 52 + .../akka/src/akka/dispatch/ThreadPoolBuilder.scala | 259 ++++ .../akka/src/akka/event/EventHandler.scala | 235 ++++ .../akka/src/akka/event/JavaEventHandler.java | 35 + .../presentation/akka/src/akka/japi/JavaAPI.scala | 108 ++ .../akka/remoteinterface/RemoteEventHandler.scala | 43 + .../src/akka/remoteinterface/RemoteInterface.scala | 493 +++++++ .../akka/src/akka/routing/Iterators.scala | 49 + .../akka/src/akka/routing/Listeners.scala | 37 + .../presentation/akka/src/akka/routing/Pool.scala | 292 ++++ .../akka/src/akka/routing/Routers.scala | 87 ++ .../akka/src/akka/routing/Routing.scala | 64 + .../presentation/akka/src/akka/util/Address.scala | 29 + .../akka/src/akka/util/AkkaLoader.scala | 94 ++ .../presentation/akka/src/akka/util/Bootable.scala | 10 + .../akka/src/akka/util/BoundedBlockingQueue.scala | 326 +++++ .../presentation/akka/src/akka/util/Crypt.scala | 44 + .../presentation/akka/src/akka/util/Duration.scala | 437 ++++++ .../presentation/akka/src/akka/util/HashCode.scala | 57 + .../presentation/akka/src/akka/util/Helpers.scala | 99 ++ .../akka/src/akka/util/ListenerManagement.scala | 81 ++ .../presentation/akka/src/akka/util/LockUtil.scala | 197 +++ .../akka/src/akka/util/ReflectiveAccess.scala | 232 ++++ .../presentation/akka/src/akka/util/package.scala | 27 + .../akka/src/com/eaio/util/lang/Hex.java | 215 +++ .../akka/src/com/eaio/uuid/MACAddressParser.java | 116 ++ .../presentation/akka/src/com/eaio/uuid/UUID.java | 311 +++++ .../akka/src/com/eaio/uuid/UUIDGen.java | 364 +++++ .../akka/src/com/eaio/uuid/UUIDHelper.java | 86 ++ .../akka/src/com/eaio/uuid/UUIDHolder.java | 42 + test/disabled/presentation/akka/src/pi.scala | 108 ++ test/disabled/presentation/timeofday.check | 100 ++ test/disabled/presentation/timeofday/Runner.scala | 3 + .../presentation/timeofday/src/timeofday.scala | 35 + test/files/presentation/akka.check | 492 ------- test/files/presentation/akka.flags | 18 - test/files/presentation/akka/Runner.scala | 3 - .../presentation/akka/src/akka/AkkaException.scala | 40 - .../presentation/akka/src/akka/actor/Actor.scala | 503 ------- .../akka/src/akka/actor/ActorRef.scala | 1433 -------------------- .../akka/src/akka/actor/ActorRegistry.scala | 389 ------ .../presentation/akka/src/akka/actor/Actors.java | 108 -- .../akka/actor/BootableActorLoaderService.scala | 60 - .../presentation/akka/src/akka/actor/FSM.scala | 527 ------- .../akka/src/akka/actor/Scheduler.scala | 133 -- .../akka/src/akka/actor/Supervisor.scala | 176 --- .../akka/src/akka/actor/UntypedActor.scala | 134 -- .../presentation/akka/src/akka/actor/package.scala | 23 - .../presentation/akka/src/akka/config/Config.scala | 93 -- .../akka/src/akka/config/ConfigParser.scala | 74 - .../akka/src/akka/config/Configuration.scala | 166 --- .../akka/src/akka/config/Configurator.scala | 21 - .../akka/src/akka/config/Importer.scala | 64 - .../akka/src/akka/config/SupervisionConfig.scala | 134 -- .../akka/src/akka/dataflow/DataFlow.scala | 165 --- .../akka/src/akka/dispatch/Dispatchers.scala | 227 ---- .../ExecutorBasedEventDrivenDispatcher.scala | 305 ----- ...torBasedEventDrivenWorkStealingDispatcher.scala | 165 --- .../akka/src/akka/dispatch/Future.scala | 832 ------------ .../akka/src/akka/dispatch/MailboxHandling.scala | 68 - .../akka/src/akka/dispatch/MessageHandling.scala | 260 ---- .../src/akka/dispatch/ThreadBasedDispatcher.scala | 52 - .../akka/src/akka/dispatch/ThreadPoolBuilder.scala | 259 ---- .../akka/src/akka/event/EventHandler.scala | 235 ---- .../akka/src/akka/event/JavaEventHandler.java | 35 - .../presentation/akka/src/akka/japi/JavaAPI.scala | 108 -- .../akka/remoteinterface/RemoteEventHandler.scala | 43 - .../src/akka/remoteinterface/RemoteInterface.scala | 493 ------- .../akka/src/akka/routing/Iterators.scala | 49 - .../akka/src/akka/routing/Listeners.scala | 37 - .../presentation/akka/src/akka/routing/Pool.scala | 292 ---- .../akka/src/akka/routing/Routers.scala | 87 -- .../akka/src/akka/routing/Routing.scala | 64 - .../presentation/akka/src/akka/util/Address.scala | 29 - .../akka/src/akka/util/AkkaLoader.scala | 94 -- .../presentation/akka/src/akka/util/Bootable.scala | 10 - .../akka/src/akka/util/BoundedBlockingQueue.scala | 326 ----- .../presentation/akka/src/akka/util/Crypt.scala | 44 - .../presentation/akka/src/akka/util/Duration.scala | 437 ------ .../presentation/akka/src/akka/util/HashCode.scala | 57 - .../presentation/akka/src/akka/util/Helpers.scala | 99 -- .../akka/src/akka/util/ListenerManagement.scala | 81 -- .../presentation/akka/src/akka/util/LockUtil.scala | 197 --- .../akka/src/akka/util/ReflectiveAccess.scala | 232 ---- .../presentation/akka/src/akka/util/package.scala | 27 - .../akka/src/com/eaio/util/lang/Hex.java | 215 --- .../akka/src/com/eaio/uuid/MACAddressParser.java | 116 -- .../presentation/akka/src/com/eaio/uuid/UUID.java | 311 ----- .../akka/src/com/eaio/uuid/UUIDGen.java | 364 ----- .../akka/src/com/eaio/uuid/UUIDHelper.java | 86 -- .../akka/src/com/eaio/uuid/UUIDHolder.java | 42 - test/files/presentation/akka/src/pi.scala | 108 -- test/files/presentation/timeofday.check | 100 -- test/files/presentation/timeofday/Runner.scala | 3 - .../presentation/timeofday/src/timeofday.scala | 35 - 122 files changed, 11380 insertions(+), 11380 deletions(-) create mode 100644 test/disabled/presentation/akka.check create mode 100644 test/disabled/presentation/akka.flags create mode 100644 test/disabled/presentation/akka/Runner.scala create mode 100644 test/disabled/presentation/akka/src/akka/AkkaException.scala create mode 100644 test/disabled/presentation/akka/src/akka/actor/Actor.scala create mode 100644 test/disabled/presentation/akka/src/akka/actor/ActorRef.scala create mode 100644 test/disabled/presentation/akka/src/akka/actor/ActorRegistry.scala create mode 100644 test/disabled/presentation/akka/src/akka/actor/Actors.java create mode 100644 test/disabled/presentation/akka/src/akka/actor/BootableActorLoaderService.scala create mode 100644 test/disabled/presentation/akka/src/akka/actor/FSM.scala create mode 100644 test/disabled/presentation/akka/src/akka/actor/Scheduler.scala create mode 100644 test/disabled/presentation/akka/src/akka/actor/Supervisor.scala create mode 100644 test/disabled/presentation/akka/src/akka/actor/UntypedActor.scala create mode 100644 test/disabled/presentation/akka/src/akka/actor/package.scala create mode 100644 test/disabled/presentation/akka/src/akka/config/Config.scala create mode 100644 test/disabled/presentation/akka/src/akka/config/ConfigParser.scala create mode 100644 test/disabled/presentation/akka/src/akka/config/Configuration.scala create mode 100644 test/disabled/presentation/akka/src/akka/config/Configurator.scala create mode 100644 test/disabled/presentation/akka/src/akka/config/Importer.scala create mode 100644 test/disabled/presentation/akka/src/akka/config/SupervisionConfig.scala create mode 100644 test/disabled/presentation/akka/src/akka/dataflow/DataFlow.scala create mode 100644 test/disabled/presentation/akka/src/akka/dispatch/Dispatchers.scala create mode 100644 test/disabled/presentation/akka/src/akka/dispatch/ExecutorBasedEventDrivenDispatcher.scala create mode 100644 test/disabled/presentation/akka/src/akka/dispatch/ExecutorBasedEventDrivenWorkStealingDispatcher.scala create mode 100644 test/disabled/presentation/akka/src/akka/dispatch/Future.scala create mode 100644 test/disabled/presentation/akka/src/akka/dispatch/MailboxHandling.scala create mode 100644 test/disabled/presentation/akka/src/akka/dispatch/MessageHandling.scala create mode 100644 test/disabled/presentation/akka/src/akka/dispatch/ThreadBasedDispatcher.scala create mode 100644 test/disabled/presentation/akka/src/akka/dispatch/ThreadPoolBuilder.scala create mode 100644 test/disabled/presentation/akka/src/akka/event/EventHandler.scala create mode 100644 test/disabled/presentation/akka/src/akka/event/JavaEventHandler.java create mode 100644 test/disabled/presentation/akka/src/akka/japi/JavaAPI.scala create mode 100644 test/disabled/presentation/akka/src/akka/remoteinterface/RemoteEventHandler.scala create mode 100644 test/disabled/presentation/akka/src/akka/remoteinterface/RemoteInterface.scala create mode 100644 test/disabled/presentation/akka/src/akka/routing/Iterators.scala create mode 100644 test/disabled/presentation/akka/src/akka/routing/Listeners.scala create mode 100644 test/disabled/presentation/akka/src/akka/routing/Pool.scala create mode 100644 test/disabled/presentation/akka/src/akka/routing/Routers.scala create mode 100644 test/disabled/presentation/akka/src/akka/routing/Routing.scala create mode 100644 test/disabled/presentation/akka/src/akka/util/Address.scala create mode 100644 test/disabled/presentation/akka/src/akka/util/AkkaLoader.scala create mode 100644 test/disabled/presentation/akka/src/akka/util/Bootable.scala create mode 100644 test/disabled/presentation/akka/src/akka/util/BoundedBlockingQueue.scala create mode 100644 test/disabled/presentation/akka/src/akka/util/Crypt.scala create mode 100644 test/disabled/presentation/akka/src/akka/util/Duration.scala create mode 100644 test/disabled/presentation/akka/src/akka/util/HashCode.scala create mode 100644 test/disabled/presentation/akka/src/akka/util/Helpers.scala create mode 100644 test/disabled/presentation/akka/src/akka/util/ListenerManagement.scala create mode 100644 test/disabled/presentation/akka/src/akka/util/LockUtil.scala create mode 100644 test/disabled/presentation/akka/src/akka/util/ReflectiveAccess.scala create mode 100644 test/disabled/presentation/akka/src/akka/util/package.scala create mode 100644 test/disabled/presentation/akka/src/com/eaio/util/lang/Hex.java create mode 100644 test/disabled/presentation/akka/src/com/eaio/uuid/MACAddressParser.java create mode 100644 test/disabled/presentation/akka/src/com/eaio/uuid/UUID.java create mode 100644 test/disabled/presentation/akka/src/com/eaio/uuid/UUIDGen.java create mode 100644 test/disabled/presentation/akka/src/com/eaio/uuid/UUIDHelper.java create mode 100644 test/disabled/presentation/akka/src/com/eaio/uuid/UUIDHolder.java create mode 100644 test/disabled/presentation/akka/src/pi.scala create mode 100644 test/disabled/presentation/timeofday.check create mode 100644 test/disabled/presentation/timeofday/Runner.scala create mode 100644 test/disabled/presentation/timeofday/src/timeofday.scala delete mode 100644 test/files/presentation/akka.check delete mode 100644 test/files/presentation/akka.flags delete mode 100644 test/files/presentation/akka/Runner.scala delete mode 100644 test/files/presentation/akka/src/akka/AkkaException.scala delete mode 100644 test/files/presentation/akka/src/akka/actor/Actor.scala delete mode 100644 test/files/presentation/akka/src/akka/actor/ActorRef.scala delete mode 100644 test/files/presentation/akka/src/akka/actor/ActorRegistry.scala delete mode 100644 test/files/presentation/akka/src/akka/actor/Actors.java delete mode 100644 test/files/presentation/akka/src/akka/actor/BootableActorLoaderService.scala delete mode 100644 test/files/presentation/akka/src/akka/actor/FSM.scala delete mode 100644 test/files/presentation/akka/src/akka/actor/Scheduler.scala delete mode 100644 test/files/presentation/akka/src/akka/actor/Supervisor.scala delete mode 100644 test/files/presentation/akka/src/akka/actor/UntypedActor.scala delete mode 100644 test/files/presentation/akka/src/akka/actor/package.scala delete mode 100644 test/files/presentation/akka/src/akka/config/Config.scala delete mode 100644 test/files/presentation/akka/src/akka/config/ConfigParser.scala delete mode 100644 test/files/presentation/akka/src/akka/config/Configuration.scala delete mode 100644 test/files/presentation/akka/src/akka/config/Configurator.scala delete mode 100644 test/files/presentation/akka/src/akka/config/Importer.scala delete mode 100644 test/files/presentation/akka/src/akka/config/SupervisionConfig.scala delete mode 100644 test/files/presentation/akka/src/akka/dataflow/DataFlow.scala delete mode 100644 test/files/presentation/akka/src/akka/dispatch/Dispatchers.scala delete mode 100644 test/files/presentation/akka/src/akka/dispatch/ExecutorBasedEventDrivenDispatcher.scala delete mode 100644 test/files/presentation/akka/src/akka/dispatch/ExecutorBasedEventDrivenWorkStealingDispatcher.scala delete mode 100644 test/files/presentation/akka/src/akka/dispatch/Future.scala delete mode 100644 test/files/presentation/akka/src/akka/dispatch/MailboxHandling.scala delete mode 100644 test/files/presentation/akka/src/akka/dispatch/MessageHandling.scala delete mode 100644 test/files/presentation/akka/src/akka/dispatch/ThreadBasedDispatcher.scala delete mode 100644 test/files/presentation/akka/src/akka/dispatch/ThreadPoolBuilder.scala delete mode 100644 test/files/presentation/akka/src/akka/event/EventHandler.scala delete mode 100644 test/files/presentation/akka/src/akka/event/JavaEventHandler.java delete mode 100644 test/files/presentation/akka/src/akka/japi/JavaAPI.scala delete mode 100644 test/files/presentation/akka/src/akka/remoteinterface/RemoteEventHandler.scala delete mode 100644 test/files/presentation/akka/src/akka/remoteinterface/RemoteInterface.scala delete mode 100644 test/files/presentation/akka/src/akka/routing/Iterators.scala delete mode 100644 test/files/presentation/akka/src/akka/routing/Listeners.scala delete mode 100644 test/files/presentation/akka/src/akka/routing/Pool.scala delete mode 100644 test/files/presentation/akka/src/akka/routing/Routers.scala delete mode 100644 test/files/presentation/akka/src/akka/routing/Routing.scala delete mode 100644 test/files/presentation/akka/src/akka/util/Address.scala delete mode 100644 test/files/presentation/akka/src/akka/util/AkkaLoader.scala delete mode 100644 test/files/presentation/akka/src/akka/util/Bootable.scala delete mode 100644 test/files/presentation/akka/src/akka/util/BoundedBlockingQueue.scala delete mode 100644 test/files/presentation/akka/src/akka/util/Crypt.scala delete mode 100644 test/files/presentation/akka/src/akka/util/Duration.scala delete mode 100644 test/files/presentation/akka/src/akka/util/HashCode.scala delete mode 100644 test/files/presentation/akka/src/akka/util/Helpers.scala delete mode 100644 test/files/presentation/akka/src/akka/util/ListenerManagement.scala delete mode 100644 test/files/presentation/akka/src/akka/util/LockUtil.scala delete mode 100644 test/files/presentation/akka/src/akka/util/ReflectiveAccess.scala delete mode 100644 test/files/presentation/akka/src/akka/util/package.scala delete mode 100644 test/files/presentation/akka/src/com/eaio/util/lang/Hex.java delete mode 100644 test/files/presentation/akka/src/com/eaio/uuid/MACAddressParser.java delete mode 100644 test/files/presentation/akka/src/com/eaio/uuid/UUID.java delete mode 100644 test/files/presentation/akka/src/com/eaio/uuid/UUIDGen.java delete mode 100644 test/files/presentation/akka/src/com/eaio/uuid/UUIDHelper.java delete mode 100644 test/files/presentation/akka/src/com/eaio/uuid/UUIDHolder.java delete mode 100644 test/files/presentation/akka/src/pi.scala delete mode 100644 test/files/presentation/timeofday.check delete mode 100644 test/files/presentation/timeofday/Runner.scala delete mode 100644 test/files/presentation/timeofday/src/timeofday.scala diff --git a/test/disabled/presentation/akka.check b/test/disabled/presentation/akka.check new file mode 100644 index 0000000000..9cd20ffb1c --- /dev/null +++ b/test/disabled/presentation/akka.check @@ -0,0 +1,492 @@ +reload: Actor.scala, ActorRef.scala, ActorRegistry.scala, Actors.java, Address.scala, AkkaException.scala, AkkaLoader.scala, Bootable.scala, BootableActorLoaderService.scala, BoundedBlockingQueue.scala, Config.scala, ConfigParser.scala, Configuration.scala, Configurator.scala, Crypt.scala, DataFlow.scala, Dispatchers.scala, Duration.scala, EventHandler.scala, ExecutorBasedEventDrivenDispatcher.scala, ExecutorBasedEventDrivenWorkStealingDispatcher.scala, FSM.scala, Future.scala, HashCode.scala, Helpers.scala, Hex.java, Importer.scala, Iterators.scala, JavaAPI.scala, JavaEventHandler.java, ListenerManagement.scala, Listeners.scala, LockUtil.scala, MACAddressParser.java, MailboxHandling.scala, MessageHandling.scala, Pool.scala, ReflectiveAccess.scala, RemoteEventHandler.scala, RemoteInterface.scala, Routers.scala, Routing.scala, Scheduler.scala, SupervisionConfig.scala, Supervisor.scala, ThreadBasedDispatcher.scala, ThreadPoolBuilder.scala, UUID.java, UUIDGen.java, UUIDHelper.java, UUIDHolder.java, UntypedActor.scala, package.scala, package.scala, pi.scala + +askTypeCompletion at pi.scala(52,59) +================================================================================ +[response] aksTypeCompletion at (52,59) +retrieved 0 members + +================================================================================ + +askTypeCompletion at pi.scala(55,25) +================================================================================ +[response] aksTypeCompletion at (55,25) +retrieved 45 members +`class Broadcastakka.routing.Routing.Broadcast` +`method !=(x$1: Any)Boolean` +`method !=(x$1: AnyRef)Boolean` +`method ##()Int` +`method +(other: String)String` +`method ->[B](y: B)(akka.routing.Routing.type, B)` +`method ==(x$1: Any)Boolean` +`method ==(x$1: AnyRef)Boolean` +`method asInstanceOf[T0]=> T0` +`method clone()Object` +`method dispatcherActor(routing: akka.routing.Routing.PF[Any,akka.actor.ActorRef])akka.actor.ActorRef` +`method dispatcherActor(routing: akka.routing.Routing.PF[Any,akka.actor.ActorRef], msgTransformer: Any => Any)akka.actor.ActorRef` +`method ensuring(cond: Boolean)akka.routing.Routing.type` +`method ensuring(cond: Boolean, msg: => Any)akka.routing.Routing.type` +`method ensuring(cond: akka.routing.Routing.type => Boolean)akka.routing.Routing.type` +`method ensuring(cond: akka.routing.Routing.type => Boolean, msg: => Any)akka.routing.Routing.type` +`method eq(x$1: AnyRef)Boolean` +`method equals(x$1: Any)Boolean` +`method filter[A, B](filter: akka.routing.Routing.PF[A,Unit], filtered: akka.routing.Routing.PF[A,B])akka.routing.Routing.PF[A,B]` +`method finalize()Unit` +`method formatted(fmtstr: String)String` +`method hashCode()Int` +`method intercept[A, B](interceptor: A => Unit, interceptee: akka.routing.Routing.PF[A,B])akka.routing.Routing.PF[A,B]` +`method isInstanceOf[T0]=> Boolean` +`method loadBalancerActor(actors: => akka.routing.InfiniteIterator[akka.actor.ActorRef])akka.actor.ActorRef` +`method loggerActor(actorToLog: akka.actor.ActorRef, logger: Any => Unit)akka.actor.ActorRef` +`method ne(x$1: AnyRef)Boolean` +`method notify()Unit` +`method notifyAll()Unit` +`method synchronized[T0](x$1: T0)T0` +`method toString()String` +`method wait()Unit` +`method wait(x$1: Long)Unit` +`method wait(x$1: Long, x$2: Int)Unit` +`method x=> akka.routing.Routing.type` +`method →[B](y: B)(akka.routing.Routing.type, B)` +`trait RoutingMessageakka.routing.Routing.RoutingMessage` +`type PFakka.routing.Routing.PF` +`value __leftOfArrowakka.routing.Routing.type` +`value __resultOfEnsuringakka.routing.Routing.type` +`value selfAny` +================================================================================ + +askTypeCompletion at pi.scala(55,73) +================================================================================ +[response] aksTypeCompletion at (55,73) +retrieved 131 members +`method !!![T](message: Any, timeout: Long)(implicit sender: Option[akka.actor.ActorRef])akka.dispatch.Future[T]` +`method !!(message: Any, timeout: Long)(implicit sender: Option[akka.actor.ActorRef])Option[Any]` +`method !(message: Any)(implicit sender: Option[akka.actor.ActorRef])Unit` +`method !=(x$1: Any)Boolean` +`method !=(x$1: AnyRef)Boolean` +`method ##()Int` +`method +(other: String)String` +`method ->[B](y: B)(akka.actor.ActorRef, B)` +`method ==(x$1: Any)Boolean` +`method ==(x$1: AnyRef)Boolean` +`method actor=> akka.actor.Actor` +`method actorClass=> Class[_ <: akka.actor.Actor]` +`method actorClassName=> String` +`method actorInstance=> java.util.concurrent.atomic.AtomicReference[akka.actor.Actor]` +`method asInstanceOf[T0]=> T0` +`method channel=> akka.actor.Channel[Any]` +`method clone()Object` +`method compareTo(other: akka.actor.ActorRef)Int` +`method dispatcher=> akka.dispatch.MessageDispatcher` +`method dispatcher_=(md: akka.dispatch.MessageDispatcher)Unit` +`method ensuring(cond: Boolean)akka.actor.ActorRef` +`method ensuring(cond: Boolean, msg: => Any)akka.actor.ActorRef` +`method ensuring(cond: akka.actor.ActorRef => Boolean)akka.actor.ActorRef` +`method ensuring(cond: akka.actor.ActorRef => Boolean, msg: => Any)akka.actor.ActorRef` +`method eq(x$1: AnyRef)Boolean` +`method equals(that: Any)Boolean` +`method exit()Unit` +`method finalize()Unit` +`method formatted(fmtstr: String)String` +`method forward(message: Any)(implicit sender: Some[akka.actor.ActorRef])Any` +`method forward(message: AnyRef, sender: akka.actor.ActorRef)Unit` +`method getActorClass()Class[_ <: akka.actor.Actor]` +`method getActorClassName()String` +`method getChannel=> akka.actor.Channel[Any]` +`method getDispatcher()akka.dispatch.MessageDispatcher` +`method getFaultHandler()akka.config.Supervision.FaultHandlingStrategy` +`method getHomeAddress()java.net.InetSocketAddress` +`method getId()String` +`method getLifeCycle()akka.config.Supervision.LifeCycle` +`method getLinkedActors()java.util.Map[akka.actor.Uuid,akka.actor.ActorRef]` +`method getMailboxSize()Int` +`method getReceiveTimeout()Option[Long]` +`method getSender()Option[akka.actor.ActorRef]` +`method getSenderFuture()Option[akka.dispatch.CompletableFuture[Any]]` +`method getSupervisor()akka.actor.ActorRef` +`method getTimeout()Long` +`method getUuid()akka.actor.Uuid` +`method handleTrapExit(dead: akka.actor.ActorRef, reason: Throwable)Unit` +`method hashCode()Int` +`method homeAddress=> Option[java.net.InetSocketAddress]` +`method id=> String` +`method id_=(id: String)Unit` +`method invoke(messageHandle: akka.dispatch.MessageInvocation)Unit` +`method isBeingRestarted=> Boolean` +`method isDefinedAt(message: Any)Boolean` +`method isInstanceOf[T0]=> Boolean` +`method isRunning=> Boolean` +`method isShutdown=> Boolean` +`method isUnstarted=> Boolean` +`method link(actorRef: akka.actor.ActorRef)Unit` +`method linkedActors=> java.util.Map[akka.actor.Uuid,akka.actor.ActorRef]` +`method mailbox=> AnyRef` +`method mailboxSize=> Int` +`method mailbox_=(value: AnyRef)AnyRef` +`method ne(x$1: AnyRef)Boolean` +`method notify()Unit` +`method notifyAll()Unit` +`method postMessageToMailbox(message: Any, senderOption: Option[akka.actor.ActorRef])Unit` +`method postMessageToMailboxAndCreateFutureResultWithTimeout[T](message: Any, timeout: Long, senderOption: Option[akka.actor.ActorRef], senderFuture: Option[akka.dispatch.CompletableFuture[T]])akka.dispatch.CompletableFuture[T]` +`method registerSupervisorAsRemoteActor=> Option[akka.actor.Uuid]` +`method reply(message: Any)Unit` +`method replySafe(message: AnyRef)Boolean` +`method replyUnsafe(message: AnyRef)Unit` +`method reply_?(message: Any)Boolean` +`method restart(reason: Throwable, maxNrOfRetries: Option[Int], withinTimeRange: Option[Int])Unit` +`method restartLinkedActors(reason: Throwable, maxNrOfRetries: Option[Int], withinTimeRange: Option[Int])Unit` +`method sendOneWay(message: AnyRef)Unit` +`method sendOneWay(message: AnyRef, sender: akka.actor.ActorRef)Unit` +`method sendRequestReply(message: AnyRef)AnyRef` +`method sendRequestReply(message: AnyRef, sender: akka.actor.ActorRef)AnyRef` +`method sendRequestReply(message: AnyRef, timeout: Long, sender: akka.actor.ActorRef)AnyRef` +`method sendRequestReplyFuture[T <: AnyRef](message: AnyRef)akka.dispatch.Future[T]` +`method sendRequestReplyFuture[T <: AnyRef](message: AnyRef, sender: akka.actor.ActorRef)akka.dispatch.Future[T]` +`method sendRequestReplyFuture[T <: AnyRef](message: AnyRef, timeout: Long, sender: akka.actor.ActorRef)akka.dispatch.Future[T]` +`method sender=> Option[akka.actor.ActorRef]` +`method senderFuture()Option[akka.dispatch.CompletableFuture[Any]]` +`method setDispatcher(dispatcher: akka.dispatch.MessageDispatcher)Unit` +`method setFaultHandler(handler: akka.config.Supervision.FaultHandlingStrategy)Unit` +`method setId(x$1: String)Unit` +`method setLifeCycle(lifeCycle: akka.config.Supervision.LifeCycle)Unit` +`method setReceiveTimeout(timeout: Long)Unit` +`method setTimeout(x$1: Long)Unit` +`method spawn(clazz: Class[_ <: akka.actor.Actor])akka.actor.ActorRef` +`method spawnLink(clazz: Class[_ <: akka.actor.Actor])akka.actor.ActorRef` +`method spawnLinkRemote(clazz: Class[_ <: akka.actor.Actor], hostname: String, port: Int, timeout: Long)akka.actor.ActorRef` +`method spawnLinkRemote[T <: akka.actor.Actor](hostname: String, port: Int, timeout: Long)(implicit evidence$4: Manifest[T])akka.actor.ActorRef` +`method spawnLink[T <: akka.actor.Actor](implicit evidence$3: Manifest[T])akka.actor.ActorRef` +`method spawnRemote(clazz: Class[_ <: akka.actor.Actor], hostname: String, port: Int, timeout: Long)akka.actor.ActorRef` +`method spawnRemote[T <: akka.actor.Actor](hostname: String, port: Int, timeout: Long)(implicit evidence$2: Manifest[T])akka.actor.ActorRef` +`method spawn[T <: akka.actor.Actor](implicit evidence$1: Manifest[T])akka.actor.ActorRef` +`method start()akka.actor.ActorRef` +`method startLink(actorRef: akka.actor.ActorRef)Unit` +`method stop()Unit` +`method supervisor=> Option[akka.actor.ActorRef]` +`method supervisor_=(sup: Option[akka.actor.ActorRef])Unit` +`method synchronized[T0](x$1: T0)T0` +`method toString()String` +`method unlink(actorRef: akka.actor.ActorRef)Unit` +`method uuid=> akka.actor.Uuid` +`method uuid_=(uid: akka.actor.Uuid)Unit` +`method wait()Unit` +`method wait(x$1: Long)Unit` +`method wait(x$1: Long, x$2: Int)Unit` +`method x=> akka.actor.ActorRef` +`method →[B](y: B)(akka.actor.ActorRef, B)` +`value __leftOfArrowakka.actor.ActorRef` +`value __resultOfEnsuringakka.actor.ActorRef` +`value selfAny` +`variable _statusakka.actor.ActorRefInternals.StatusType` +`variable _uuidakka.actor.Uuid` +`variable currentMessageakka.dispatch.MessageInvocation` +`variable faultHandlerakka.config.Supervision.FaultHandlingStrategy` +`variable hotswapscala.collection.immutable.Stack[PartialFunction[Any,Unit]]` +`variable idString` +`variable lifeCycleakka.config.Supervision.LifeCycle` +`variable receiveTimeoutOption[Long]` +`variable timeoutLong` +================================================================================ + +askTypeCompletion at pi.scala(65,15) +================================================================================ +[response] aksTypeCompletion at (65,15) +retrieved 131 members +`method !!![T](message: Any, timeout: Long)(implicit sender: Option[akka.actor.ActorRef])akka.dispatch.Future[T]` +`method !!(message: Any, timeout: Long)(implicit sender: Option[akka.actor.ActorRef])Option[Any]` +`method !(message: Any)(implicit sender: Option[akka.actor.ActorRef])Unit` +`method !=(x$1: Any)Boolean` +`method !=(x$1: AnyRef)Boolean` +`method ##()Int` +`method +(other: String)String` +`method ->[B](y: B)(akka.actor.ActorRef, B)` +`method ==(x$1: Any)Boolean` +`method ==(x$1: AnyRef)Boolean` +`method actor=> akka.actor.Actor` +`method actorClass=> Class[_ <: akka.actor.Actor]` +`method actorClassName=> String` +`method actorInstance=> java.util.concurrent.atomic.AtomicReference[akka.actor.Actor]` +`method asInstanceOf[T0]=> T0` +`method channel=> akka.actor.Channel[Any]` +`method clone()Object` +`method compareTo(other: akka.actor.ActorRef)Int` +`method dispatcher=> akka.dispatch.MessageDispatcher` +`method dispatcher_=(md: akka.dispatch.MessageDispatcher)Unit` +`method ensuring(cond: Boolean)akka.actor.ActorRef` +`method ensuring(cond: Boolean, msg: => Any)akka.actor.ActorRef` +`method ensuring(cond: akka.actor.ActorRef => Boolean)akka.actor.ActorRef` +`method ensuring(cond: akka.actor.ActorRef => Boolean, msg: => Any)akka.actor.ActorRef` +`method eq(x$1: AnyRef)Boolean` +`method equals(that: Any)Boolean` +`method exit()Unit` +`method finalize()Unit` +`method formatted(fmtstr: String)String` +`method forward(message: Any)(implicit sender: Some[akka.actor.ActorRef])Any` +`method forward(message: AnyRef, sender: akka.actor.ActorRef)Unit` +`method getActorClass()Class[_ <: akka.actor.Actor]` +`method getActorClassName()String` +`method getChannel=> akka.actor.Channel[Any]` +`method getDispatcher()akka.dispatch.MessageDispatcher` +`method getFaultHandler()akka.config.Supervision.FaultHandlingStrategy` +`method getHomeAddress()java.net.InetSocketAddress` +`method getId()String` +`method getLifeCycle()akka.config.Supervision.LifeCycle` +`method getLinkedActors()java.util.Map[akka.actor.Uuid,akka.actor.ActorRef]` +`method getMailboxSize()Int` +`method getReceiveTimeout()Option[Long]` +`method getSender()Option[akka.actor.ActorRef]` +`method getSenderFuture()Option[akka.dispatch.CompletableFuture[Any]]` +`method getSupervisor()akka.actor.ActorRef` +`method getTimeout()Long` +`method getUuid()akka.actor.Uuid` +`method handleTrapExit(dead: akka.actor.ActorRef, reason: Throwable)Unit` +`method hashCode()Int` +`method homeAddress=> Option[java.net.InetSocketAddress]` +`method id=> String` +`method id_=(id: String)Unit` +`method invoke(messageHandle: akka.dispatch.MessageInvocation)Unit` +`method isBeingRestarted=> Boolean` +`method isDefinedAt(message: Any)Boolean` +`method isInstanceOf[T0]=> Boolean` +`method isRunning=> Boolean` +`method isShutdown=> Boolean` +`method isUnstarted=> Boolean` +`method link(actorRef: akka.actor.ActorRef)Unit` +`method linkedActors=> java.util.Map[akka.actor.Uuid,akka.actor.ActorRef]` +`method mailbox=> AnyRef` +`method mailboxSize=> Int` +`method mailbox_=(value: AnyRef)AnyRef` +`method ne(x$1: AnyRef)Boolean` +`method notify()Unit` +`method notifyAll()Unit` +`method postMessageToMailbox(message: Any, senderOption: Option[akka.actor.ActorRef])Unit` +`method postMessageToMailboxAndCreateFutureResultWithTimeout[T](message: Any, timeout: Long, senderOption: Option[akka.actor.ActorRef], senderFuture: Option[akka.dispatch.CompletableFuture[T]])akka.dispatch.CompletableFuture[T]` +`method registerSupervisorAsRemoteActor=> Option[akka.actor.Uuid]` +`method reply(message: Any)Unit` +`method replySafe(message: AnyRef)Boolean` +`method replyUnsafe(message: AnyRef)Unit` +`method reply_?(message: Any)Boolean` +`method restart(reason: Throwable, maxNrOfRetries: Option[Int], withinTimeRange: Option[Int])Unit` +`method restartLinkedActors(reason: Throwable, maxNrOfRetries: Option[Int], withinTimeRange: Option[Int])Unit` +`method sendOneWay(message: AnyRef)Unit` +`method sendOneWay(message: AnyRef, sender: akka.actor.ActorRef)Unit` +`method sendRequestReply(message: AnyRef)AnyRef` +`method sendRequestReply(message: AnyRef, sender: akka.actor.ActorRef)AnyRef` +`method sendRequestReply(message: AnyRef, timeout: Long, sender: akka.actor.ActorRef)AnyRef` +`method sendRequestReplyFuture[T <: AnyRef](message: AnyRef)akka.dispatch.Future[T]` +`method sendRequestReplyFuture[T <: AnyRef](message: AnyRef, sender: akka.actor.ActorRef)akka.dispatch.Future[T]` +`method sendRequestReplyFuture[T <: AnyRef](message: AnyRef, timeout: Long, sender: akka.actor.ActorRef)akka.dispatch.Future[T]` +`method sender=> Option[akka.actor.ActorRef]` +`method senderFuture()Option[akka.dispatch.CompletableFuture[Any]]` +`method setDispatcher(dispatcher: akka.dispatch.MessageDispatcher)Unit` +`method setFaultHandler(handler: akka.config.Supervision.FaultHandlingStrategy)Unit` +`method setId(x$1: String)Unit` +`method setLifeCycle(lifeCycle: akka.config.Supervision.LifeCycle)Unit` +`method setReceiveTimeout(timeout: Long)Unit` +`method setTimeout(x$1: Long)Unit` +`method spawn(clazz: Class[_ <: akka.actor.Actor])akka.actor.ActorRef` +`method spawnLink(clazz: Class[_ <: akka.actor.Actor])akka.actor.ActorRef` +`method spawnLinkRemote(clazz: Class[_ <: akka.actor.Actor], hostname: String, port: Int, timeout: Long)akka.actor.ActorRef` +`method spawnLinkRemote[T <: akka.actor.Actor](hostname: String, port: Int, timeout: Long)(implicit evidence$4: Manifest[T])akka.actor.ActorRef` +`method spawnLink[T <: akka.actor.Actor](implicit evidence$3: Manifest[T])akka.actor.ActorRef` +`method spawnRemote(clazz: Class[_ <: akka.actor.Actor], hostname: String, port: Int, timeout: Long)akka.actor.ActorRef` +`method spawnRemote[T <: akka.actor.Actor](hostname: String, port: Int, timeout: Long)(implicit evidence$2: Manifest[T])akka.actor.ActorRef` +`method spawn[T <: akka.actor.Actor](implicit evidence$1: Manifest[T])akka.actor.ActorRef` +`method start()akka.actor.ActorRef` +`method startLink(actorRef: akka.actor.ActorRef)Unit` +`method stop()Unit` +`method supervisor=> Option[akka.actor.ActorRef]` +`method supervisor_=(sup: Option[akka.actor.ActorRef])Unit` +`method synchronized[T0](x$1: T0)T0` +`method toString()String` +`method unlink(actorRef: akka.actor.ActorRef)Unit` +`method uuid=> akka.actor.Uuid` +`method uuid_=(uid: akka.actor.Uuid)Unit` +`method wait()Unit` +`method wait(x$1: Long)Unit` +`method wait(x$1: Long, x$2: Int)Unit` +`method x=> akka.actor.ActorRef` +`method →[B](y: B)(akka.actor.ActorRef, B)` +`value __leftOfArrowakka.actor.ActorRef` +`value __resultOfEnsuringakka.actor.ActorRef` +`value selfAny` +`variable _statusakka.actor.ActorRefInternals.StatusType` +`variable _uuidakka.actor.Uuid` +`variable currentMessageakka.dispatch.MessageInvocation` +`variable faultHandlerakka.config.Supervision.FaultHandlingStrategy` +`variable hotswapscala.collection.immutable.Stack[PartialFunction[Any,Unit]]` +`variable idString` +`variable lifeCycleakka.config.Supervision.LifeCycle` +`variable receiveTimeoutOption[Long]` +`variable timeoutLong` +================================================================================ + +askTypeCompletion at pi.scala(74,46) +================================================================================ +[response] aksTypeCompletion at (74,46) +retrieved 131 members +`method !!![T](message: Any, timeout: Long)(implicit sender: Option[akka.actor.ActorRef])akka.dispatch.Future[T]` +`method !!(message: Any, timeout: Long)(implicit sender: Option[akka.actor.ActorRef])Option[Any]` +`method !(message: Any)(implicit sender: Option[akka.actor.ActorRef])Unit` +`method !=(x$1: Any)Boolean` +`method !=(x$1: AnyRef)Boolean` +`method ##()Int` +`method +(other: String)String` +`method ->[B](y: B)(akka.actor.ScalaActorRef, B)` +`method ==(x$1: Any)Boolean` +`method ==(x$1: AnyRef)Boolean` +`method actor=> akka.actor.Actor` +`method actorClass=> Class[_ <: akka.actor.Actor]` +`method actorClassName=> String` +`method actorInstance=> java.util.concurrent.atomic.AtomicReference[akka.actor.Actor]` +`method asInstanceOf[T0]=> T0` +`method channel=> akka.actor.Channel[Any]` +`method clone()Object` +`method compareTo(other: akka.actor.ActorRef)Int` +`method dispatcher=> akka.dispatch.MessageDispatcher` +`method dispatcher_=(md: akka.dispatch.MessageDispatcher)Unit` +`method ensuring(cond: Boolean)akka.actor.ScalaActorRef` +`method ensuring(cond: Boolean, msg: => Any)akka.actor.ScalaActorRef` +`method ensuring(cond: akka.actor.ScalaActorRef => Boolean)akka.actor.ScalaActorRef` +`method ensuring(cond: akka.actor.ScalaActorRef => Boolean, msg: => Any)akka.actor.ScalaActorRef` +`method eq(x$1: AnyRef)Boolean` +`method equals(x$1: Any)Boolean` +`method exit()Unit` +`method finalize()Unit` +`method formatted(fmtstr: String)String` +`method forward(message: Any)(implicit sender: Some[akka.actor.ActorRef])Any` +`method forward(message: AnyRef, sender: akka.actor.ActorRef)Unit` +`method getActorClass()Class[_ <: akka.actor.Actor]` +`method getActorClassName()String` +`method getChannel=> akka.actor.Channel[Any]` +`method getDispatcher()akka.dispatch.MessageDispatcher` +`method getFaultHandler()akka.config.Supervision.FaultHandlingStrategy` +`method getHomeAddress()java.net.InetSocketAddress` +`method getId()String` +`method getLifeCycle()akka.config.Supervision.LifeCycle` +`method getLinkedActors()java.util.Map[akka.actor.Uuid,akka.actor.ActorRef]` +`method getMailboxSize()Int` +`method getReceiveTimeout()Option[Long]` +`method getSender()Option[akka.actor.ActorRef]` +`method getSenderFuture()Option[akka.dispatch.CompletableFuture[Any]]` +`method getSupervisor()akka.actor.ActorRef` +`method getTimeout()Long` +`method getUuid()akka.actor.Uuid` +`method handleTrapExit(dead: akka.actor.ActorRef, reason: Throwable)Unit` +`method hashCode()Int` +`method homeAddress=> Option[java.net.InetSocketAddress]` +`method id=> String` +`method id_=(id: String)Unit` +`method invoke(messageHandle: akka.dispatch.MessageInvocation)Unit` +`method isBeingRestarted=> Boolean` +`method isDefinedAt(message: Any)Boolean` +`method isInstanceOf[T0]=> Boolean` +`method isRunning=> Boolean` +`method isShutdown=> Boolean` +`method isUnstarted=> Boolean` +`method link(actorRef: akka.actor.ActorRef)Unit` +`method linkedActors=> java.util.Map[akka.actor.Uuid,akka.actor.ActorRef]` +`method mailbox=> AnyRef` +`method mailboxSize=> Int` +`method mailbox_=(value: AnyRef)AnyRef` +`method ne(x$1: AnyRef)Boolean` +`method notify()Unit` +`method notifyAll()Unit` +`method postMessageToMailbox(message: Any, senderOption: Option[akka.actor.ActorRef])Unit` +`method postMessageToMailboxAndCreateFutureResultWithTimeout[T](message: Any, timeout: Long, senderOption: Option[akka.actor.ActorRef], senderFuture: Option[akka.dispatch.CompletableFuture[T]])akka.dispatch.CompletableFuture[T]` +`method registerSupervisorAsRemoteActor=> Option[akka.actor.Uuid]` +`method reply(message: Any)Unit` +`method replySafe(message: AnyRef)Boolean` +`method replyUnsafe(message: AnyRef)Unit` +`method reply_?(message: Any)Boolean` +`method restart(reason: Throwable, maxNrOfRetries: Option[Int], withinTimeRange: Option[Int])Unit` +`method restartLinkedActors(reason: Throwable, maxNrOfRetries: Option[Int], withinTimeRange: Option[Int])Unit` +`method sendOneWay(message: AnyRef)Unit` +`method sendOneWay(message: AnyRef, sender: akka.actor.ActorRef)Unit` +`method sendRequestReply(message: AnyRef)AnyRef` +`method sendRequestReply(message: AnyRef, sender: akka.actor.ActorRef)AnyRef` +`method sendRequestReply(message: AnyRef, timeout: Long, sender: akka.actor.ActorRef)AnyRef` +`method sendRequestReplyFuture[T <: AnyRef](message: AnyRef)akka.dispatch.Future[T]` +`method sendRequestReplyFuture[T <: AnyRef](message: AnyRef, sender: akka.actor.ActorRef)akka.dispatch.Future[T]` +`method sendRequestReplyFuture[T <: AnyRef](message: AnyRef, timeout: Long, sender: akka.actor.ActorRef)akka.dispatch.Future[T]` +`method sender=> Option[akka.actor.ActorRef]` +`method senderFuture()Option[akka.dispatch.CompletableFuture[Any]]` +`method setDispatcher(dispatcher: akka.dispatch.MessageDispatcher)Unit` +`method setFaultHandler(x$1: akka.config.Supervision.FaultHandlingStrategy)Unit` +`method setId(x$1: String)Unit` +`method setLifeCycle(x$1: akka.config.Supervision.LifeCycle)Unit` +`method setReceiveTimeout(timeout: Long)Unit` +`method setTimeout(x$1: Long)Unit` +`method spawn(clazz: Class[_ <: akka.actor.Actor])akka.actor.ActorRef` +`method spawnLink(clazz: Class[_ <: akka.actor.Actor])akka.actor.ActorRef` +`method spawnLinkRemote(clazz: Class[_ <: akka.actor.Actor], hostname: String, port: Int, timeout: Long)akka.actor.ActorRef` +`method spawnLinkRemote[T <: akka.actor.Actor](hostname: String, port: Int, timeout: Long)(implicit evidence$4: Manifest[T])akka.actor.ActorRef` +`method spawnLink[T <: akka.actor.Actor](implicit evidence$3: Manifest[T])akka.actor.ActorRef` +`method spawnRemote(clazz: Class[_ <: akka.actor.Actor], hostname: String, port: Int, timeout: Long)akka.actor.ActorRef` +`method spawnRemote[T <: akka.actor.Actor](hostname: String, port: Int, timeout: Long)(implicit evidence$2: Manifest[T])akka.actor.ActorRef` +`method spawn[T <: akka.actor.Actor](implicit evidence$1: Manifest[T])akka.actor.ActorRef` +`method start()akka.actor.ActorRef` +`method startLink(actorRef: akka.actor.ActorRef)Unit` +`method stop()Unit` +`method supervisor=> Option[akka.actor.ActorRef]` +`method supervisor_=(sup: Option[akka.actor.ActorRef])Unit` +`method synchronized[T0](x$1: T0)T0` +`method toString()String` +`method unlink(actorRef: akka.actor.ActorRef)Unit` +`method uuid=> akka.actor.Uuid` +`method uuid_=(uid: akka.actor.Uuid)Unit` +`method wait()Unit` +`method wait(x$1: Long)Unit` +`method wait(x$1: Long, x$2: Int)Unit` +`method x=> akka.actor.ScalaActorRef` +`method →[B](y: B)(akka.actor.ScalaActorRef, B)` +`value __leftOfArrowakka.actor.ScalaActorRef` +`value __resultOfEnsuringakka.actor.ScalaActorRef` +`value selfAny` +`variable _statusakka.actor.ActorRefInternals.StatusType` +`variable _uuidakka.actor.Uuid` +`variable currentMessageakka.dispatch.MessageInvocation` +`variable faultHandlerakka.config.Supervision.FaultHandlingStrategy` +`variable hotswapscala.collection.immutable.Stack[PartialFunction[Any,Unit]]` +`variable idString` +`variable lifeCycleakka.config.Supervision.LifeCycle` +`variable receiveTimeoutOption[Long]` +`variable timeoutLong` +================================================================================ + +askType at pi.scala(34,16) +================================================================================ +[response] askTypeAt at (34,16) +def receive: PartialFunction[Any,Unit] = ((x0$3: Any) => x0$3 match { + case (start: Int, nrOfElements: Int)Pi.Work((start @ _), (nrOfElements @ _)) => Worker.this.self.reply(Pi.this.Result.apply(Worker.this.calculatePiFor(start, nrOfElements))) +}) +================================================================================ + +askHyperlinkPos for `calculate` at (11,11) pi.scala +================================================================================ +[response] found askHyperlinkPos for `calculate` at (93,7) pi.scala +================================================================================ + +askHyperlinkPos for `PiMessage` at (17,41) pi.scala +================================================================================ +[response] found askHyperlinkPos for `PiMessage` at (16,16) pi.scala +================================================================================ + +askHyperlinkPos for `Actor` at (24,28) pi.scala +================================================================================ +[response] found askHyperlinkPos for `Actor` at (289,7) Actor.scala +================================================================================ + +askHyperlinkPos for `reply` at (36,18) pi.scala +================================================================================ +[response] found askHyperlinkPos for `reply` at (1382,7) ActorRef.scala +================================================================================ + +askHyperlinkPos for `nrOfResults` at (73,19) pi.scala +================================================================================ +[response] found askHyperlinkPos for `nrOfResults` at (48,9) pi.scala +================================================================================ + +askHyperlinkPos for `latch` at (86,11) pi.scala +================================================================================ +[response] found askHyperlinkPos for `latch` at (44,61) pi.scala +================================================================================ diff --git a/test/disabled/presentation/akka.flags b/test/disabled/presentation/akka.flags new file mode 100644 index 0000000000..56d026a62d --- /dev/null +++ b/test/disabled/presentation/akka.flags @@ -0,0 +1,18 @@ +# This file contains command line options that are passed to the presentation compiler +# Lines starting with # are stripped, and you can split arguments on several lines. + +# The -bootclasspath option is treated specially by the test framework: if it's not specified +# in this file, the presentation compiler will pick up the scala-library/compiler that's on the +# java classpath used to run this test (usually build/pack) + +# Any option can be passed this way, like presentation debug +# -Ypresentation-debug -Ypresentation-verbose + +# the classpath is relative to the current working directory. That means it depends where you're +# running partest from. Run it from the root scala checkout for these files to resolve correctly +# (by default when running 'ant test', or 'test/partest'). Paths use Unix separators, the test +# framework translates them to the platform dependent representation. +# -bootclasspath lib/scala-compiler.jar:lib/scala-library.jar:lib/fjbg.jar + +# the following line would test using the quick compiler +# -bootclasspath build/quick/classes/compiler:build/quick/classes/library:lib/fjbg.jar diff --git a/test/disabled/presentation/akka/Runner.scala b/test/disabled/presentation/akka/Runner.scala new file mode 100644 index 0000000000..14a6aa8350 --- /dev/null +++ b/test/disabled/presentation/akka/Runner.scala @@ -0,0 +1,3 @@ +import scala.tools.nsc.interactive.tests.InteractiveTest + +object Test extends InteractiveTest diff --git a/test/disabled/presentation/akka/src/akka/AkkaException.scala b/test/disabled/presentation/akka/src/akka/AkkaException.scala new file mode 100644 index 0000000000..155a7a16b5 --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/AkkaException.scala @@ -0,0 +1,40 @@ +/** + * Copyright (C) 2009-2011 Scalable Solutions AB + */ + +package akka + +import akka.actor.newUuid +import java.net.{ InetAddress, UnknownHostException } + +/** + * Akka base Exception. Each Exception gets: + *
    + *
  • a uuid for tracking purposes
  • + *
  • toString that includes exception name, message, uuid, and the stacktrace
  • + *
+ * + * @author Jonas Bonér + */ +class AkkaException(message: String = "", cause: Throwable = null) extends RuntimeException(message, cause) with Serializable { + val uuid = "%s_%s".format(AkkaException.hostname, newUuid) + + override lazy val toString = + "%s: %s\n[%s]\n%s".format(getClass.getName, message, uuid, stackTraceToString) + + def stackTraceToString = { + val trace = getStackTrace + val sb = new StringBuffer + for (i ← 0 until trace.length) + sb.append("\tat %s\n" format trace(i)) + sb.toString + } +} + +object AkkaException { + val hostname = try { + InetAddress.getLocalHost.getHostName + } catch { + case e: UnknownHostException => "unknown" + } +} diff --git a/test/disabled/presentation/akka/src/akka/actor/Actor.scala b/test/disabled/presentation/akka/src/akka/actor/Actor.scala new file mode 100644 index 0000000000..b955c4c38b --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/actor/Actor.scala @@ -0,0 +1,503 @@ +/** Copyright (C) 2009-2011 Scalable Solutions AB + */ + +package akka.actor + +import akka.dispatch._ +import akka.config.Config._ +import akka.util.Helpers.{ narrow, narrowSilently } +import akka.util.ListenerManagement +import akka.AkkaException + +import scala.beans.BeanProperty +import akka.util.{ ReflectiveAccess, Duration } +import akka.remoteinterface.RemoteSupport +import akka.japi.{ Creator, Procedure } +import java.lang.reflect.InvocationTargetException + +/** Life-cycle messages for the Actors + */ +sealed trait LifeCycleMessage extends Serializable + +/* Marker trait to show which Messages are automatically handled by Akka */ +sealed trait AutoReceivedMessage { self: LifeCycleMessage => } + +case class HotSwap(code: ActorRef => Actor.Receive, discardOld: Boolean = true) + extends AutoReceivedMessage with LifeCycleMessage { + + /** Java API + */ + def this(code: akka.japi.Function[ActorRef, Procedure[Any]], discardOld: Boolean) = + this((self: ActorRef) => { + val behavior = code(self) + val result: Actor.Receive = { case msg => behavior(msg) } + result + }, discardOld) + + /** Java API with default non-stacking behavior + */ + def this(code: akka.japi.Function[ActorRef, Procedure[Any]]) = this(code, true) +} + +case object RevertHotSwap extends AutoReceivedMessage with LifeCycleMessage + +case class Restart(reason: Throwable) extends AutoReceivedMessage with LifeCycleMessage + +case class Exit(dead: ActorRef, killer: Throwable) extends AutoReceivedMessage with LifeCycleMessage + +case class Link(child: ActorRef) extends AutoReceivedMessage with LifeCycleMessage + +case class Unlink(child: ActorRef) extends AutoReceivedMessage with LifeCycleMessage + +case class UnlinkAndStop(child: ActorRef) extends AutoReceivedMessage with LifeCycleMessage + +case object PoisonPill extends AutoReceivedMessage with LifeCycleMessage + +case object Kill extends AutoReceivedMessage with LifeCycleMessage + +case object ReceiveTimeout extends LifeCycleMessage + +case class MaximumNumberOfRestartsWithinTimeRangeReached( + @BeanProperty val victim: ActorRef, + @BeanProperty val maxNrOfRetries: Option[Int], + @BeanProperty val withinTimeRange: Option[Int], + @BeanProperty val lastExceptionCausingRestart: Throwable) extends LifeCycleMessage + +// Exceptions for Actors +class ActorStartException private[akka] (message: String, cause: Throwable = null) extends AkkaException(message, cause) +class IllegalActorStateException private[akka] (message: String, cause: Throwable = null) extends AkkaException(message, cause) +class ActorKilledException private[akka] (message: String, cause: Throwable = null) extends AkkaException(message, cause) +class ActorInitializationException private[akka] (message: String, cause: Throwable = null) extends AkkaException(message, cause) +class ActorTimeoutException private[akka] (message: String, cause: Throwable = null) extends AkkaException(message, cause) +class InvalidMessageException private[akka] (message: String, cause: Throwable = null) extends AkkaException(message, cause) + +/** This message is thrown by default when an Actors behavior doesn't match a message + */ +case class UnhandledMessageException(msg: Any, ref: ActorRef) extends Exception { + override def getMessage() = "Actor %s does not handle [%s]".format(ref, msg) + override def fillInStackTrace() = this //Don't waste cycles generating stack trace +} + +/** Actor factory module with factory methods for creating various kinds of Actors. + * + * @author Jonas Bonér + */ +object Actor extends ListenerManagement { + + /** Add shutdown cleanups + */ + private[akka] lazy val shutdownHook = { + val hook = new Runnable { + override def run { + // Clear Thread.subclassAudits + val tf = classOf[java.lang.Thread].getDeclaredField("subclassAudits") + tf.setAccessible(true) + val subclassAudits = tf.get(null).asInstanceOf[java.util.Map[_, _]] + subclassAudits synchronized { subclassAudits.clear } + } + } + Runtime.getRuntime.addShutdownHook(new Thread(hook)) + hook + } + + val registry = new ActorRegistry + + lazy val remote: RemoteSupport = { + ReflectiveAccess + .Remote + .defaultRemoteSupport + .map(_()) + .getOrElse(throw new UnsupportedOperationException("You need to have akka-remote.jar on classpath")) + } + + private[akka] val TIMEOUT = Duration(config.getInt("akka.actor.timeout", 5), TIME_UNIT).toMillis + private[akka] val SERIALIZE_MESSAGES = config.getBool("akka.actor.serialize-messages", false) + + /** A Receive is a convenience type that defines actor message behavior currently modeled as + * a PartialFunction[Any, Unit]. + */ + type Receive = PartialFunction[Any, Unit] + + private[actor] val actorRefInCreation = new ThreadLocal[Option[ActorRef]] { + override def initialValue = None + } + + /** Creates an ActorRef out of the Actor with type T. + *
+   *   import Actor._
+   *   val actor = actorOf[MyActor]
+   *   actor.start()
+   *   actor ! message
+   *   actor.stop()
+   *  
+ * You can create and start the actor in one statement like this: + *
+   *   val actor = actorOf[MyActor].start()
+   *  
+ */ + def actorOf[T <: Actor: Manifest]: ActorRef = actorOf(manifest[T].erasure.asInstanceOf[Class[_ <: Actor]]) + + /** Creates an ActorRef out of the Actor of the specified Class. + *
+   *   import Actor._
+   *   val actor = actorOf(classOf[MyActor])
+   *   actor.start()
+   *   actor ! message
+   *   actor.stop()
+   *  
+ * You can create and start the actor in one statement like this: + *
+   *   val actor = actorOf(classOf[MyActor]).start()
+   *  
+ */ + def actorOf(clazz: Class[_ <: Actor]): ActorRef = new LocalActorRef(() => { + import ReflectiveAccess.{ createInstance, noParams, noArgs } + createInstance[Actor](clazz.asInstanceOf[Class[_]], noParams, noArgs) match { + case Right(actor) => actor + case Left(exception) => + val cause = exception match { + case i: InvocationTargetException => i.getTargetException + case _ => exception + } + + throw new ActorInitializationException( + "Could not instantiate Actor of " + clazz + + "\nMake sure Actor is NOT defined inside a class/trait," + + "\nif so put it outside the class/trait, f.e. in a companion object," + + "\nOR try to change: 'actorOf[MyActor]' to 'actorOf(new MyActor)'.", cause) + } + + }, None) + + /** Creates an ActorRef out of the Actor. Allows you to pass in a factory function + * that creates the Actor. Please note that this function can be invoked multiple + * times if for example the Actor is supervised and needs to be restarted. + *

+ * This function should NOT be used for remote actors. + *

+   *   import Actor._
+   *   val actor = actorOf(new MyActor)
+   *   actor.start()
+   *   actor ! message
+   *   actor.stop()
+   *  
+ * You can create and start the actor in one statement like this: + *
+   *   val actor = actorOf(new MyActor).start()
+   *  
+ */ + def actorOf(factory: => Actor): ActorRef = new LocalActorRef(() => factory, None) + + /** Creates an ActorRef out of the Actor. Allows you to pass in a factory (Creator) + * that creates the Actor. Please note that this function can be invoked multiple + * times if for example the Actor is supervised and needs to be restarted. + *

+ * This function should NOT be used for remote actors. + * JAVA API + */ + def actorOf(creator: Creator[Actor]): ActorRef = new LocalActorRef(() => creator.create, None) + + /** Use to spawn out a block of code in an event-driven actor. Will shut actor down when + * the block has been executed. + *

+ * NOTE: If used from within an Actor then has to be qualified with 'Actor.spawn' since + * there is a method 'spawn[ActorType]' in the Actor trait already. + * Example: + *

+   *  import Actor.{spawn}
+   *
+   *  spawn  {
+   *   ... // do stuff
+   *  }
+   *  
+ */ + def spawn(body: => Unit)(implicit dispatcher: MessageDispatcher = Dispatchers.defaultGlobalDispatcher): Unit = { + case object Spawn + actorOf(new Actor() { + self.dispatcher = dispatcher + def receive = { + case Spawn => try { body } finally { self.stop() } + } + }).start() ! Spawn + } + + /** Implicitly converts the given Option[Any] to a AnyOptionAsTypedOption which offers the method as[T] + * to convert an Option[Any] to an Option[T]. + */ + implicit def toAnyOptionAsTypedOption(anyOption: Option[Any]) = new AnyOptionAsTypedOption(anyOption) + + /** Implicitly converts the given Future[_] to a AnyOptionAsTypedOption which offers the method as[T] + * to convert an Option[Any] to an Option[T]. + * This means that the following code is equivalent: + * (actor !! "foo").as[Int] (Deprecated) + * and + * (actor !!! "foo").as[Int] (Recommended) + */ + implicit def futureToAnyOptionAsTypedOption(anyFuture: Future[_]) = new AnyOptionAsTypedOption({ + try { anyFuture.await } catch { case t: FutureTimeoutException => } + anyFuture.resultOrException + }) +} + +/** Actor base trait that should be extended by or mixed to create an Actor with the semantics of the 'Actor Model': + * http://en.wikipedia.org/wiki/Actor_model + *

+ * An actor has a well-defined (non-cyclic) life-cycle. + *

+ *  => NEW (newly created actor) - can't receive messages (yet)
+ *     => STARTED (when 'start' is invoked) - can receive messages
+ *         => SHUT DOWN (when 'exit' is invoked) - can't do anything
+ *  
+ * + *

+ * The Actor's API is available in the 'self' member variable. + * + *

+ * Here you find functions like: + * - !, !!, !!! and forward + * - link, unlink, startLink, spawnLink etc + * - makeRemote etc. + * - start, stop + * - etc. + * + *

+ * Here you also find fields like + * - dispatcher = ... + * - id = ... + * - lifeCycle = ... + * - faultHandler = ... + * - trapExit = ... + * - etc. + * + *

+ * This means that to use them you have to prefix them with 'self', like this: self ! Message + * + * However, for convenience you can import these functions and fields like below, which will allow you do + * drop the 'self' prefix: + *

+ *  class MyActor extends Actor  {
+ *   import self._
+ *   id = ...
+ *   dispatcher = ...
+ *   spawnLink[OtherActor]
+ *   ...
+ *  }
+ *  
+ * + * @author Jonas Bonér + */ +trait Actor { + + /** Type alias because traits cannot have companion objects. + */ + type Receive = Actor.Receive + + /* + * Some[ActorRef] representation of the 'self' ActorRef reference. + *

+ * Mainly for internal use, functions as the implicit sender references when invoking + * the 'forward' function. + */ + @transient + implicit val someSelf: Some[ActorRef] = { + val optRef = Actor.actorRefInCreation.get + if (optRef.isEmpty) throw new ActorInitializationException( + "ActorRef for instance of actor [" + getClass.getName + "] is not in scope." + + "\n\tYou can not create an instance of an actor explicitly using 'new MyActor'." + + "\n\tYou have to use one of the factory methods in the 'Actor' object to create a new actor." + + "\n\tEither use:" + + "\n\t\t'val actor = Actor.actorOf[MyActor]', or" + + "\n\t\t'val actor = Actor.actorOf(new MyActor(..))'") + Actor.actorRefInCreation.set(None) + optRef.asInstanceOf[Some[ActorRef]].get.id = getClass.getName //FIXME: Is this needed? + optRef.asInstanceOf[Some[ActorRef]] + } + + /* + * Option[ActorRef] representation of the 'self' ActorRef reference. + *

+ * Mainly for internal use, functions as the implicit sender references when invoking + * one of the message send functions ('!', '!!' and '!!!'). + */ + implicit def optionSelf: Option[ActorRef] = someSelf + + /** The 'self' field holds the ActorRef for this actor. + *

+ * Can be used to send messages to itself: + *

+   *  self ! message
+   *  
+ * Here you also find most of the Actor API. + *

+ * For example fields like: + *

+   *  self.dispatcher = ...
+   *  self.trapExit = ...
+   *  self.faultHandler = ...
+   *  self.lifeCycle = ...
+   *  self.sender
+   *  
+ *

+ * Here you also find methods like: + *

+   *  self.reply(..)
+   *  self.link(..)
+   *  self.unlink(..)
+   *  self.start(..)
+   *  self.stop(..)
+   *  
+ */ + @transient + val self: ScalaActorRef = someSelf.get + + /** User overridable callback/setting. + *

+ * Partial function implementing the actor logic. + * To be implemented by concrete actor class. + *

+ * Example code: + *

+   *   def receive = {
+   *     case Ping =>
+   *       println("got a 'Ping' message")
+   *       self.reply("pong")
+   *
+   *     case OneWay =>
+   *       println("got a 'OneWay' message")
+   *
+   *     case unknown =>
+   *       println("unknown message: " + unknown)
+   *  }
+   *  
+ */ + protected def receive: Receive + + /** User overridable callback. + *

+ * Is called when an Actor is started by invoking 'actor.start()'. + */ + def preStart() {} + + /** User overridable callback. + *

+ * Is called when 'actor.stop()' is invoked. + */ + def postStop() {} + + /** User overridable callback. + *

+ * Is called on a crashed Actor right BEFORE it is restarted to allow clean up of resources before Actor is terminated. + */ + def preRestart(reason: Throwable) {} + + /** User overridable callback. + *

+ * Is called right AFTER restart on the newly created Actor to allow reinitialization after an Actor crash. + */ + def postRestart(reason: Throwable) {} + + /** User overridable callback. + *

+ * Is called when a message isn't handled by the current behavior of the actor + * by default it throws an UnhandledMessageException + */ + def unhandled(msg: Any) { + throw new UnhandledMessageException(msg, self) + } + + /** Is the actor able to handle the message passed in as arguments? + */ + def isDefinedAt(message: Any): Boolean = { + val behaviorStack = self.hotswap + message match { //Same logic as apply(msg) but without the unhandled catch-all + case l: AutoReceivedMessage => true + case msg if behaviorStack.nonEmpty && + behaviorStack.head.isDefinedAt(msg) => true + case msg if behaviorStack.isEmpty && + processingBehavior.isDefinedAt(msg) => true + case _ => false + } + } + + /** Changes the Actor's behavior to become the new 'Receive' (PartialFunction[Any, Unit]) handler. + * Puts the behavior on top of the hotswap stack. + * If "discardOld" is true, an unbecome will be issued prior to pushing the new behavior to the stack + */ + def become(behavior: Receive, discardOld: Boolean = true) { + if (discardOld) unbecome() + self.hotswap = self.hotswap.push(behavior) + } + + /** Reverts the Actor behavior to the previous one in the hotswap stack. + */ + def unbecome(): Unit = { + val h = self.hotswap + if (h.nonEmpty) self.hotswap = h.pop + } + + // ========================================= + // ==== INTERNAL IMPLEMENTATION DETAILS ==== + // ========================================= + + private[akka] final def apply(msg: Any) = { + if (msg.isInstanceOf[AnyRef] && (msg.asInstanceOf[AnyRef] eq null)) + throw new InvalidMessageException("Message from [" + self.sender + "] to [" + self.toString + "] is null") + val behaviorStack = self.hotswap + msg match { + case l: AutoReceivedMessage => autoReceiveMessage(l) + case msg if behaviorStack.nonEmpty && + behaviorStack.head.isDefinedAt(msg) => behaviorStack.head.apply(msg) + case msg if behaviorStack.isEmpty && + processingBehavior.isDefinedAt(msg) => processingBehavior.apply(msg) + case unknown => unhandled(unknown) //This is the only line that differs from processingbehavior + } + } + + private final def autoReceiveMessage(msg: AutoReceivedMessage): Unit = msg match { + case HotSwap(code, discardOld) => become(code(self), discardOld) + case RevertHotSwap => unbecome() + case Exit(dead, reason) => self.handleTrapExit(dead, reason) + case Link(child) => self.link(child) + case Unlink(child) => self.unlink(child) + case UnlinkAndStop(child) => self.unlink(child); child.stop() + case Restart(reason) => throw reason + case Kill => throw new ActorKilledException("Kill") + case PoisonPill => + val f = self.senderFuture + self.stop() + if (f.isDefined) f.get.completeWithException(new ActorKilledException("PoisonPill")) + } + + private lazy val processingBehavior = receive //ProcessingBehavior is the original behavior +} + +private[actor] class AnyOptionAsTypedOption(anyOption: Option[Any]) { + + /** Convenience helper to cast the given Option of Any to an Option of the given type. Will throw a ClassCastException + * if the actual type is not assignable from the given one. + */ + def as[T]: Option[T] = narrow[T](anyOption) + + /** Convenience helper to cast the given Option of Any to an Option of the given type. Will swallow a possible + * ClassCastException and return None in that case. + */ + def asSilently[T: Manifest]: Option[T] = narrowSilently[T](anyOption) +} + +/** Marker interface for proxyable actors (such as typed actor). + * + * @author Jonas Bonér + */ +trait Proxyable { + private[actor] def swapProxiedActor(newInstance: Actor) +} + +/** Represents the different Actor types. + * + * @author Jonas Bonér + */ +sealed trait ActorType +object ActorType { + case object ScalaActor extends ActorType + case object TypedActor extends ActorType +} diff --git a/test/disabled/presentation/akka/src/akka/actor/ActorRef.scala b/test/disabled/presentation/akka/src/akka/actor/ActorRef.scala new file mode 100644 index 0000000000..07fa358744 --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/actor/ActorRef.scala @@ -0,0 +1,1433 @@ +/** + * Copyright (C) 2009-2011 Scalable Solutions AB + */ + +package akka.actor + +import akka.event.EventHandler +import akka.dispatch._ +import akka.config.Supervision._ +import akka.util._ +import ReflectiveAccess._ + +import java.net.InetSocketAddress +import java.util.concurrent.atomic.AtomicReference +import java.util.concurrent.{ ScheduledFuture, ConcurrentHashMap, TimeUnit } +import java.util.{ Map => JMap } + +import scala.beans.BeanProperty +import scala.collection.immutable.Stack +import scala.annotation.tailrec + +private[akka] object ActorRefInternals { + + /** + * LifeCycles for ActorRefs. + */ + private[akka] sealed trait StatusType + object UNSTARTED extends StatusType + object RUNNING extends StatusType + object BEING_RESTARTED extends StatusType + object SHUTDOWN extends StatusType +} + +/** + * Abstraction for unification of sender and senderFuture for later reply. + * Can be stored away and used at a later point in time. + */ +abstract class Channel[T] { + + /** + * Scala API.

+ * Sends the specified message to the channel. + */ + def !(msg: T): Unit + + /** + * Java API.

+ * Sends the specified message to the channel. + */ + def sendOneWay(msg: T): Unit = this.!(msg) +} + +/** + * ActorRef is an immutable and serializable handle to an Actor. + *

+ * Create an ActorRef for an Actor by using the factory method on the Actor object. + *

+ * Here is an example on how to create an actor with a default constructor. + *

+ *   import Actor._
+ *
+ *   val actor = actorOf[MyActor]
+ *   actor.start()
+ *   actor ! message
+ *   actor.stop()
+ * 
+ * + * You can also create and start actors like this: + *
+ *   val actor = actorOf[MyActor].start()
+ * 
+ * + * Here is an example on how to create an actor with a non-default constructor. + *
+ *   import Actor._
+ *
+ *   val actor = actorOf(new MyActor(...))
+ *   actor.start()
+ *   actor ! message
+ *   actor.stop()
+ * 
+ * + * @author Jonas Bonér + */ +trait ActorRef extends ActorRefShared with java.lang.Comparable[ActorRef] { scalaRef: ScalaActorRef => + // Only mutable for RemoteServer in order to maintain identity across nodes + @volatile + protected[akka] var _uuid = newUuid + @volatile + protected[this] var _status: ActorRefInternals.StatusType = ActorRefInternals.UNSTARTED + + /** + * User overridable callback/setting. + *

+ * Identifier for actor, does not have to be a unique one. Default is the 'uuid'. + *

+ * This field is used for logging, AspectRegistry.actorsFor(id), identifier for remote + * actor in RemoteServer etc.But also as the identifier for persistence, which means + * that you can use a custom name to be able to retrieve the "correct" persisted state + * upon restart, remote restart etc. + */ + @BeanProperty + @volatile + var id: String = _uuid.toString + + /** + * User overridable callback/setting. + *

+ * Defines the default timeout for '!!' and '!!!' invocations, + * e.g. the timeout for the future returned by the call to '!!' and '!!!'. + */ + @deprecated("Will be replaced by implicit-scoped timeout on all methods that needs it, will default to timeout specified in config", "1.1") + @BeanProperty + @volatile + var timeout: Long = Actor.TIMEOUT + + /** + * User overridable callback/setting. + *

+ * Defines the default timeout for an initial receive invocation. + * When specified, the receive function should be able to handle a 'ReceiveTimeout' message. + */ + @volatile + var receiveTimeout: Option[Long] = None + + /** + * Akka Java API.

+ * Defines the default timeout for an initial receive invocation. + * When specified, the receive function should be able to handle a 'ReceiveTimeout' message. + */ + def setReceiveTimeout(timeout: Long) = this.receiveTimeout = Some(timeout) + def getReceiveTimeout(): Option[Long] = receiveTimeout + + /** + * Akka Java API.

+ * A faultHandler defines what should be done when a linked actor signals an error. + *

+ * Can be one of: + *

+   * getContext().setFaultHandler(new AllForOneStrategy(new Class[]{Throwable.class},maxNrOfRetries, withinTimeRange));
+   * 
+ * Or: + *
+   * getContext().setFaultHandler(new OneForOneStrategy(new Class[]{Throwable.class},maxNrOfRetries, withinTimeRange));
+   * 
+ */ + def setFaultHandler(handler: FaultHandlingStrategy) + def getFaultHandler(): FaultHandlingStrategy + + /** + * Akka Java API.

+ * A lifeCycle defines whether the actor will be stopped on error (Temporary) or if it can be restarted (Permanent) + *

+ * Can be one of: + * + * import static akka.config.Supervision.*; + *

+   * getContext().setLifeCycle(permanent());
+   * 
+ * Or: + *
+   * getContext().setLifeCycle(temporary());
+   * 
+ */ + def setLifeCycle(lifeCycle: LifeCycle): Unit + def getLifeCycle(): LifeCycle + + /** + * Akka Java API.

+ * The default dispatcher is the Dispatchers.globalExecutorBasedEventDrivenDispatcher. + * This means that all actors will share the same event-driven executor based dispatcher. + *

+ * You can override it so it fits the specific use-case that the actor is used for. + * See the akka.dispatch.Dispatchers class for the different + * 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. + */ + def setDispatcher(dispatcher: MessageDispatcher) = this.dispatcher = dispatcher + def getDispatcher(): MessageDispatcher = dispatcher + + /** + * Returns on which node this actor lives if None it lives in the local ActorRegistry + */ + @deprecated("Remoting will become fully transparent in the future", "1.1") + def homeAddress: Option[InetSocketAddress] + + /** + * Java API.

+ */ + @deprecated("Remoting will become fully transparent in the future", "1.1") + def getHomeAddress(): InetSocketAddress = homeAddress getOrElse null + + /** + * Holds the hot swapped partial function. + */ + @volatile + protected[akka] var hotswap = Stack[PartialFunction[Any, Unit]]() + + /** + * This is a reference to the message currently being processed by the actor + */ + @volatile + protected[akka] var currentMessage: MessageInvocation = null + + /** + * Comparison only takes uuid into account. + */ + def compareTo(other: ActorRef) = this.uuid compareTo other.uuid + + /** + * Returns the uuid for the actor. + */ + def getUuid() = _uuid + def uuid = _uuid + + /** + * Akka Java API.

+ * The reference sender Actor of the last received message. + * Is defined if the message was sent from another Actor, else None. + */ + def getSender(): Option[ActorRef] = sender + + /** + * Akka Java API.

+ * The reference sender future of the last received message. + * Is defined if the message was sent with sent with '!!' or '!!!', else None. + */ + def getSenderFuture(): Option[CompletableFuture[Any]] = senderFuture + + /** + * Is the actor being restarted? + */ + def isBeingRestarted: Boolean = _status == ActorRefInternals.BEING_RESTARTED + + /** + * Is the actor running? + */ + def isRunning: Boolean = _status match { + case ActorRefInternals.BEING_RESTARTED | ActorRefInternals.RUNNING => true + case _ => false + } + + /** + * Is the actor shut down? + */ + def isShutdown: Boolean = _status == ActorRefInternals.SHUTDOWN + + /** + * Is the actor ever started? + */ + def isUnstarted: Boolean = _status == ActorRefInternals.UNSTARTED + + /** + * Is the actor able to handle the message passed in as arguments? + */ + @deprecated("Will be removed without replacement, it's just not reliable in the face of `become` and `unbecome`", "1.1") + def isDefinedAt(message: Any): Boolean = actor.isDefinedAt(message) + + /** + * Only for internal use. UUID is effectively final. + */ + protected[akka] def uuid_=(uid: Uuid) = _uuid = uid + + /** + * Akka Java API.

+ * Sends a one-way asynchronous message. E.g. fire-and-forget semantics. + *

+ *

+   * actor.sendOneWay(message);
+   * 
+ *

+ */ + def sendOneWay(message: AnyRef): Unit = sendOneWay(message, null) + + /** + * Akka Java API.

+ * Sends a one-way asynchronous message. E.g. fire-and-forget semantics. + *

+ * Allows you to pass along the sender of the message. + *

+ *

+   * actor.sendOneWay(message, context);
+   * 
+ *

+ */ + def sendOneWay(message: AnyRef, sender: ActorRef): Unit = this.!(message)(Option(sender)) + + /** + * Akka Java API.

+ * @see sendRequestReply(message: AnyRef, timeout: Long, sender: ActorRef) + * Uses the default timeout of the Actor (setTimeout()) and omits the sender reference + */ + def sendRequestReply(message: AnyRef): AnyRef = sendRequestReply(message, timeout, null) + + /** + * Akka Java API.

+ * @see sendRequestReply(message: AnyRef, timeout: Long, sender: ActorRef) + * Uses the default timeout of the Actor (setTimeout()) + */ + def sendRequestReply(message: AnyRef, sender: ActorRef): AnyRef = sendRequestReply(message, timeout, sender) + + /** + * Akka Java API.

+ * Sends a message asynchronously and waits on a future for a reply message under the hood. + *

+ * It waits on the reply either until it receives it or until the timeout expires + * (which will throw an ActorTimeoutException). E.g. send-and-receive-eventually semantics. + *

+ * NOTE: + * Use this method with care. In most cases it is better to use 'sendOneWay' together with 'getContext().getSender()' to + * implement request/response message exchanges. + *

+ * If you are sending messages using sendRequestReply then you have to use getContext().reply(..) + * to send a reply message to the original sender. If not then the sender will block until the timeout expires. + */ + def sendRequestReply(message: AnyRef, timeout: Long, sender: ActorRef): AnyRef = { + !!(message, timeout)(Option(sender)).getOrElse(throw new ActorTimeoutException( + "Message [" + message + + "]\n\tsent to [" + actorClassName + + "]\n\tfrom [" + (if (sender ne null) sender.actorClassName else "nowhere") + + "]\n\twith timeout [" + timeout + + "]\n\ttimed out.")) + .asInstanceOf[AnyRef] + } + + /** + * Akka Java API.

+ * @see sendRequestReplyFuture(message: AnyRef, sender: ActorRef): Future[_] + * Uses the Actors default timeout (setTimeout()) and omits the sender + */ + def sendRequestReplyFuture[T <: AnyRef](message: AnyRef): Future[T] = sendRequestReplyFuture(message, timeout, null).asInstanceOf[Future[T]] + + /** + * Akka Java API.

+ * @see sendRequestReplyFuture(message: AnyRef, sender: ActorRef): Future[_] + * Uses the Actors default timeout (setTimeout()) + */ + def sendRequestReplyFuture[T <: AnyRef](message: AnyRef, sender: ActorRef): Future[T] = sendRequestReplyFuture(message, timeout, sender).asInstanceOf[Future[T]] + + /** + * Akka Java API.

+ * Sends a message asynchronously returns a future holding the eventual reply message. + *

+ * NOTE: + * Use this method with care. In most cases it is better to use 'sendOneWay' together with the 'getContext().getSender()' to + * implement request/response message exchanges. + *

+ * If you are sending messages using sendRequestReplyFuture then you have to use getContext().reply(..) + * to send a reply message to the original sender. If not then the sender will block until the timeout expires. + */ + def sendRequestReplyFuture[T <: AnyRef](message: AnyRef, timeout: Long, sender: ActorRef): Future[T] = !!!(message, timeout)(Option(sender)).asInstanceOf[Future[T]] + + /** + * Akka Java API.

+ * Forwards the message specified to this actor and preserves the original sender of the message + */ + def forward(message: AnyRef, sender: ActorRef): Unit = + if (sender eq null) throw new IllegalArgumentException("The 'sender' argument to 'forward' can't be null") + else forward(message)(Some(sender)) + + /** + * Akka Java API.

+ * Use getContext().replyUnsafe(..) to reply with a message to the original sender of the message currently + * being processed. + *

+ * Throws an IllegalStateException if unable to determine what to reply to. + */ + def replyUnsafe(message: AnyRef) = reply(message) + + /** + * Akka Java API.

+ * Use getContext().replySafe(..) to reply with a message to the original sender of the message currently + * being processed. + *

+ * Returns true if reply was sent, and false if unable to determine what to reply to. + */ + def replySafe(message: AnyRef): Boolean = reply_?(message) + + /** + * Returns the class for the Actor instance that is managed by the ActorRef. + */ + @deprecated("Will be removed without replacement, doesn't make any sense to have in the face of `become` and `unbecome`", "1.1") + def actorClass: Class[_ <: Actor] + + /** + * Akka Java API.

+ * Returns the class for the Actor instance that is managed by the ActorRef. + */ + @deprecated("Will be removed without replacement, doesn't make any sense to have in the face of `become` and `unbecome`", "1.1") + def getActorClass(): Class[_ <: Actor] = actorClass + + /** + * Returns the class name for the Actor instance that is managed by the ActorRef. + */ + @deprecated("Will be removed without replacement, doesn't make any sense to have in the face of `become` and `unbecome`", "1.1") + def actorClassName: String + + /** + * Akka Java API.

+ * Returns the class name for the Actor instance that is managed by the ActorRef. + */ + @deprecated("Will be removed without replacement, doesn't make any sense to have in the face of `become` and `unbecome`", "1.1") + def getActorClassName(): String = actorClassName + + /** + * Sets the dispatcher for this actor. Needs to be invoked before the actor is started. + */ + def dispatcher_=(md: MessageDispatcher): Unit + + /** + * Get the dispatcher for this actor. + */ + def dispatcher: MessageDispatcher + + /** + * Starts up the actor and its message queue. + */ + def start(): ActorRef + + /** + * Shuts down the actor its dispatcher and message queue. + * Alias for 'stop'. + */ + def exit() = stop() + + /** + * Shuts down the actor its dispatcher and message queue. + */ + def stop(): Unit + + /** + * Links an other actor to this actor. Links are unidirectional and means that a the linking actor will + * receive a notification if the linked actor has crashed. + *

+ * If the 'trapExit' member field of the 'faultHandler' has been set to at contain at least one exception class then it will + * 'trap' these exceptions and automatically restart the linked actors according to the restart strategy + * defined by the 'faultHandler'. + */ + def link(actorRef: ActorRef): Unit + + /** + * Unlink the actor. + */ + def unlink(actorRef: ActorRef): Unit + + /** + * Atomically start and link an actor. + */ + def startLink(actorRef: ActorRef): Unit + + /** + * Atomically create (from actor class) and start an actor. + *

+ * To be invoked from within the actor itself. + */ + @deprecated("Will be removed after 1.1, use Actor.actorOf instead", "1.1") + def spawn(clazz: Class[_ <: Actor]): ActorRef + + /** + * Atomically create (from actor class), make it remote and start an actor. + *

+ * To be invoked from within the actor itself. + */ + @deprecated("Will be removed after 1.1, client managed actors will be removed", "1.1") + def spawnRemote(clazz: Class[_ <: Actor], hostname: String, port: Int, timeout: Long): ActorRef + + /** + * Atomically create (from actor class), link and start an actor. + *

+ * To be invoked from within the actor itself. + */ + @deprecated("Will be removed after 1.1, use use Actor.remote.actorOf instead and then link on success", "1.1") + def spawnLink(clazz: Class[_ <: Actor]): ActorRef + + /** + * Atomically create (from actor class), make it remote, link and start an actor. + *

+ * To be invoked from within the actor itself. + */ + @deprecated("Will be removed after 1.1, client managed actors will be removed", "1.1") + def spawnLinkRemote(clazz: Class[_ <: Actor], hostname: String, port: Int, timeout: Long): ActorRef + + /** + * Returns the mailbox size. + */ + def mailboxSize = dispatcher.mailboxSize(this) + + /** + * Akka Java API.

+ * Returns the mailbox size. + */ + def getMailboxSize(): Int = mailboxSize + + /** + * Returns the supervisor, if there is one. + */ + def supervisor: Option[ActorRef] + + /** + * Akka Java API.

+ * Returns the supervisor, if there is one. + */ + def getSupervisor(): ActorRef = supervisor getOrElse null + + /** + * Returns an unmodifiable Java Map containing the linked actors, + * please note that the backing map is thread-safe but not immutable + */ + def linkedActors: JMap[Uuid, ActorRef] + + /** + * Java API.

+ * Returns an unmodifiable Java Map containing the linked actors, + * please note that the backing map is thread-safe but not immutable + */ + def getLinkedActors(): JMap[Uuid, ActorRef] = linkedActors + + /** + * Abstraction for unification of sender and senderFuture for later reply + */ + def channel: Channel[Any] = { + if (senderFuture.isDefined) { + new Channel[Any] { + val future = senderFuture.get + def !(msg: Any) = future completeWithResult msg + } + } else if (sender.isDefined) { + val someSelf = Some(this) + new Channel[Any] { + val client = sender.get + def !(msg: Any) = client.!(msg)(someSelf) + } + } else throw new IllegalActorStateException("No channel available") + } + + /** + * Java API.

+ * Abstraction for unification of sender and senderFuture for later reply + */ + def getChannel: Channel[Any] = channel + + protected[akka] def invoke(messageHandle: MessageInvocation): Unit + + protected[akka] def postMessageToMailbox(message: Any, senderOption: Option[ActorRef]): Unit + + protected[akka] def postMessageToMailboxAndCreateFutureResultWithTimeout[T]( + message: Any, + timeout: Long, + senderOption: Option[ActorRef], + senderFuture: Option[CompletableFuture[T]]): CompletableFuture[T] + + protected[akka] def actorInstance: AtomicReference[Actor] + + protected[akka] def actor: Actor = actorInstance.get + + protected[akka] def supervisor_=(sup: Option[ActorRef]): Unit + + protected[akka] def mailbox: AnyRef + protected[akka] def mailbox_=(value: AnyRef): AnyRef + + protected[akka] def handleTrapExit(dead: ActorRef, reason: Throwable): Unit + + protected[akka] def restart(reason: Throwable, maxNrOfRetries: Option[Int], withinTimeRange: Option[Int]): Unit + + protected[akka] def restartLinkedActors(reason: Throwable, maxNrOfRetries: Option[Int], withinTimeRange: Option[Int]): Unit + + protected[akka] def registerSupervisorAsRemoteActor: Option[Uuid] + + override def hashCode: Int = HashCode.hash(HashCode.SEED, uuid) + + override def equals(that: Any): Boolean = { + that.isInstanceOf[ActorRef] && + that.asInstanceOf[ActorRef].uuid == uuid + } + + override def toString = "Actor[" + id + ":" + uuid + "]" +} + +/** + * Local (serializable) ActorRef that is used when referencing the Actor on its "home" node. + * + * @author Jonas Bonér + */ +class LocalActorRef private[akka] ( + private[this] val actorFactory: () => Actor, + val homeAddress: Option[InetSocketAddress], + val clientManaged: Boolean = false) + extends ActorRef with ScalaActorRef { + protected[akka] val guard = new ReentrantGuard + + @volatile + protected[akka] var _futureTimeout: Option[ScheduledFuture[AnyRef]] = None + @volatile + private[akka] lazy val _linkedActors = new ConcurrentHashMap[Uuid, ActorRef] + @volatile + private[akka] var _supervisor: Option[ActorRef] = None + @volatile + private var maxNrOfRetriesCount: Int = 0 + @volatile + private var restartsWithinTimeRangeTimestamp: Long = 0L + @volatile + private var _mailbox: AnyRef = _ + @volatile + private[akka] var _dispatcher: MessageDispatcher = Dispatchers.defaultGlobalDispatcher + + protected[akka] val actorInstance = guard.withGuard { new AtomicReference[Actor](newActor) } + + //If it was started inside "newActor", initialize it + if (isRunning) initializeActorInstance + + // used only for deserialization + private[akka] def this( + __uuid: Uuid, + __id: String, + __timeout: Long, + __receiveTimeout: Option[Long], + __lifeCycle: LifeCycle, + __supervisor: Option[ActorRef], + __hotswap: Stack[PartialFunction[Any, Unit]], + __factory: () => Actor, + __homeAddress: Option[InetSocketAddress]) = { + this(__factory, __homeAddress) + _uuid = __uuid + id = __id + timeout = __timeout + receiveTimeout = __receiveTimeout + lifeCycle = __lifeCycle + _supervisor = __supervisor + hotswap = __hotswap + setActorSelfFields(actor, this) + start + } + + /** + * Returns whether this actor ref is client-managed remote or not + */ + private[akka] final def isClientManaged_? = clientManaged && homeAddress.isDefined && isRemotingEnabled + + // ========= PUBLIC FUNCTIONS ========= + + /** + * Returns the class for the Actor instance that is managed by the ActorRef. + */ + @deprecated("Will be removed without replacement, doesn't make any sense to have in the face of `become` and `unbecome`", "1.1") + def actorClass: Class[_ <: Actor] = actor.getClass.asInstanceOf[Class[_ <: Actor]] + + /** + * Returns the class name for the Actor instance that is managed by the ActorRef. + */ + @deprecated("Will be removed without replacement, doesn't make any sense to have in the face of `become` and `unbecome`", "1.1") + def actorClassName: String = actorClass.getName + + /** + * Sets the dispatcher for this actor. Needs to be invoked before the actor is started. + */ + def dispatcher_=(md: MessageDispatcher): Unit = guard.withGuard { + if (!isBeingRestarted) { + if (!isRunning) _dispatcher = md + else throw new ActorInitializationException( + "Can not swap dispatcher for " + toString + " after it has been started") + } + } + + /** + * Get the dispatcher for this actor. + */ + def dispatcher: MessageDispatcher = _dispatcher + + /** + * Starts up the actor and its message queue. + */ + def start(): ActorRef = guard.withGuard { + if (isShutdown) throw new ActorStartException( + "Can't restart an actor that has been shut down with 'stop' or 'exit'") + if (!isRunning) { + dispatcher.attach(this) + + _status = ActorRefInternals.RUNNING + + // If we are not currently creating this ActorRef instance + if ((actorInstance ne null) && (actorInstance.get ne null)) + initializeActorInstance + + if (isClientManaged_?) + Actor.remote.registerClientManagedActor(homeAddress.get.getAddress.getHostAddress, homeAddress.get.getPort, uuid) + + checkReceiveTimeout //Schedule the initial Receive timeout + } + this + } + + /** + * Shuts down the actor its dispatcher and message queue. + */ + def stop() = guard.withGuard { + if (isRunning) { + receiveTimeout = None + cancelReceiveTimeout + dispatcher.detach(this) + _status = ActorRefInternals.SHUTDOWN + try { + actor.postStop + } finally { + currentMessage = null + Actor.registry.unregister(this) + if (isRemotingEnabled) { + if (isClientManaged_?) + Actor.remote.unregisterClientManagedActor(homeAddress.get.getAddress.getHostAddress, homeAddress.get.getPort, uuid) + Actor.remote.unregister(this) + } + setActorSelfFields(actorInstance.get, null) + } + } //else if (isBeingRestarted) throw new ActorKilledException("Actor [" + toString + "] is being restarted.") + } + + /** + * Links an other actor to this actor. Links are unidirectional and means that a the linking actor will + * receive a notification if the linked actor has crashed. + *

+ * If the 'trapExit' member field of the 'faultHandler' has been set to at contain at least one exception class then it will + * 'trap' these exceptions and automatically restart the linked actors according to the restart strategy + * defined by the 'faultHandler'. + *

+ * To be invoked from within the actor itself. + */ + def link(actorRef: ActorRef): Unit = guard.withGuard { + val actorRefSupervisor = actorRef.supervisor + val hasSupervisorAlready = actorRefSupervisor.isDefined + if (hasSupervisorAlready && actorRefSupervisor.get.uuid == uuid) return // we already supervise this guy + else if (hasSupervisorAlready) throw new IllegalActorStateException( + "Actor can only have one supervisor [" + actorRef + "], e.g. link(actor) fails") + else { + _linkedActors.put(actorRef.uuid, actorRef) + actorRef.supervisor = Some(this) + } + } + + /** + * Unlink the actor. + *

+ * To be invoked from within the actor itself. + */ + def unlink(actorRef: ActorRef) = guard.withGuard { + if (_linkedActors.remove(actorRef.uuid) eq null) + throw new IllegalActorStateException("Actor [" + actorRef + "] is not a linked actor, can't unlink") + + actorRef.supervisor = None + } + + /** + * Atomically start and link an actor. + *

+ * To be invoked from within the actor itself. + */ + def startLink(actorRef: ActorRef): Unit = guard.withGuard { + link(actorRef) + actorRef.start() + } + + /** + * Atomically create (from actor class) and start an actor. + *

+ * To be invoked from within the actor itself. + */ + def spawn(clazz: Class[_ <: Actor]): ActorRef = + Actor.actorOf(clazz).start() + + /** + * Atomically create (from actor class), start and make an actor remote. + *

+ * To be invoked from within the actor itself. + */ + def spawnRemote(clazz: Class[_ <: Actor], hostname: String, port: Int, timeout: Long = Actor.TIMEOUT): ActorRef = { + ensureRemotingEnabled + val ref = Actor.remote.actorOf(clazz, hostname, port) + ref.timeout = timeout + ref.start() + } + + /** + * Atomically create (from actor class), start and link an actor. + *

+ * To be invoked from within the actor itself. + */ + def spawnLink(clazz: Class[_ <: Actor]): ActorRef = { + val actor = spawn(clazz) + link(actor) + actor.start() + actor + } + + /** + * Atomically create (from actor class), start, link and make an actor remote. + *

+ * To be invoked from within the actor itself. + */ + def spawnLinkRemote(clazz: Class[_ <: Actor], hostname: String, port: Int, timeout: Long = Actor.TIMEOUT): ActorRef = { + ensureRemotingEnabled + val actor = Actor.remote.actorOf(clazz, hostname, port) + actor.timeout = timeout + link(actor) + actor.start() + actor + } + + /** + * Returns the mailbox. + */ + def mailbox: AnyRef = _mailbox + + protected[akka] def mailbox_=(value: AnyRef): AnyRef = { _mailbox = value; value } + + /** + * Returns the supervisor, if there is one. + */ + def supervisor: Option[ActorRef] = _supervisor + + // ========= AKKA PROTECTED FUNCTIONS ========= + + protected[akka] def supervisor_=(sup: Option[ActorRef]): Unit = _supervisor = sup + + protected[akka] def postMessageToMailbox(message: Any, senderOption: Option[ActorRef]): Unit = + if (isClientManaged_?) { + Actor.remote.send[Any]( + message, senderOption, None, homeAddress.get, timeout, true, this, None, ActorType.ScalaActor, None) + } else + dispatcher dispatchMessage new MessageInvocation(this, message, senderOption, None) + + protected[akka] def postMessageToMailboxAndCreateFutureResultWithTimeout[T]( + message: Any, + timeout: Long, + senderOption: Option[ActorRef], + senderFuture: Option[CompletableFuture[T]]): CompletableFuture[T] = { + if (isClientManaged_?) { + val future = Actor.remote.send[T]( + message, senderOption, senderFuture, homeAddress.get, timeout, false, this, None, ActorType.ScalaActor, None) + if (future.isDefined) future.get + else throw new IllegalActorStateException("Expected a future from remote call to actor " + toString) + } else { + val future = if (senderFuture.isDefined) senderFuture else Some(new DefaultCompletableFuture[T](timeout)) + dispatcher dispatchMessage new MessageInvocation( + this, message, senderOption, future.asInstanceOf[Some[CompletableFuture[Any]]]) + future.get + } + } + + /** + * Callback for the dispatcher. This is the single entry point to the user Actor implementation. + */ + protected[akka] def invoke(messageHandle: MessageInvocation): Unit = { + guard.lock.lock + try { + if (!isShutdown) { + currentMessage = messageHandle + try { + try { + cancelReceiveTimeout // FIXME: leave this here? + actor(messageHandle.message) + currentMessage = null // reset current message after successful invocation + } catch { + case e: InterruptedException => + currentMessage = null // received message while actor is shutting down, ignore + case e => + handleExceptionInDispatch(e, messageHandle.message) + } + finally { + checkReceiveTimeout // Reschedule receive timeout + } + } catch { + case e => + EventHandler.error(e, this, messageHandle.message.toString) + throw e + } + } + } finally { guard.lock.unlock } + } + + protected[akka] def handleTrapExit(dead: ActorRef, reason: Throwable) { + faultHandler match { + case AllForOneStrategy(trapExit, maxRetries, within) if trapExit.exists(_.isAssignableFrom(reason.getClass)) => + restartLinkedActors(reason, maxRetries, within) + + case OneForOneStrategy(trapExit, maxRetries, within) if trapExit.exists(_.isAssignableFrom(reason.getClass)) => + dead.restart(reason, maxRetries, within) + + case _ => + if (_supervisor.isDefined) notifySupervisorWithMessage(Exit(this, reason)) + else dead.stop() + } + } + + private def requestRestartPermission(maxNrOfRetries: Option[Int], withinTimeRange: Option[Int]): Boolean = { + val denied = if (maxNrOfRetries.isEmpty && withinTimeRange.isEmpty) { //Immortal + false + } else if (withinTimeRange.isEmpty) { // restrict number of restarts + maxNrOfRetriesCount += 1 //Increment number of retries + maxNrOfRetriesCount > maxNrOfRetries.get + } else { // cannot restart more than N within M timerange + maxNrOfRetriesCount += 1 //Increment number of retries + val windowStart = restartsWithinTimeRangeTimestamp + val now = System.currentTimeMillis + val retries = maxNrOfRetriesCount + //We are within the time window if it isn't the first restart, or if the window hasn't closed + val insideWindow = if (windowStart == 0) false + else (now - windowStart) <= withinTimeRange.get + + //The actor is dead if it dies X times within the window of restart + val unrestartable = insideWindow && retries > maxNrOfRetries.getOrElse(1) + + if (windowStart == 0 || !insideWindow) //(Re-)set the start of the window + restartsWithinTimeRangeTimestamp = now + + if (windowStart != 0 && !insideWindow) //Reset number of restarts if window has expired + maxNrOfRetriesCount = 1 + + unrestartable + } + + denied == false //If we weren't denied, we have a go + } + + protected[akka] def restart(reason: Throwable, maxNrOfRetries: Option[Int], withinTimeRange: Option[Int]) { + def performRestart() { + val failedActor = actorInstance.get + + failedActor match { + case p: Proxyable => + failedActor.preRestart(reason) + failedActor.postRestart(reason) + case _ => + failedActor.preRestart(reason) + val freshActor = newActor + setActorSelfFields(failedActor, null) // Only null out the references if we could instantiate the new actor + actorInstance.set(freshActor) // Assign it here so if preStart fails, we can null out the sef-refs next call + freshActor.preStart + freshActor.postRestart(reason) + } + } + + def tooManyRestarts() { + _supervisor.foreach { sup => + // can supervisor handle the notification? + val notification = MaximumNumberOfRestartsWithinTimeRangeReached(this, maxNrOfRetries, withinTimeRange, reason) + if (sup.isDefinedAt(notification)) notifySupervisorWithMessage(notification) + } + stop + } + + @tailrec + def attemptRestart() { + val success = if (requestRestartPermission(maxNrOfRetries, withinTimeRange)) { + guard.withGuard[Boolean] { + _status = ActorRefInternals.BEING_RESTARTED + + lifeCycle match { + case Temporary => + shutDownTemporaryActor(this) + true + + case _ => // either permanent or none where default is permanent + val success = try { + performRestart() + true + } catch { + case e => + EventHandler.error(e, this, "Exception in restart of Actor [%s]".format(toString)) + false // an error or exception here should trigger a retry + } + finally { + currentMessage = null + } + if (success) { + _status = ActorRefInternals.RUNNING + dispatcher.resume(this) + restartLinkedActors(reason, maxNrOfRetries, withinTimeRange) + } + success + } + } + } else { + tooManyRestarts() + true // done + } + + if (success) () // alles gut + else attemptRestart() + } + + attemptRestart() // recur + } + + protected[akka] def restartLinkedActors(reason: Throwable, maxNrOfRetries: Option[Int], withinTimeRange: Option[Int]) = { + val i = _linkedActors.values.iterator + while (i.hasNext) { + val actorRef = i.next + actorRef.lifeCycle match { + // either permanent or none where default is permanent + case Temporary => shutDownTemporaryActor(actorRef) + case _ => actorRef.restart(reason, maxNrOfRetries, withinTimeRange) + } + } + } + + protected[akka] def registerSupervisorAsRemoteActor: Option[Uuid] = guard.withGuard { + ensureRemotingEnabled + if (_supervisor.isDefined) { + if (homeAddress.isDefined) Actor.remote.registerSupervisorForActor(this) + Some(_supervisor.get.uuid) + } else None + } + + def linkedActors: JMap[Uuid, ActorRef] = java.util.Collections.unmodifiableMap(_linkedActors) + + // ========= PRIVATE FUNCTIONS ========= + + private[this] def newActor: Actor = { + try { + Actor.actorRefInCreation.set(Some(this)) + val a = actorFactory() + if (a eq null) throw new ActorInitializationException("Actor instance passed to ActorRef can not be 'null'") + a + } finally { + Actor.actorRefInCreation.set(None) + } + } + + private def shutDownTemporaryActor(temporaryActor: ActorRef) { + temporaryActor.stop() + _linkedActors.remove(temporaryActor.uuid) // remove the temporary actor + // if last temporary actor is gone, then unlink me from supervisor + if (_linkedActors.isEmpty) notifySupervisorWithMessage(UnlinkAndStop(this)) + true + } + + private def handleExceptionInDispatch(reason: Throwable, message: Any) = { + EventHandler.error(reason, this, message.toString) + + //Prevent any further messages to be processed until the actor has been restarted + dispatcher.suspend(this) + + senderFuture.foreach(_.completeWithException(reason)) + + if (supervisor.isDefined) notifySupervisorWithMessage(Exit(this, reason)) + else { + lifeCycle match { + case Temporary => shutDownTemporaryActor(this) + case _ => dispatcher.resume(this) //Resume processing for this actor + } + } + } + + private def notifySupervisorWithMessage(notification: LifeCycleMessage) = { + // FIXME to fix supervisor restart of remote actor for oneway calls, inject a supervisor proxy that can send notification back to client + _supervisor.foreach { sup => + if (sup.isShutdown) { // if supervisor is shut down, game over for all linked actors + //Scoped stop all linked actors, to avoid leaking the 'i' val + { + val i = _linkedActors.values.iterator + while (i.hasNext) { + i.next.stop() + i.remove + } + } + //Stop the actor itself + stop + } else sup ! notification // else notify supervisor + } + } + + private def setActorSelfFields(actor: Actor, value: ActorRef) { + + @tailrec + def lookupAndSetSelfFields(clazz: Class[_], actor: Actor, value: ActorRef): Boolean = { + val success = try { + val selfField = clazz.getDeclaredField("self") + val someSelfField = clazz.getDeclaredField("someSelf") + selfField.setAccessible(true) + someSelfField.setAccessible(true) + selfField.set(actor, value) + someSelfField.set(actor, if (value ne null) Some(value) else null) + true + } catch { + case e: NoSuchFieldException => false + } + + if (success) true + else { + val parent = clazz.getSuperclass + if (parent eq null) + throw new IllegalActorStateException(toString + " is not an Actor since it have not mixed in the 'Actor' trait") + lookupAndSetSelfFields(parent, actor, value) + } + } + + lookupAndSetSelfFields(actor.getClass, actor, value) + } + + private def initializeActorInstance = { + actor.preStart // run actor preStart + Actor.registry.register(this) + } + + protected[akka] def checkReceiveTimeout = { + cancelReceiveTimeout + if (receiveTimeout.isDefined && dispatcher.mailboxSize(this) <= 0) { //Only reschedule if desired and there are currently no more messages to be processed + _futureTimeout = Some(Scheduler.scheduleOnce(this, ReceiveTimeout, receiveTimeout.get, TimeUnit.MILLISECONDS)) + } + } + + protected[akka] def cancelReceiveTimeout = { + if (_futureTimeout.isDefined) { + _futureTimeout.get.cancel(true) + _futureTimeout = None + } + } +} + +/** + * System messages for RemoteActorRef. + * + * @author Jonas Bonér + */ +object RemoteActorSystemMessage { + val Stop = "RemoteActorRef:stop".intern +} + +/** + * Remote ActorRef that is used when referencing the Actor on a different node than its "home" node. + * This reference is network-aware (remembers its origin) and immutable. + * + * @author Jonas Bonér + */ +private[akka] case class RemoteActorRef private[akka] ( + classOrServiceName: String, + val actorClassName: String, + val hostname: String, + val port: Int, + _timeout: Long, + loader: Option[ClassLoader], + val actorType: ActorType = ActorType.ScalaActor) + extends ActorRef with ScalaActorRef { + + ensureRemotingEnabled + + val homeAddress = Some(new InetSocketAddress(hostname, port)) + + //protected def clientManaged = classOrServiceName.isEmpty //If no class or service name, it's client managed + id = classOrServiceName + //id = classOrServiceName.getOrElse("uuid:" + uuid) //If we're a server-managed we want to have classOrServiceName as id, or else, we're a client-managed and we want to have our uuid as id + + timeout = _timeout + + start + + def postMessageToMailbox(message: Any, senderOption: Option[ActorRef]): Unit = + Actor.remote.send[Any](message, senderOption, None, homeAddress.get, timeout, true, this, None, actorType, loader) + + def postMessageToMailboxAndCreateFutureResultWithTimeout[T]( + message: Any, + timeout: Long, + senderOption: Option[ActorRef], + senderFuture: Option[CompletableFuture[T]]): CompletableFuture[T] = { + val future = Actor.remote.send[T]( + message, senderOption, senderFuture, + homeAddress.get, timeout, + false, this, None, + actorType, loader) + if (future.isDefined) future.get + else throw new IllegalActorStateException("Expected a future from remote call to actor " + toString) + } + + def start: ActorRef = synchronized { + _status = ActorRefInternals.RUNNING + this + } + + def stop: Unit = synchronized { + if (_status == ActorRefInternals.RUNNING) { + _status = ActorRefInternals.SHUTDOWN + postMessageToMailbox(RemoteActorSystemMessage.Stop, None) + } + } + + protected[akka] def registerSupervisorAsRemoteActor: Option[Uuid] = None + + // ==== NOT SUPPORTED ==== + @deprecated("Will be removed without replacement, doesn't make any sense to have in the face of `become` and `unbecome`", "1.1") + def actorClass: Class[_ <: Actor] = unsupported + def dispatcher_=(md: MessageDispatcher): Unit = unsupported + def dispatcher: MessageDispatcher = unsupported + def link(actorRef: ActorRef): Unit = unsupported + def unlink(actorRef: ActorRef): Unit = unsupported + def startLink(actorRef: ActorRef): Unit = unsupported + def spawn(clazz: Class[_ <: Actor]): ActorRef = unsupported + def spawnRemote(clazz: Class[_ <: Actor], hostname: String, port: Int, timeout: Long): ActorRef = unsupported + def spawnLink(clazz: Class[_ <: Actor]): ActorRef = unsupported + def spawnLinkRemote(clazz: Class[_ <: Actor], hostname: String, port: Int, timeout: Long): ActorRef = unsupported + def supervisor: Option[ActorRef] = unsupported + def linkedActors: JMap[Uuid, ActorRef] = unsupported + protected[akka] def mailbox: AnyRef = unsupported + protected[akka] def mailbox_=(value: AnyRef): AnyRef = unsupported + protected[akka] def handleTrapExit(dead: ActorRef, reason: Throwable): Unit = unsupported + protected[akka] def restart(reason: Throwable, maxNrOfRetries: Option[Int], withinTimeRange: Option[Int]): Unit = unsupported + protected[akka] def restartLinkedActors(reason: Throwable, maxNrOfRetries: Option[Int], withinTimeRange: Option[Int]): Unit = unsupported + protected[akka] def invoke(messageHandle: MessageInvocation): Unit = unsupported + protected[akka] def supervisor_=(sup: Option[ActorRef]): Unit = unsupported + protected[akka] def actorInstance: AtomicReference[Actor] = unsupported + private def unsupported = throw new UnsupportedOperationException("Not supported for RemoteActorRef") +} + +/** + * This trait represents the common (external) methods for all ActorRefs + * Needed because implicit conversions aren't applied when instance imports are used + * + * i.e. + * var self: ScalaActorRef = ... + * import self._ + * //can't call ActorRef methods here unless they are declared in a common + * //superclass, which ActorRefShared is. + */ +trait ActorRefShared { + /** + * Returns the uuid for the actor. + */ + def uuid: Uuid +} + +/** + * This trait represents the Scala Actor API + * There are implicit conversions in ../actor/Implicits.scala + * from ActorRef -> ScalaActorRef and back + */ +trait ScalaActorRef extends ActorRefShared { ref: ActorRef => + + /** + * Identifier for actor, does not have to be a unique one. Default is the 'uuid'. + *

+ * This field is used for logging, AspectRegistry.actorsFor(id), identifier for remote + * actor in RemoteServer etc.But also as the identifier for persistence, which means + * that you can use a custom name to be able to retrieve the "correct" persisted state + * upon restart, remote restart etc. + */ + def id: String + + def id_=(id: String): Unit + + /** + * User overridable callback/setting. + *

+ * Defines the life-cycle for a supervised actor. + */ + @volatile + @BeanProperty + var lifeCycle: LifeCycle = UndefinedLifeCycle + + /** + * User overridable callback/setting. + *

+ * Don't forget to supply a List of exception types to intercept (trapExit) + *

+ * Can be one of: + *

+   *  faultHandler = AllForOneStrategy(trapExit = List(classOf[Exception]), maxNrOfRetries, withinTimeRange)
+   * 
+ * Or: + *
+   *  faultHandler = OneForOneStrategy(trapExit = List(classOf[Exception]), maxNrOfRetries, withinTimeRange)
+   * 
+ */ + @volatile + @BeanProperty + var faultHandler: FaultHandlingStrategy = NoFaultHandlingStrategy + + /** + * The reference sender Actor of the last received message. + * Is defined if the message was sent from another Actor, else None. + */ + def sender: Option[ActorRef] = { + val msg = currentMessage + if (msg eq null) None + else msg.sender + } + + /** + * The reference sender future of the last received message. + * Is defined if the message was sent with sent with '!!' or '!!!', else None. + */ + def senderFuture(): Option[CompletableFuture[Any]] = { + val msg = currentMessage + if (msg eq null) None + else msg.senderFuture + } + + /** + * Sends a one-way asynchronous message. E.g. fire-and-forget semantics. + *

+ * + * 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, + * if invoked from within an Actor. If not then no sender is available. + *

+   *   actor ! message
+   * 
+ *

+ */ + def !(message: Any)(implicit sender: Option[ActorRef] = None): Unit = { + if (isRunning) postMessageToMailbox(message, sender) + else throw new ActorInitializationException( + "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. + *

+ * It waits on the reply either until it receives it (in the form of Some(replyMessage)) + * or until the timeout expires (which will return None). E.g. send-and-receive-eventually semantics. + *

+ * NOTE: + * Use this method with care. In most cases it is better to use '!' together with the 'sender' member field to + * implement request/response message exchanges. + * If you are sending messages using !! then you have to use self.reply(..) + * to send a reply message to the original sender. If not then the sender will block until the timeout expires. + */ + def !!(message: Any, timeout: Long = this.timeout)(implicit sender: Option[ActorRef] = None): Option[Any] = { + if (isRunning) { + val future = postMessageToMailboxAndCreateFutureResultWithTimeout[Any](message, timeout, sender, None) + val isMessageJoinPoint = if (isTypedActorEnabled) TypedActorModule.resolveFutureIfMessageIsJoinPoint(message, future) + else false + try { + future.await + } catch { + case e: FutureTimeoutException => + if (isMessageJoinPoint) { + EventHandler.error(e, this, e.getMessage) + throw e + } else None + } + future.resultOrException + } else throw new ActorInitializationException( + "Actor has not been started, you need to invoke 'actor.start()' before using it") + } + + /** + * Sends a message asynchronously returns a future holding the eventual reply message. + *

+ * NOTE: + * Use this method with care. In most cases it is better to use '!' together with the 'sender' member field to + * implement request/response message exchanges. + * If you are sending messages using !!! then you have to use self.reply(..) + * to send a reply message to the original sender. If not then the sender will block until the timeout expires. + */ + def !!![T](message: Any, timeout: Long = this.timeout)(implicit sender: Option[ActorRef] = None): Future[T] = { + if (isRunning) postMessageToMailboxAndCreateFutureResultWithTimeout[T](message, timeout, sender, None) + else throw new ActorInitializationException( + "Actor has not been started, you need to invoke 'actor.start()' before using it") + } + + /** + * Forwards the message and passes the original sender actor as the sender. + *

+ * Works with '!', '!!' and '!!!'. + */ + def forward(message: Any)(implicit sender: Some[ActorRef]) = { + if (isRunning) { + if (sender.get.senderFuture.isDefined) + postMessageToMailboxAndCreateFutureResultWithTimeout(message, timeout, sender.get.sender, sender.get.senderFuture) + else + postMessageToMailbox(message, sender.get.sender) + } else throw new ActorInitializationException("Actor has not been started, you need to invoke 'actor.start()' before using it") + } + + /** + * Use self.reply(..) to reply with a message to the original sender of the message currently + * being processed. + *

+ * Throws an IllegalStateException if unable to determine what to reply to. + */ + def reply(message: Any) = if (!reply_?(message)) throw new IllegalActorStateException( + "\n\tNo sender in scope, can't reply. " + + "\n\tYou have probably: " + + "\n\t\t1. Sent a message to an Actor from an instance that is NOT an Actor." + + "\n\t\t2. Invoked a method on an TypedActor from an instance NOT an TypedActor." + + "\n\tElse you might want to use 'reply_?' which returns Boolean(true) if succes and Boolean(false) if no sender in scope") + + /** + * Use reply_?(..) to reply with a message to the original sender of the message currently + * being processed. + *

+ * Returns true if reply was sent, and false if unable to determine what to reply to. + */ + def reply_?(message: Any): Boolean = { + if (senderFuture.isDefined) { + senderFuture.get completeWithResult message + true + } else if (sender.isDefined) { + //TODO: optimize away this allocation, perhaps by having implicit self: Option[ActorRef] in signature + sender.get.!(message)(Some(this)) + true + } else false + } + + /** + * Atomically create (from actor class) and start an actor. + */ + def spawn[T <: Actor: Manifest]: ActorRef = + spawn(manifest[T].erasure.asInstanceOf[Class[_ <: Actor]]) + + /** + * Atomically create (from actor class), start and make an actor remote. + */ + def spawnRemote[T <: Actor: Manifest](hostname: String, port: Int, timeout: Long): ActorRef = { + ensureRemotingEnabled + spawnRemote(manifest[T].erasure.asInstanceOf[Class[_ <: Actor]], hostname, port, timeout) + } + + /** + * Atomically create (from actor class), start and link an actor. + */ + def spawnLink[T <: Actor: Manifest]: ActorRef = + spawnLink(manifest[T].erasure.asInstanceOf[Class[_ <: Actor]]) + + /** + * Atomically create (from actor class), start, link and make an actor remote. + */ + def spawnLinkRemote[T <: Actor: Manifest](hostname: String, port: Int, timeout: Long): ActorRef = { + ensureRemotingEnabled + spawnLinkRemote(manifest[T].erasure.asInstanceOf[Class[_ <: Actor]], hostname, port, timeout) + } +} diff --git a/test/disabled/presentation/akka/src/akka/actor/ActorRegistry.scala b/test/disabled/presentation/akka/src/akka/actor/ActorRegistry.scala new file mode 100644 index 0000000000..df335dc8b4 --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/actor/ActorRegistry.scala @@ -0,0 +1,389 @@ +/** + * Copyright (C) 2009-2011 Scalable Solutions AB + */ + +package akka.actor + +import scala.collection.mutable.{ ListBuffer, Map } +import scala.reflect.Manifest + +import java.util.concurrent.{ ConcurrentSkipListSet, ConcurrentHashMap } +import java.util.{ Set => JSet } + +import annotation.tailrec +import akka.util.ReflectiveAccess._ +import akka.util.{ ReflectiveAccess, ReadWriteGuard, ListenerManagement } + +/** + * Base trait for ActorRegistry events, allows listen to when an actor is added and removed from the ActorRegistry. + * + * @author Jonas Bonér + */ +sealed trait ActorRegistryEvent +case class ActorRegistered(actor: ActorRef) extends ActorRegistryEvent +case class ActorUnregistered(actor: ActorRef) extends ActorRegistryEvent + +/** + * Registry holding all Actor instances in the whole system. + * Mapped by: + *

    + *
  • the Actor's UUID
  • + *
  • the Actor's id field (which can be set by user-code)
  • + *
  • the Actor's class
  • + *
  • all Actors that are subtypes of a specific type
  • + *
      + * + * @author Jonas Bonér + */ + +final class ActorRegistry private[actor] () extends ListenerManagement { + + private val actorsByUUID = new ConcurrentHashMap[Uuid, ActorRef] + private val actorsById = new Index[String, ActorRef] + private val guard = new ReadWriteGuard + + /** + * Returns all actors in the system. + */ + def actors: Array[ActorRef] = filter(_ => true) + + /** + * Returns the number of actors in the system. + */ + def size: Int = actorsByUUID.size + + /** + * Invokes a function for all actors. + */ + def foreach(f: (ActorRef) => Unit) = { + val elements = actorsByUUID.elements + while (elements.hasMoreElements) f(elements.nextElement) + } + + /** + * Invokes the function on all known actors until it returns Some + * Returns None if the function never returns Some + */ + def find[T](f: PartialFunction[ActorRef, T]): Option[T] = { + val elements = actorsByUUID.elements + while (elements.hasMoreElements) { + val element = elements.nextElement + if (f isDefinedAt element) return Some(f(element)) + } + None + } + + /** + * Finds all actors that are subtypes of the class passed in as the Manifest argument and supporting passed message. + */ + def actorsFor[T <: Actor](message: Any)(implicit manifest: Manifest[T]): Array[ActorRef] = + filter(a => manifest.erasure.isAssignableFrom(a.actor.getClass) && a.isDefinedAt(message)) + + /** + * Finds all actors that satisfy a predicate. + */ + def filter(p: ActorRef => Boolean): Array[ActorRef] = { + val all = new ListBuffer[ActorRef] + val elements = actorsByUUID.elements + while (elements.hasMoreElements) { + val actorId = elements.nextElement + if (p(actorId)) all += actorId + } + all.toArray + } + + /** + * Finds all actors that are subtypes of the class passed in as the Manifest argument. + */ + def actorsFor[T <: Actor](implicit manifest: Manifest[T]): Array[ActorRef] = + actorsFor[T](manifest.erasure.asInstanceOf[Class[T]]) + + /** + * Finds any actor that matches T. Very expensive, traverses ALL alive actors. + */ + def actorFor[T <: Actor](implicit manifest: Manifest[T]): Option[ActorRef] = + find({ case a: ActorRef if manifest.erasure.isAssignableFrom(a.actor.getClass) => a }) + + /** + * Finds all actors of type or sub-type specified by the class passed in as the Class argument. + */ + def actorsFor[T <: Actor](clazz: Class[T]): Array[ActorRef] = + filter(a => clazz.isAssignableFrom(a.actor.getClass)) + + /** + * Finds all actors that has a specific id. + */ + def actorsFor(id: String): Array[ActorRef] = actorsById values id + + /** + * Finds the actor that has a specific UUID. + */ + def actorFor(uuid: Uuid): Option[ActorRef] = Option(actorsByUUID get uuid) + + /** + * Returns all typed actors in the system. + */ + def typedActors: Array[AnyRef] = filterTypedActors(_ => true) + + /** + * Invokes a function for all typed actors. + */ + def foreachTypedActor(f: (AnyRef) => Unit) = { + TypedActorModule.ensureEnabled + val elements = actorsByUUID.elements + while (elements.hasMoreElements) { + val proxy = typedActorFor(elements.nextElement) + if (proxy.isDefined) f(proxy.get) + } + } + + /** + * Invokes the function on all known typed actors until it returns Some + * Returns None if the function never returns Some + */ + def findTypedActor[T](f: PartialFunction[AnyRef, T]): Option[T] = { + TypedActorModule.ensureEnabled + val elements = actorsByUUID.elements + while (elements.hasMoreElements) { + val proxy = typedActorFor(elements.nextElement) + if (proxy.isDefined && (f isDefinedAt proxy)) return Some(f(proxy)) + } + None + } + + /** + * Finds all typed actors that satisfy a predicate. + */ + def filterTypedActors(p: AnyRef => Boolean): Array[AnyRef] = { + TypedActorModule.ensureEnabled + val all = new ListBuffer[AnyRef] + val elements = actorsByUUID.elements + while (elements.hasMoreElements) { + val proxy = typedActorFor(elements.nextElement) + if (proxy.isDefined && p(proxy.get)) all += proxy.get + } + all.toArray + } + + /** + * Finds all typed actors that are subtypes of the class passed in as the Manifest argument. + */ + def typedActorsFor[T <: AnyRef](implicit manifest: Manifest[T]): Array[AnyRef] = { + TypedActorModule.ensureEnabled + typedActorsFor[T](manifest.erasure.asInstanceOf[Class[T]]) + } + + /** + * Finds any typed actor that matches T. + */ + def typedActorFor[T <: AnyRef](implicit manifest: Manifest[T]): Option[AnyRef] = { + TypedActorModule.ensureEnabled + def predicate(proxy: AnyRef): Boolean = { + val actorRef = TypedActorModule.typedActorObjectInstance.get.actorFor(proxy) + actorRef.isDefined && manifest.erasure.isAssignableFrom(actorRef.get.actor.getClass) + } + findTypedActor({ case a: Some[AnyRef] if predicate(a.get) => a }) + } + + /** + * Finds all typed actors of type or sub-type specified by the class passed in as the Class argument. + */ + def typedActorsFor[T <: AnyRef](clazz: Class[T]): Array[AnyRef] = { + TypedActorModule.ensureEnabled + def predicate(proxy: AnyRef): Boolean = { + val actorRef = TypedActorModule.typedActorObjectInstance.get.actorFor(proxy) + actorRef.isDefined && clazz.isAssignableFrom(actorRef.get.actor.getClass) + } + filterTypedActors(predicate) + } + + /** + * Finds all typed actors that have a specific id. + */ + def typedActorsFor(id: String): Array[AnyRef] = { + TypedActorModule.ensureEnabled + val actorRefs = actorsById values id + actorRefs.flatMap(typedActorFor(_)) + } + + /** + * Finds the typed actor that has a specific UUID. + */ + def typedActorFor(uuid: Uuid): Option[AnyRef] = { + TypedActorModule.ensureEnabled + val actorRef = actorsByUUID get uuid + if (actorRef eq null) None + else typedActorFor(actorRef) + } + + /** + * Get the typed actor proxy for a given typed actor ref. + */ + private def typedActorFor(actorRef: ActorRef): Option[AnyRef] = { + TypedActorModule.typedActorObjectInstance.get.proxyFor(actorRef) + } + + /** + * Registers an actor in the ActorRegistry. + */ + private[akka] def register(actor: ActorRef) { + val id = actor.id + val uuid = actor.uuid + + actorsById.put(id, actor) + actorsByUUID.put(uuid, actor) + + // notify listeners + notifyListeners(ActorRegistered(actor)) + } + + /** + * Unregisters an actor in the ActorRegistry. + */ + private[akka] def unregister(actor: ActorRef) { + val id = actor.id + val uuid = actor.uuid + + actorsByUUID remove uuid + actorsById.remove(id, actor) + + // notify listeners + notifyListeners(ActorUnregistered(actor)) + } + + /** + * Shuts down and unregisters all actors in the system. + */ + def shutdownAll() { + if (TypedActorModule.isEnabled) { + val elements = actorsByUUID.elements + while (elements.hasMoreElements) { + val actorRef = elements.nextElement + val proxy = typedActorFor(actorRef) + if (proxy.isDefined) TypedActorModule.typedActorObjectInstance.get.stop(proxy.get) + else actorRef.stop() + } + } else foreach(_.stop()) + if (Remote.isEnabled) { + Actor.remote.clear //TODO: REVISIT: Should this be here? + } + actorsByUUID.clear + actorsById.clear + } +} + +/** + * An implementation of a ConcurrentMultiMap + * Adds/remove is serialized over the specified key + * Reads are fully concurrent <-- el-cheapo + * + * @author Viktor Klang + */ +class Index[K <: AnyRef, V <: AnyRef: Manifest] { + private val Naught = Array[V]() //Nil for Arrays + private val container = new ConcurrentHashMap[K, JSet[V]] + private val emptySet = new ConcurrentSkipListSet[V] + + /** + * Associates the value of type V with the key of type K + * @return true if the value didn't exist for the key previously, and false otherwise + */ + def put(key: K, value: V): Boolean = { + //Tailrecursive spin-locking put + @tailrec + def spinPut(k: K, v: V): Boolean = { + var retry = false + var added = false + val set = container get k + + if (set ne null) { + set.synchronized { + if (set.isEmpty) retry = true //IF the set is empty then it has been removed, so signal retry + else { //Else add the value to the set and signal that retry is not needed + added = set add v + retry = false + } + } + } else { + val newSet = new ConcurrentSkipListSet[V] + newSet add v + + // Parry for two simultaneous putIfAbsent(id,newSet) + val oldSet = container.putIfAbsent(k, newSet) + if (oldSet ne null) { + oldSet.synchronized { + if (oldSet.isEmpty) retry = true //IF the set is empty then it has been removed, so signal retry + else { //Else try to add the value to the set and signal that retry is not needed + added = oldSet add v + retry = false + } + } + } else added = true + } + + if (retry) spinPut(k, v) + else added + } + + spinPut(key, value) + } + + /** + * @return a _new_ array of all existing values for the given key at the time of the call + */ + def values(key: K): Array[V] = { + val set: JSet[V] = container get key + val result = if (set ne null) set toArray Naught else Naught + result.asInstanceOf[Array[V]] + } + + /** + * @return Some(value) for the first matching value where the supplied function returns true for the given key, + * if no matches it returns None + */ + def findValue(key: K)(f: (V) => Boolean): Option[V] = { + import scala.collection.JavaConversions._ + val set = container get key + if (set ne null) set.iterator.find(f) + else None + } + + /** + * Applies the supplied function to all keys and their values + */ + def foreach(fun: (K, V) => Unit) { + import scala.collection.JavaConversions._ + container.entrySet foreach { (e) => + e.getValue.foreach(fun(e.getKey, _)) + } + } + + /** + * Disassociates the value of type V from the key of type K + * @return true if the value was disassociated from the key and false if it wasn't previously associated with the key + */ + def remove(key: K, value: V): Boolean = { + val set = container get key + + if (set ne null) { + set.synchronized { + if (set.remove(value)) { //If we can remove the value + if (set.isEmpty) //and the set becomes empty + container.remove(key, emptySet) //We try to remove the key if it's mapped to an empty set + + true //Remove succeeded + } else false //Remove failed + } + } else false //Remove failed + } + + /** + * @return true if the underlying containers is empty, may report false negatives when the last remove is underway + */ + def isEmpty: Boolean = container.isEmpty + + /** + * Removes all keys and all values + */ + def clear = foreach { case (k, v) => remove(k, v) } +} diff --git a/test/disabled/presentation/akka/src/akka/actor/Actors.java b/test/disabled/presentation/akka/src/akka/actor/Actors.java new file mode 100644 index 0000000000..a5ec9f37dc --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/actor/Actors.java @@ -0,0 +1,108 @@ +package akka.actor; + +import akka.japi.Creator; +import akka.remoteinterface.RemoteSupport; + +/** + * JAVA API for + * - creating actors, + * - creating remote actors, + * - locating actors + */ +public class Actors { + /** + * + * @return The actor registry + */ + public static ActorRegistry registry() { + return Actor$.MODULE$.registry(); + } + + /** + * + * @return + * @throws UnsupportedOperationException If remoting isn't configured + * @throws ModuleNotAvailableException If the class for the remote support cannot be loaded + */ + public static RemoteSupport remote() { + return Actor$.MODULE$.remote(); + } + + /** + * NOTE: Use this convenience method with care, do NOT make it possible to get a reference to the + * UntypedActor instance directly, but only through its 'ActorRef' wrapper reference. + *

      + * Creates an ActorRef out of the Actor. Allows you to pass in the instance for the UntypedActor. + * Only use this method when you need to pass in constructor arguments into the 'UntypedActor'. + *

      + * You use it by implementing the UntypedActorFactory interface. + * Example in Java: + *

      +   *   ActorRef actor = Actors.actorOf(new UntypedActorFactory() {
      +   *     public UntypedActor create() {
      +   *       return new MyUntypedActor("service:name", 5);
      +   *     }
      +   *   });
      +   *   actor.start();
      +   *   actor.sendOneWay(message, context);
      +   *   actor.stop();
      +   * 
      + */ + public static ActorRef actorOf(final Creator factory) { + return Actor$.MODULE$.actorOf(factory); + } + + /** + * Creates an ActorRef out of the Actor type represented by the class provided. + * Example in Java: + *
      +   *   ActorRef actor = Actors.actorOf(MyUntypedActor.class);
      +   *   actor.start();
      +   *   actor.sendOneWay(message, context);
      +   *   actor.stop();
      +   * 
      + * You can create and start the actor in one statement like this: + *
      +   *   val actor = Actors.actorOf(MyActor.class).start();
      +   * 
      + */ + public static ActorRef actorOf(final Class type) { + return Actor$.MODULE$.actorOf(type); + } + + /** + * The message that is sent when an Actor gets a receive timeout. + *
      +     *  if( message == receiveTimeout() ) {
      +     *    //Timed out
      +     *  }
      +     * 
      + * @return the single instance of ReceiveTimeout + */ + public final static ReceiveTimeout$ receiveTimeout() { + return ReceiveTimeout$.MODULE$; + } + + /** + * The message that when sent to an Actor kills it by throwing an exception. + *
      +     *  actor.sendOneWay(kill());
      +     * 
      + * @return the single instance of Kill + */ + public final static Kill$ kill() { + return Kill$.MODULE$; + } + + + /** + * The message that when sent to an Actor shuts it down by calling 'stop'. + *
      +     *  actor.sendOneWay(poisonPill());
      +     * 
      + * @return the single instance of PoisonPill + */ + public final static PoisonPill$ poisonPill() { + return PoisonPill$.MODULE$; + } +} diff --git a/test/disabled/presentation/akka/src/akka/actor/BootableActorLoaderService.scala b/test/disabled/presentation/akka/src/akka/actor/BootableActorLoaderService.scala new file mode 100644 index 0000000000..a54fca9ac7 --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/actor/BootableActorLoaderService.scala @@ -0,0 +1,60 @@ +/** + * Copyright (C) 2009-2011 Scalable Solutions AB + */ + +package akka.actor + +import java.io.File +import java.net.{ URL, URLClassLoader } +import java.util.jar.JarFile + +import akka.util.{ Bootable } +import akka.config.Config._ + +/** + * Handles all modules in the deploy directory (load and unload) + */ +trait BootableActorLoaderService extends Bootable { + + val BOOT_CLASSES = config.getList("akka.boot") + lazy val applicationLoader: Option[ClassLoader] = createApplicationClassLoader + + protected def createApplicationClassLoader: Option[ClassLoader] = Some({ + if (HOME.isDefined) { + val DEPLOY = HOME.get + "/deploy" + val DEPLOY_DIR = new File(DEPLOY) + if (!DEPLOY_DIR.exists) { + System.exit(-1) + } + val filesToDeploy = DEPLOY_DIR.listFiles.toArray.toList + .asInstanceOf[List[File]].filter(_.getName.endsWith(".jar")) + var dependencyJars: List[URL] = Nil + filesToDeploy.map { file => + val jarFile = new JarFile(file) + val en = jarFile.entries + while (en.hasMoreElements) { + val name = en.nextElement.getName + if (name.endsWith(".jar")) dependencyJars ::= new File( + String.format("jar:file:%s!/%s", jarFile.getName, name)).toURI.toURL + } + } + val toDeploy = filesToDeploy.map(_.toURI.toURL) + val allJars = toDeploy ::: dependencyJars + + new URLClassLoader(allJars.toArray, Thread.currentThread.getContextClassLoader) + } else Thread.currentThread.getContextClassLoader + }) + + abstract override def onLoad = { + super.onLoad + + for (loader ← applicationLoader; clazz ← BOOT_CLASSES) { + loader.loadClass(clazz).newInstance + } + } + + abstract override def onUnload = { + super.onUnload + Actor.registry.shutdownAll() + } +} diff --git a/test/disabled/presentation/akka/src/akka/actor/FSM.scala b/test/disabled/presentation/akka/src/akka/actor/FSM.scala new file mode 100644 index 0000000000..d9cd9a9ca2 --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/actor/FSM.scala @@ -0,0 +1,527 @@ +/** + * Copyright (C) 2009-2011 Scalable Solutions AB + */ +package akka.actor + +import akka.util._ +import akka.event.EventHandler + +import scala.collection.mutable +import java.util.concurrent.ScheduledFuture + +object FSM { + + object NullFunction extends PartialFunction[Any, Nothing] { + def isDefinedAt(o: Any) = false + def apply(o: Any) = sys.error("undefined") + } + + case class CurrentState[S](fsmRef: ActorRef, state: S) + case class Transition[S](fsmRef: ActorRef, from: S, to: S) + case class SubscribeTransitionCallBack(actorRef: ActorRef) + case class UnsubscribeTransitionCallBack(actorRef: ActorRef) + + sealed trait Reason + case object Normal extends Reason + case object Shutdown extends Reason + case class Failure(cause: Any) extends Reason + + case object StateTimeout + case class TimeoutMarker(generation: Long) + + case class Timer(name: String, msg: AnyRef, repeat: Boolean, generation: Int) { + private var ref: Option[ScheduledFuture[AnyRef]] = _ + + def schedule(actor: ActorRef, timeout: Duration) { + if (repeat) { + ref = Some(Scheduler.schedule(actor, this, timeout.length, timeout.length, timeout.unit)) + } else { + ref = Some(Scheduler.scheduleOnce(actor, this, timeout.length, timeout.unit)) + } + } + + def cancel { + if (ref.isDefined) { + ref.get.cancel(true) + ref = None + } + } + } + + /* + * This extractor is just convenience for matching a (S, S) pair, including a + * reminder what the new state is. + */ + object -> { + def unapply[S](in: (S, S)) = Some(in) + } + + /* + * With these implicits in scope, you can write "5 seconds" anywhere a + * Duration or Option[Duration] is expected. This is conveniently true + * for derived classes. + */ + implicit def d2od(d: Duration): Option[Duration] = Some(d) +} + +/** + * Finite State Machine actor trait. Use as follows: + * + *
      + *   object A {
      + *     trait State
      + *     case class One extends State
      + *     case class Two extends State
      + *
      + *     case class Data(i : Int)
      + *   }
      + *
      + *   class A extends Actor with FSM[A.State, A.Data] {
      + *     import A._
      + *
      + *     startWith(One, Data(42))
      + *     when(One) {
      + *         case Event(SomeMsg, Data(x)) => ...
      + *         case Ev(SomeMsg) => ... // convenience when data not needed
      + *     }
      + *     when(Two, stateTimeout = 5 seconds) { ... }
      + *     initialize
      + *   }
      + * 
      + * + * Within the partial function the following values are returned for effecting + * state transitions: + * + * - stay for staying in the same state + * - stay using Data(...) for staying in the same state, but with + * different data + * - stay forMax 5.millis for staying with a state timeout; can be + * combined with using + * - goto(...) for changing into a different state; also supports + * using and forMax + * - stop for terminating this FSM actor + * + * Each of the above also supports the method replying(AnyRef) for + * sending a reply before changing state. + * + * While changing state, custom handlers may be invoked which are registered + * using onTransition. This is meant to enable concentrating + * different concerns in different places; you may choose to use + * when for describing the properties of a state, including of + * course initiating transitions, but you can describe the transitions using + * onTransition to avoid having to duplicate that code among + * multiple paths which lead to a transition: + * + *
      + * onTransition {
      + *   case Active -> _ => cancelTimer("activeTimer")
      + * }
      + * 
      + * + * Multiple such blocks are supported and all of them will be called, not only + * the first matching one. + * + * Another feature is that other actors may subscribe for transition events by + * sending a SubscribeTransitionCallback message to this actor; + * use UnsubscribeTransitionCallback before stopping the other + * actor. + * + * State timeouts set an upper bound to the time which may pass before another + * message is received in the current state. If no external message is + * available, then upon expiry of the timeout a StateTimeout message is sent. + * Note that this message will only be received in the state for which the + * timeout was set and that any message received will cancel the timeout + * (possibly to be started again by the next transition). + * + * Another feature is the ability to install and cancel single-shot as well as + * repeated timers which arrange for the sending of a user-specified message: + * + *
      + *   setTimer("tock", TockMsg, 1 second, true) // repeating
      + *   setTimer("lifetime", TerminateMsg, 1 hour, false) // single-shot
      + *   cancelTimer("tock")
      + *   timerActive_? ("tock")
      + * 
      + */ +trait FSM[S, D] extends ListenerManagement { + this: Actor => + + import FSM._ + + type StateFunction = scala.PartialFunction[Event[D], State] + type Timeout = Option[Duration] + type TransitionHandler = PartialFunction[(S, S), Unit] + + /** + * **************************************** + * DSL + * **************************************** + */ + + /** + * Insert a new StateFunction at the end of the processing chain for the + * given state. If the stateTimeout parameter is set, entering this state + * without a differing explicit timeout setting will trigger a StateTimeout + * event; the same is true when using #stay. + * + * @param stateName designator for the state + * @param stateTimeout default state timeout for this state + * @param stateFunction partial function describing response to input + */ + protected final def when(stateName: S, stateTimeout: Timeout = None)(stateFunction: StateFunction) = { + register(stateName, stateFunction, stateTimeout) + } + + /** + * Set initial state. Call this method from the constructor before the #initialize method. + * + * @param stateName initial state designator + * @param stateData initial state data + * @param timeout state timeout for the initial state, overriding the default timeout for that state + */ + protected final def startWith(stateName: S, + stateData: D, + timeout: Timeout = None) = { + currentState = State(stateName, stateData, timeout) + } + + /** + * Produce transition to other state. Return this from a state function in + * order to effect the transition. + * + * @param nextStateName state designator for the next state + * @return state transition descriptor + */ + protected final def goto(nextStateName: S): State = { + State(nextStateName, currentState.stateData) + } + + /** + * Produce "empty" transition descriptor. Return this from a state function + * when no state change is to be effected. + * + * @return descriptor for staying in current state + */ + protected final def stay(): State = { + // cannot directly use currentState because of the timeout field + goto(currentState.stateName) + } + + /** + * Produce change descriptor to stop this FSM actor with reason "Normal". + */ + protected final def stop(): State = { + stop(Normal) + } + + /** + * Produce change descriptor to stop this FSM actor including specified reason. + */ + protected final def stop(reason: Reason): State = { + stop(reason, currentState.stateData) + } + + /** + * Produce change descriptor to stop this FSM actor including specified reason. + */ + protected final def stop(reason: Reason, stateData: D): State = { + stay using stateData withStopReason (reason) + } + + /** + * Schedule named timer to deliver message after given delay, possibly repeating. + * @param name identifier to be used with cancelTimer() + * @param msg message to be delivered + * @param timeout delay of first message delivery and between subsequent messages + * @param repeat send once if false, scheduleAtFixedRate if true + * @return current state descriptor + */ + protected final def setTimer(name: String, msg: AnyRef, timeout: Duration, repeat: Boolean): State = { + if (timers contains name) { + timers(name).cancel + } + val timer = Timer(name, msg, repeat, timerGen.next) + timer.schedule(self, timeout) + timers(name) = timer + stay + } + + /** + * Cancel named timer, ensuring that the message is not subsequently delivered (no race). + * @param name of the timer to cancel + */ + protected final def cancelTimer(name: String) = { + if (timers contains name) { + timers(name).cancel + timers -= name + } + } + + /** + * Inquire whether the named timer is still active. Returns true unless the + * timer does not exist, has previously been canceled or if it was a + * single-shot timer whose message was already received. + */ + protected final def timerActive_?(name: String) = timers contains name + + /** + * Set state timeout explicitly. This method can safely be used from within a + * state handler. + */ + protected final def setStateTimeout(state: S, timeout: Timeout) { + stateTimeouts(state) = timeout + } + + /** + * Set handler which is called upon each state transition, i.e. not when + * staying in the same state. This may use the pair extractor defined in the + * FSM companion object like so: + * + *
      +   * onTransition {
      +   *   case Old -> New => doSomething
      +   * }
      +   * 
      + * + * It is also possible to supply a 2-ary function object: + * + *
      +   * onTransition(handler _)
      +   *
      +   * private def handler(from: S, to: S) { ... }
      +   * 
      + * + * The underscore is unfortunately necessary to enable the nicer syntax shown + * above (it uses the implicit conversion total2pf under the hood). + * + * Multiple handlers may be installed, and every one of them will be + * called, not only the first one matching. + */ + protected final def onTransition(transitionHandler: TransitionHandler) { + transitionEvent :+= transitionHandler + } + + /** + * Convenience wrapper for using a total function instead of a partial + * function literal. To be used with onTransition. + */ + implicit protected final def total2pf(transitionHandler: (S, S) => Unit) = + new PartialFunction[(S, S), Unit] { + def isDefinedAt(in: (S, S)) = true + def apply(in: (S, S)) { transitionHandler(in._1, in._2) } + } + + /** + * Set handler which is called upon termination of this FSM actor. + */ + protected final def onTermination(terminationHandler: PartialFunction[StopEvent[S, D], Unit]) = { + terminateEvent = terminationHandler + } + + /** + * Set handler which is called upon reception of unhandled messages. + */ + protected final def whenUnhandled(stateFunction: StateFunction) = { + handleEvent = stateFunction orElse handleEventDefault + } + + /** + * Verify existence of initial state and setup timers. This should be the + * last call within the constructor. + */ + def initialize { + makeTransition(currentState) + } + + /** + * **************************************************************** + * PRIVATE IMPLEMENTATION DETAILS + * **************************************************************** + */ + + /* + * FSM State data and current timeout handling + */ + private var currentState: State = _ + private var timeoutFuture: Option[ScheduledFuture[AnyRef]] = None + private var generation: Long = 0L + + /* + * Timer handling + */ + private val timers = mutable.Map[String, Timer]() + private val timerGen = Iterator from 0 + + /* + * State definitions + */ + private val stateFunctions = mutable.Map[S, StateFunction]() + private val stateTimeouts = mutable.Map[S, Timeout]() + + private def register(name: S, function: StateFunction, timeout: Timeout) { + if (stateFunctions contains name) { + stateFunctions(name) = stateFunctions(name) orElse function + stateTimeouts(name) = timeout orElse stateTimeouts(name) + } else { + stateFunctions(name) = function + stateTimeouts(name) = timeout + } + } + + /* + * unhandled event handler + */ + private val handleEventDefault: StateFunction = { + case Event(value, stateData) => + stay + } + private var handleEvent: StateFunction = handleEventDefault + + /* + * termination handling + */ + private var terminateEvent: PartialFunction[StopEvent[S, D], Unit] = { + case StopEvent(Failure(cause), _, _) => + case StopEvent(reason, _, _) => + } + + /* + * transition handling + */ + private var transitionEvent: List[TransitionHandler] = Nil + private def handleTransition(prev: S, next: S) { + val tuple = (prev, next) + for (te ← transitionEvent) { if (te.isDefinedAt(tuple)) te(tuple) } + } + + // ListenerManagement shall not start() or stop() listener actors + override protected val manageLifeCycleOfListeners = false + + /** + * ******************************************* + * Main actor receive() method + * ******************************************* + */ + override final protected def receive: Receive = { + case TimeoutMarker(gen) => + if (generation == gen) { + processEvent(StateTimeout) + } + case t@Timer(name, msg, repeat, generation) => + if ((timers contains name) && (timers(name).generation == generation)) { + processEvent(msg) + if (!repeat) { + timers -= name + } + } + case SubscribeTransitionCallBack(actorRef) => + addListener(actorRef) + // send current state back as reference point + try { + actorRef ! CurrentState(self, currentState.stateName) + } catch { + case e: ActorInitializationException => + EventHandler.warning(this, "trying to register not running listener") + } + case UnsubscribeTransitionCallBack(actorRef) => + removeListener(actorRef) + case value => { + if (timeoutFuture.isDefined) { + timeoutFuture.get.cancel(true) + timeoutFuture = None + } + generation += 1 + processEvent(value) + } + } + + private def processEvent(value: Any) = { + val event = Event(value, currentState.stateData) + val stateFunc = stateFunctions(currentState.stateName) + val nextState = if (stateFunc isDefinedAt event) { + stateFunc(event) + } else { + // handleEventDefault ensures that this is always defined + handleEvent(event) + } + nextState.stopReason match { + case Some(reason) => terminate(reason) + case None => makeTransition(nextState) + } + } + + private def makeTransition(nextState: State) = { + if (!stateFunctions.contains(nextState.stateName)) { + terminate(Failure("Next state %s does not exist".format(nextState.stateName))) + } else { + if (currentState.stateName != nextState.stateName) { + handleTransition(currentState.stateName, nextState.stateName) + notifyListeners(Transition(self, currentState.stateName, nextState.stateName)) + } + applyState(nextState) + } + } + + private def applyState(nextState: State) = { + currentState = nextState + val timeout = if (currentState.timeout.isDefined) currentState.timeout else stateTimeouts(currentState.stateName) + if (timeout.isDefined) { + val t = timeout.get + if (t.finite_? && t.length >= 0) { + timeoutFuture = Some(Scheduler.scheduleOnce(self, TimeoutMarker(generation), t.length, t.unit)) + } + } + } + + private def terminate(reason: Reason) = { + terminateEvent.apply(StopEvent(reason, currentState.stateName, currentState.stateData)) + self.stop() + } + + case class Event[D](event: Any, stateData: D) + object Ev { + def unapply[D](e: Event[D]): Option[Any] = Some(e.event) + } + + case class State(stateName: S, stateData: D, timeout: Timeout = None) { + + /** + * Modify state transition descriptor to include a state timeout for the + * next state. This timeout overrides any default timeout set for the next + * state. + */ + def forMax(timeout: Duration): State = { + copy(timeout = Some(timeout)) + } + + /** + * Send reply to sender of the current message, if available. + * + * @return this state transition descriptor + */ + def replying(replyValue: Any): State = { + self.sender match { + case Some(sender) => sender ! replyValue + case None => + } + this + } + + /** + * Modify state transition descriptor with new state data. The data will be + * set when transitioning to the new state. + */ + def using(nextStateDate: D): State = { + copy(stateData = nextStateDate) + } + + private[akka] var stopReason: Option[Reason] = None + + private[akka] def withStopReason(reason: Reason): State = { + stopReason = Some(reason) + this + } + } + + case class StopEvent[S, D](reason: Reason, currentState: S, stateData: D) +} diff --git a/test/disabled/presentation/akka/src/akka/actor/Scheduler.scala b/test/disabled/presentation/akka/src/akka/actor/Scheduler.scala new file mode 100644 index 0000000000..128584f3c5 --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/actor/Scheduler.scala @@ -0,0 +1,133 @@ +/* + * Copyright 2007 WorldWide Conferencing, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Rework of David Pollak's ActorPing class in the Lift Project + * which is licensed under the Apache 2 License. + */ +package akka.actor + +import scala.collection.JavaConversions + +import java.util.concurrent._ + +import akka.event.EventHandler +import akka.AkkaException + +object Scheduler { + import Actor._ + + case class SchedulerException(msg: String, e: Throwable) extends RuntimeException(msg, e) + + @volatile + private var service = Executors.newSingleThreadScheduledExecutor(SchedulerThreadFactory) + + /** + * Schedules to send the specified message to the receiver after initialDelay and then repeated after delay + */ + def schedule(receiver: ActorRef, message: AnyRef, initialDelay: Long, delay: Long, timeUnit: TimeUnit): ScheduledFuture[AnyRef] = { + try { + service.scheduleAtFixedRate( + new Runnable { def run = receiver ! message }, + initialDelay, delay, timeUnit).asInstanceOf[ScheduledFuture[AnyRef]] + } catch { + case e: Exception => + val error = SchedulerException(message + " could not be scheduled on " + receiver, e) + EventHandler.error(error, this, "%s @ %s".format(receiver, message)) + throw error + } + } + + /** + * Schedules to run specified function to the receiver after initialDelay and then repeated after delay, + * avoid blocking operations since this is executed in the schedulers thread + */ + def schedule(f: () => Unit, initialDelay: Long, delay: Long, timeUnit: TimeUnit): ScheduledFuture[AnyRef] = + schedule(new Runnable { def run = f() }, initialDelay, delay, timeUnit) + + /** + * Schedules to run specified runnable to the receiver after initialDelay and then repeated after delay, + * avoid blocking operations since this is executed in the schedulers thread + */ + def schedule(runnable: Runnable, initialDelay: Long, delay: Long, timeUnit: TimeUnit): ScheduledFuture[AnyRef] = { + try { + service.scheduleAtFixedRate(runnable, initialDelay, delay, timeUnit).asInstanceOf[ScheduledFuture[AnyRef]] + } catch { + case e: Exception => + val error = SchedulerException("Failed to schedule a Runnable", e) + EventHandler.error(error, this, error.getMessage) + throw error + } + } + + /** + * Schedules to send the specified message to the receiver after delay + */ + def scheduleOnce(receiver: ActorRef, message: AnyRef, delay: Long, timeUnit: TimeUnit): ScheduledFuture[AnyRef] = { + try { + service.schedule( + new Runnable { def run = receiver ! message }, + delay, timeUnit).asInstanceOf[ScheduledFuture[AnyRef]] + } catch { + case e: Exception => + val error = SchedulerException(message + " could not be scheduleOnce'd on " + receiver, e) + EventHandler.error(e, this, receiver + " @ " + message) + throw error + } + } + + /** + * Schedules a function to be run after delay, + * avoid blocking operations since the runnable is executed in the schedulers thread + */ + def scheduleOnce(f: () => Unit, delay: Long, timeUnit: TimeUnit): ScheduledFuture[AnyRef] = + scheduleOnce(new Runnable { def run = f() }, delay, timeUnit) + + /** + * Schedules a runnable to be run after delay, + * avoid blocking operations since the runnable is executed in the schedulers thread + */ + def scheduleOnce(runnable: Runnable, delay: Long, timeUnit: TimeUnit): ScheduledFuture[AnyRef] = { + try { + service.schedule(runnable, delay, timeUnit).asInstanceOf[ScheduledFuture[AnyRef]] + } catch { + case e: Exception => + val error = SchedulerException("Failed to scheduleOnce a Runnable", e) + EventHandler.error(e, this, error.getMessage) + throw error + } + } + + def shutdown() { + synchronized { + service.shutdown() + } + } + + def restart() { + synchronized { + shutdown() + service = Executors.newSingleThreadScheduledExecutor(SchedulerThreadFactory) + } + } +} + +private object SchedulerThreadFactory extends ThreadFactory { + private var count = 0 + val threadFactory = Executors.defaultThreadFactory() + + def newThread(r: Runnable): Thread = { + val thread = threadFactory.newThread(r) + thread.setName("akka:scheduler-" + count) + thread.setDaemon(true) + thread + } +} diff --git a/test/disabled/presentation/akka/src/akka/actor/Supervisor.scala b/test/disabled/presentation/akka/src/akka/actor/Supervisor.scala new file mode 100644 index 0000000000..4a1309faef --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/actor/Supervisor.scala @@ -0,0 +1,176 @@ +/** + * Copyright (C) 2009-2011 Scalable Solutions AB + */ + +package akka.actor + +import akka.AkkaException +import akka.util._ +import ReflectiveAccess._ +import Actor._ + +import java.util.concurrent.{ CopyOnWriteArrayList, ConcurrentHashMap } +import java.net.InetSocketAddress +import akka.config.Supervision._ + +class SupervisorException private[akka] (message: String, cause: Throwable = null) extends AkkaException(message, cause) + +/** + * Factory object for creating supervisors declarative. It creates instances of the 'Supervisor' class. + * These are not actors, if you need a supervisor that is an Actor then you have to use the 'SupervisorActor' + * factory object. + *

      + * + * Here is a sample on how to use it: + *

      + *  val supervisor = Supervisor(
      + *    SupervisorConfig(
      + *      RestartStrategy(OneForOne, 3, 10, List(classOf[Exception]),
      + *      Supervise(
      + *        myFirstActor,
      + *        Permanent) ::
      + *      Supervise(
      + *        mySecondActor,
      + *        Permanent) ::
      + *      Nil))
      + * 
      + * + * You dynamically link and unlink child children using the 'link' and 'unlink' methods. + *
      + * supervisor.link(child)
      + * supervisor.unlink(child)
      + * 
      + * + * @author Jonas Bonér + */ +object Supervisor { + def apply(config: SupervisorConfig): Supervisor = SupervisorFactory(config).newInstance.start +} + +/** + * Use this factory instead of the Supervisor factory object if you want to control + * instantiation and starting of the Supervisor, if not then it is easier and better + * to use the Supervisor factory object. + *

      + * Example usage: + *

      + *  val factory = SupervisorFactory(
      + *    SupervisorConfig(
      + *      RestartStrategy(OneForOne, 3, 10, List(classOf[Exception]),
      + *      Supervise(
      + *        myFirstActor,
      + *        Permanent) ::
      + *      Supervise(
      + *        mySecondActor,
      + *        Permanent) ::
      + *      Nil))
      + * 
      + * + * Then create a new Supervisor tree with the concrete Services we have defined. + * + *
      + * val supervisor = factory.newInstance
      + * supervisor.start // start up all managed servers
      + * 
      + * + * @author Jonas Bonér + */ +case class SupervisorFactory(val config: SupervisorConfig) { + + def newInstance: Supervisor = newInstanceFor(config) + + def newInstanceFor(config: SupervisorConfig): Supervisor = { + val supervisor = new Supervisor(config.restartStrategy, config.maxRestartsHandler) + supervisor.configure(config) + supervisor.start + supervisor + } +} + +/** + * NOTE: + *

      + * The supervisor class is only used for the configuration system when configuring supervisor + * hierarchies declaratively. Should not be used as part of the regular programming API. Instead + * wire the children together using 'link', 'spawnLink' etc. and set the 'trapExit' flag in the + * children that should trap error signals and trigger restart. + *

      + * See the ScalaDoc for the SupervisorFactory for an example on how to declaratively wire up children. + * + * @author Jonas Bonér + */ +sealed class Supervisor(handler: FaultHandlingStrategy, maxRestartsHandler: (ActorRef, MaximumNumberOfRestartsWithinTimeRangeReached) => Unit) { + import Supervisor._ + + private val _childActors = new ConcurrentHashMap[String, List[ActorRef]] + private val _childSupervisors = new CopyOnWriteArrayList[Supervisor] + + private[akka] val supervisor = actorOf(new SupervisorActor(handler, maxRestartsHandler)).start() + + def uuid = supervisor.uuid + + def start: Supervisor = { + this + } + + def shutdown(): Unit = supervisor.stop() + + def link(child: ActorRef) = supervisor.link(child) + + def unlink(child: ActorRef) = supervisor.unlink(child) + + def children: List[ActorRef] = + _childActors.values.toArray.toList.asInstanceOf[List[List[ActorRef]]].flatten + + def childSupervisors: List[Supervisor] = + _childActors.values.toArray.toList.asInstanceOf[List[Supervisor]] + + def configure(config: SupervisorConfig): Unit = config match { + case SupervisorConfig(_, servers, _) => + + servers.map(server => + server match { + case Supervise(actorRef, lifeCycle, registerAsRemoteService) => + actorRef.start() + val className = actorRef.actor.getClass.getName + val currentActors = { + val list = _childActors.get(className) + if (list eq null) List[ActorRef]() + else list + } + _childActors.put(className, actorRef :: currentActors) + actorRef.lifeCycle = lifeCycle + supervisor.link(actorRef) + if (registerAsRemoteService) + Actor.remote.register(actorRef) + case supervisorConfig@SupervisorConfig(_, _, _) => // recursive supervisor configuration + val childSupervisor = Supervisor(supervisorConfig) + supervisor.link(childSupervisor.supervisor) + _childSupervisors.add(childSupervisor) + }) + } +} + +/** + * For internal use only. + * + * @author Jonas Bonér + */ +final class SupervisorActor private[akka] (handler: FaultHandlingStrategy, maxRestartsHandler: (ActorRef, MaximumNumberOfRestartsWithinTimeRangeReached) => Unit) extends Actor { + self.faultHandler = handler + + override def postStop(): Unit = { + val i = self.linkedActors.values.iterator + while (i.hasNext) { + val ref = i.next + ref.stop() + self.unlink(ref) + } + } + + def receive = { + case max@MaximumNumberOfRestartsWithinTimeRangeReached(_, _, _, _) => maxRestartsHandler(self, max) + case unknown => throw new SupervisorException( + "SupervisorActor can not respond to messages.\n\tUnknown message [" + unknown + "]") + } +} diff --git a/test/disabled/presentation/akka/src/akka/actor/UntypedActor.scala b/test/disabled/presentation/akka/src/akka/actor/UntypedActor.scala new file mode 100644 index 0000000000..cbc43f22f8 --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/actor/UntypedActor.scala @@ -0,0 +1,134 @@ +/** + * Copyright (C) 2009-2011 Scalable Solutions AB + */ + +package akka.actor + +import akka.japi.{ Creator, Procedure } + +/** + * Subclass this abstract class to create a MDB-style untyped actor. + *

      + * This class is meant to be used from Java. + *

      + * Here is an example on how to create and use an UntypedActor: + *

      + *  public class SampleUntypedActor extends UntypedActor {
      + *    public void onReceive(Object message) throws Exception {
      + *      if (message instanceof String) {
      + *        String msg = (String)message;
      + *
      + *        if (msg.equals("UseReply")) {
      + *          // Reply to original sender of message using the 'replyUnsafe' method
      + *          getContext().replyUnsafe(msg + ":" + getContext().getUuid());
      + *
      + *        } else if (msg.equals("UseSender") && getContext().getSender().isDefined()) {
      + *          // Reply to original sender of message using the sender reference
      + *          // also passing along my own reference (the context)
      + *          getContext().getSender().get().sendOneWay(msg, context);
      + *
      + *        } else if (msg.equals("UseSenderFuture") && getContext().getSenderFuture().isDefined()) {
      + *          // Reply to original sender of message using the sender future reference
      + *          getContext().getSenderFuture().get().completeWithResult(msg);
      + *
      + *        } else if (msg.equals("SendToSelf")) {
      + *          // Send message to the actor itself recursively
      + *          getContext().sendOneWay(msg)
      + *
      + *        } else if (msg.equals("ForwardMessage")) {
      + *          // Retrieve an actor from the ActorRegistry by ID and get an ActorRef back
      + *          ActorRef actorRef = Actor.registry.actorsFor("some-actor-id").head();
      + *
      + *        } else throw new IllegalArgumentException("Unknown message: " + message);
      + *      } else throw new IllegalArgumentException("Unknown message: " + message);
      + *    }
      + *
      + *    public static void main(String[] args) {
      + *      ActorRef actor = Actors.actorOf(SampleUntypedActor.class);
      + *      actor.start();
      + *      actor.sendOneWay("SendToSelf");
      + *      actor.stop();
      + *    }
      + *  }
      + * 
      + * + * @author Jonas Bonér + */ +abstract class UntypedActor extends Actor { + + /** + * To be implemented by concrete UntypedActor. Defines the message handler. + */ + @throws(classOf[Exception]) + def onReceive(message: Any): Unit + + /** + * Returns the 'self' reference with the API. + */ + def getContext(): ActorRef = self + + /** + * Returns the 'self' reference with the API. + */ + def context(): ActorRef = self + + /** + * Java API for become + */ + def become(behavior: Procedure[Any]): Unit = become(behavior, false) + + /* + * Java API for become with optional discardOld + */ + def become(behavior: Procedure[Any], discardOld: Boolean): Unit = + super.become({ case msg => behavior.apply(msg) }, discardOld) + + /** + * User overridable callback. + *

      + * Is called when an Actor is started by invoking 'actor.start()'. + */ + override def preStart() {} + + /** + * User overridable callback. + *

      + * Is called when 'actor.stop()' is invoked. + */ + override def postStop() {} + + /** + * User overridable callback. + *

      + * Is called on a crashed Actor right BEFORE it is restarted to allow clean up of resources before Actor is terminated. + */ + override def preRestart(reason: Throwable) {} + + /** + * User overridable callback. + *

      + * Is called right AFTER restart on the newly created Actor to allow reinitialization after an Actor crash. + */ + override def postRestart(reason: Throwable) {} + + /** + * User overridable callback. + *

      + * Is called when a message isn't handled by the current behavior of the actor + * by default it throws an UnhandledMessageException + */ + override def unhandled(msg: Any) { + throw new UnhandledMessageException(msg, self) + } + + final protected def receive = { + case msg => onReceive(msg) + } +} + +/** + * Factory closure for an UntypedActor, to be used with 'Actors.actorOf(factory)'. + * + * @author Jonas Bonér + */ +trait UntypedActorFactory extends Creator[Actor] diff --git a/test/disabled/presentation/akka/src/akka/actor/package.scala b/test/disabled/presentation/akka/src/akka/actor/package.scala new file mode 100644 index 0000000000..fbeeed49cb --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/actor/package.scala @@ -0,0 +1,23 @@ +/** + * Copyright (C) 2009-2011 Scalable Solutions AB + */ + +package akka + +import actor.{ ScalaActorRef, ActorRef } + +package object actor { + implicit def actorRef2Scala(ref: ActorRef): ScalaActorRef = + ref.asInstanceOf[ScalaActorRef] + + implicit def scala2ActorRef(ref: ScalaActorRef): ActorRef = + ref.asInstanceOf[ActorRef] + + type Uuid = com.eaio.uuid.UUID + + def newUuid(): Uuid = new Uuid() + + def uuidFrom(time: Long, clockSeqAndNode: Long): Uuid = new Uuid(time, clockSeqAndNode) + + def uuidFrom(uuid: String): Uuid = new Uuid(uuid) +} diff --git a/test/disabled/presentation/akka/src/akka/config/Config.scala b/test/disabled/presentation/akka/src/akka/config/Config.scala new file mode 100644 index 0000000000..6578c66f77 --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/config/Config.scala @@ -0,0 +1,93 @@ +/** + * Copyright (C) 2009-2011 Scalable Solutions AB + */ + +package akka.config + +import akka.AkkaException + +class ConfigurationException(message: String, cause: Throwable = null) extends AkkaException(message, cause) +class ModuleNotAvailableException(message: String, cause: Throwable = null) extends AkkaException(message, cause) + +/** + * Loads up the configuration (from the akka.conf file). + * + * @author Jonas Bonér + */ +object Config { + val VERSION = "1.1.3" + + val HOME = { + val envHome = System.getenv("AKKA_HOME") match { + case null | "" | "." => None + case value => Some(value) + } + + val systemHome = System.getProperty("akka.home") match { + case null | "" => None + case value => Some(value) + } + + envHome orElse systemHome + } + + val config: Configuration = try { + val confName = { + val envConf = System.getenv("AKKA_MODE") match { + case null | "" => None + case value => Some(value) + } + + val systemConf = System.getProperty("akka.mode") match { + case null | "" => None + case value => Some(value) + } + + (envConf orElse systemConf).map("akka." + _ + ".conf").getOrElse("akka.conf") + } + + val newInstance = + if (System.getProperty("akka.config", "") != "") { + val configFile = System.getProperty("akka.config", "") + println("Loading config from -Dakka.config=" + configFile) + Configuration.fromFile(configFile) + } else if (getClass.getClassLoader.getResource(confName) ne null) { + println("Loading config [" + confName + "] from the application classpath.") + Configuration.fromResource(confName, getClass.getClassLoader) + } else if (HOME.isDefined) { + val configFile = HOME.get + "/config/" + confName + println("AKKA_HOME is defined as [" + HOME.get + "], loading config from [" + configFile + "].") + Configuration.fromFile(configFile) + } else { + println( + "\nCan't load '" + confName + "'." + + "\nOne of the three ways of locating the '" + confName + "' file needs to be defined:" + + "\n\t1. Define the '-Dakka.config=...' system property option." + + "\n\t2. Put the '" + confName + "' file on the classpath." + + "\n\t3. Define 'AKKA_HOME' environment variable pointing to the root of the Akka distribution." + + "\nI have no way of finding the '" + confName + "' configuration file." + + "\nUsing default values everywhere.") + Configuration.fromString("akka {}") // default empty config + } + + val configVersion = newInstance.getString("akka.version", VERSION) + if (configVersion != VERSION) + throw new ConfigurationException( + "Akka JAR version [" + VERSION + "] is different than the provided config version [" + configVersion + "]") + + newInstance + } catch { + case e => + System.err.println("Couldn't parse config, fatal error.") + e.printStackTrace(System.err) + System.exit(-1) + throw e + } + + val CONFIG_VERSION = config.getString("akka.version", VERSION) + + val TIME_UNIT = config.getString("akka.time-unit", "seconds") + + val startTime = System.currentTimeMillis + def uptime = (System.currentTimeMillis - startTime) / 1000 +} diff --git a/test/disabled/presentation/akka/src/akka/config/ConfigParser.scala b/test/disabled/presentation/akka/src/akka/config/ConfigParser.scala new file mode 100644 index 0000000000..73fac5e31b --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/config/ConfigParser.scala @@ -0,0 +1,74 @@ +/** + * Copyright (C) 2009-2011 Scalable Solutions AB + * + * Based on Configgy by Robey Pointer. + * Copyright 2009 Robey Pointer + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +package akka.config + +import scala.collection.mutable +import scala.util.parsing.combinator._ + +class ConfigParser(var prefix: String = "", map: mutable.Map[String, Any] = mutable.Map.empty[String, Any], importer: Importer) extends RegexParsers { + val sections = mutable.Stack[String]() + + def createPrefix = { + prefix = if (sections.isEmpty) "" else sections.toList.reverse.mkString("", ".", ".") + } + + override val whiteSpace = """(\s+|#[^\n]*\n)+""".r + + // tokens + + val numberToken: Parser[String] = """-?\d+(\.\d+)?""".r + val stringToken: Parser[String] = ("\"" + """([^\\\"]|\\[^ux]|\\\n|\\u[0-9a-fA-F]{4}|\\x[0-9a-fA-F]{2})*""" + "\"").r + val booleanToken: Parser[String] = "(true|on|false|off)".r + val identToken: Parser[String] = """([\da-zA-Z_][-\w]*)(\.[a-zA-Z_][-\w]*)*""".r + val assignToken: Parser[String] = "=".r + val sectionToken: Parser[String] = """[a-zA-Z][-\w]*""".r + + // values + + def value: Parser[Any] = number | string | list | boolean + def number = numberToken + def string = stringToken ^^ { s => s.substring(1, s.length - 1) } + def list = "[" ~> repsep(string | numberToken, opt(",")) <~ (opt(",") ~ "]") + def boolean = booleanToken + + // parser + + def root = rep(includeFile | assignment | sectionOpen | sectionClose) + + def includeFile = "include" ~> string ^^ { + case filename: String => + new ConfigParser(prefix, map, importer) parse importer.importFile(filename) + } + + def assignment = identToken ~ assignToken ~ value ^^ { + case k ~ a ~ v => map(prefix + k) = v + } + + def sectionOpen = sectionToken <~ "{" ^^ { name => + sections push name + createPrefix + } + + def sectionClose = "}" ^^ { _ => + if (sections.isEmpty) { + failure("dangling close tag") + } else { + sections.pop + createPrefix + } + } + + def parse(in: String): Map[String, Any] = { + parseAll(root, in) match { + case Success(result, _) => map.toMap + case x@Failure(msg, _) => throw new ConfigurationException(x.toString) + case x@Error(msg, _) => throw new ConfigurationException(x.toString) + } + } +} diff --git a/test/disabled/presentation/akka/src/akka/config/Configuration.scala b/test/disabled/presentation/akka/src/akka/config/Configuration.scala new file mode 100644 index 0000000000..81c32fce90 --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/config/Configuration.scala @@ -0,0 +1,166 @@ +/** + * Copyright (C) 2009-2011 Scalable Solutions AB + * + * Based on Configgy by Robey Pointer. + * Copyright 2009 Robey Pointer + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +package akka.config + +import java.io.File + +object Configuration { + val DefaultPath = new File(".").getCanonicalPath + val DefaultImporter = new FilesystemImporter(DefaultPath) + + def load(data: String, importer: Importer = DefaultImporter): Configuration = { + val parser = new ConfigParser(importer = importer) + new Configuration(parser parse data) + } + + def fromFile(filename: String, importer: Importer): Configuration = { + load(importer.importFile(filename), importer) + } + + def fromFile(path: String, filename: String): Configuration = { + val importer = new FilesystemImporter(path) + fromFile(filename, importer) + } + + def fromFile(filename: String): Configuration = { + val n = filename.lastIndexOf('/') + if (n < 0) { + fromFile(DefaultPath, filename) + } else { + fromFile(filename.substring(0, n), filename.substring(n + 1)) + } + } + + def fromResource(filename: String): Configuration = { + fromResource(filename, ClassLoader.getSystemClassLoader) + } + + def fromResource(filename: String, classLoader: ClassLoader): Configuration = { + val importer = new ResourceImporter(classLoader) + fromFile(filename, importer) + } + + def fromMap(map: Map[String, Any]) = { + new Configuration(map) + } + + def fromString(data: String): Configuration = { + load(data) + } +} + +class Configuration(val map: Map[String, Any]) { + private val trueValues = Set("true", "on") + private val falseValues = Set("false", "off") + + def contains(key: String): Boolean = map contains key + + def keys: Iterable[String] = map.keys + + def getAny(key: String): Option[Any] = { + try { + Some(map(key)) + } catch { + case _ => None + } + } + + def getAny(key: String, defaultValue: Any): Any = getAny(key).getOrElse(defaultValue) + + def getSeqAny(key: String): Seq[Any] = { + try { + map(key).asInstanceOf[Seq[Any]] + } catch { + case _ => Seq.empty[Any] + } + } + + def getString(key: String): Option[String] = map.get(key).map(_.toString) + + def getString(key: String, defaultValue: String): String = getString(key).getOrElse(defaultValue) + + def getList(key: String): Seq[String] = { + try { + map(key).asInstanceOf[Seq[String]] + } catch { + case _ => Seq.empty[String] + } + } + + def getInt(key: String): Option[Int] = { + try { + Some(map(key).toString.toInt) + } catch { + case _ => None + } + } + + def getInt(key: String, defaultValue: Int): Int = getInt(key).getOrElse(defaultValue) + + def getLong(key: String): Option[Long] = { + try { + Some(map(key).toString.toLong) + } catch { + case _ => None + } + } + + def getLong(key: String, defaultValue: Long): Long = getLong(key).getOrElse(defaultValue) + + def getFloat(key: String): Option[Float] = { + try { + Some(map(key).toString.toFloat) + } catch { + case _ => None + } + } + + def getFloat(key: String, defaultValue: Float): Float = getFloat(key).getOrElse(defaultValue) + + def getDouble(key: String): Option[Double] = { + try { + Some(map(key).toString.toDouble) + } catch { + case _ => None + } + } + + def getDouble(key: String, defaultValue: Double): Double = getDouble(key).getOrElse(defaultValue) + + def getBoolean(key: String): Option[Boolean] = { + getString(key) flatMap { s => + val isTrue = trueValues.contains(s) + if (!isTrue && !falseValues.contains(s)) None + else Some(isTrue) + } + } + + def getBoolean(key: String, defaultValue: Boolean): Boolean = getBool(key).getOrElse(defaultValue) + + def getBool(key: String): Option[Boolean] = getBoolean(key) + + def getBool(key: String, defaultValue: Boolean): Boolean = getBoolean(key, defaultValue) + + def apply(key: String): String = getString(key) match { + case None => throw new ConfigurationException("undefined config: " + key) + case Some(v) => v + } + + def apply(key: String, defaultValue: String) = getString(key, defaultValue) + def apply(key: String, defaultValue: Int) = getInt(key, defaultValue) + def apply(key: String, defaultValue: Long) = getLong(key, defaultValue) + def apply(key: String, defaultValue: Boolean) = getBool(key, defaultValue) + + def getSection(name: String): Option[Configuration] = { + val l = name.length + 1 + val m = map.collect { case (k, v) if k.startsWith(name) => (k.substring(l), v) } + if (m.isEmpty) None + else Some(new Configuration(m)) + } +} diff --git a/test/disabled/presentation/akka/src/akka/config/Configurator.scala b/test/disabled/presentation/akka/src/akka/config/Configurator.scala new file mode 100644 index 0000000000..2818339b0f --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/config/Configurator.scala @@ -0,0 +1,21 @@ +/** + * Copyright (C) 2009-2011 Scalable Solutions AB + */ + +package akka.config + +import akka.config.Supervision.{ SuperviseTypedActor, FaultHandlingStrategy } + +private[akka] trait TypedActorConfiguratorBase { + def getExternalDependency[T](clazz: Class[T]): T + + def configure(restartStrategy: FaultHandlingStrategy, components: List[SuperviseTypedActor]): TypedActorConfiguratorBase + + def inject: TypedActorConfiguratorBase + + def supervise: TypedActorConfiguratorBase + + def reset + + def stop +} diff --git a/test/disabled/presentation/akka/src/akka/config/Importer.scala b/test/disabled/presentation/akka/src/akka/config/Importer.scala new file mode 100644 index 0000000000..eebda1d4fe --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/config/Importer.scala @@ -0,0 +1,64 @@ +/** + * Copyright (C) 2009-2011 Scalable Solutions AB + * + * Based on Configgy by Robey Pointer. + * Copyright 2009 Robey Pointer + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +package akka.config + +import java.io.{ BufferedReader, File, FileInputStream, InputStream, InputStreamReader } + +/** + * An interface for finding config files and reading them into strings for + * parsing. This is used to handle `include` directives in config files. + */ +trait Importer { + + def importFile(filename: String): String + + private val BUFFER_SIZE = 8192 + + protected def streamToString(in: InputStream): String = { + try { + val reader = new BufferedReader(new InputStreamReader(in, "UTF-8")) + val buffer = new Array[Char](BUFFER_SIZE) + val sb = new StringBuilder + var n = 0 + while (n >= 0) { + n = reader.read(buffer, 0, buffer.length) + if (n >= 0) { + sb.appendAll(buffer, 0, n) + } + } + in.close() + sb.toString + } catch { + case x => throw new ConfigurationException(x.toString) + } + } +} + +/** + * An Importer that looks for imported config files in the filesystem. + * This is the default importer. + */ +class FilesystemImporter(val baseDir: String) extends Importer { + def importFile(filename: String): String = { + val f = new File(filename) + val file = if (f.isAbsolute) f else new File(baseDir, filename) + streamToString(new FileInputStream(file)) + } +} + +/** + * An Importer that looks for imported config files in the java resources + * of the system class loader (usually the jar used to launch this app). + */ +class ResourceImporter(classLoader: ClassLoader) extends Importer { + def importFile(filename: String): String = { + val stream = classLoader.getResourceAsStream(filename) + streamToString(stream) + } +} diff --git a/test/disabled/presentation/akka/src/akka/config/SupervisionConfig.scala b/test/disabled/presentation/akka/src/akka/config/SupervisionConfig.scala new file mode 100644 index 0000000000..40f61f615f --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/config/SupervisionConfig.scala @@ -0,0 +1,134 @@ +/** + * Copyright (C) 2009-2011 Scalable Solutions AB + */ + +package akka.config + +import akka.dispatch.MessageDispatcher +import akka.actor.{ MaximumNumberOfRestartsWithinTimeRangeReached, ActorRef } +import akka.japi.{ Procedure2, Procedure } + +case class RemoteAddress(val hostname: String, val port: Int) + +/** + * Configuration classes - not to be used as messages. + * + * @author Jonas Bonér + */ +object Supervision { + sealed abstract class ConfigElement + + abstract class Server extends ConfigElement + sealed abstract class LifeCycle extends ConfigElement + sealed abstract class FaultHandlingStrategy(val trapExit: List[Class[_ <: Throwable]]) extends ConfigElement + + case class SupervisorConfig(restartStrategy: FaultHandlingStrategy, worker: List[Server], maxRestartsHandler: (ActorRef, MaximumNumberOfRestartsWithinTimeRangeReached) => Unit = { (aRef, max) => () }) extends Server { + //Java API + def this(restartStrategy: FaultHandlingStrategy, worker: Array[Server]) = this(restartStrategy, worker.toList) + def this(restartStrategy: FaultHandlingStrategy, worker: Array[Server], restartHandler: Procedure2[ActorRef, MaximumNumberOfRestartsWithinTimeRangeReached]) = this(restartStrategy, worker.toList, { (aRef, max) => restartHandler.apply(aRef, max) }) + } + + class Supervise(val actorRef: ActorRef, val lifeCycle: LifeCycle, val registerAsRemoteService: Boolean = false) extends Server { + //Java API + def this(actorRef: ActorRef, lifeCycle: LifeCycle) = + this(actorRef, lifeCycle, false) + } + + object Supervise { + def apply(actorRef: ActorRef, lifeCycle: LifeCycle, registerAsRemoteService: Boolean = false) = new Supervise(actorRef, lifeCycle, registerAsRemoteService) + def apply(actorRef: ActorRef, lifeCycle: LifeCycle) = new Supervise(actorRef, lifeCycle, false) + def unapply(supervise: Supervise) = Some((supervise.actorRef, supervise.lifeCycle, supervise.registerAsRemoteService)) + } + + object AllForOneStrategy { + def apply(trapExit: List[Class[_ <: Throwable]], maxNrOfRetries: Int, withinTimeRange: Int): AllForOneStrategy = + new AllForOneStrategy(trapExit, + if (maxNrOfRetries < 0) None else Some(maxNrOfRetries), if (withinTimeRange < 0) None else Some(withinTimeRange)) + } + + case class AllForOneStrategy(override val trapExit: List[Class[_ <: Throwable]], + maxNrOfRetries: Option[Int] = None, + withinTimeRange: Option[Int] = None) extends FaultHandlingStrategy(trapExit) { + def this(trapExit: List[Class[_ <: Throwable]], maxNrOfRetries: Int, withinTimeRange: Int) = + this(trapExit, + if (maxNrOfRetries < 0) None else Some(maxNrOfRetries), if (withinTimeRange < 0) None else Some(withinTimeRange)) + + def this(trapExit: Array[Class[_ <: Throwable]], maxNrOfRetries: Int, withinTimeRange: Int) = + this(trapExit.toList, + if (maxNrOfRetries < 0) None else Some(maxNrOfRetries), if (withinTimeRange < 0) None else Some(withinTimeRange)) + + def this(trapExit: java.util.List[Class[_ <: Throwable]], maxNrOfRetries: Int, withinTimeRange: Int) = + this(trapExit.toArray.toList.asInstanceOf[List[Class[_ <: Throwable]]], + if (maxNrOfRetries < 0) None else Some(maxNrOfRetries), if (withinTimeRange < 0) None else Some(withinTimeRange)) + } + + object OneForOneStrategy { + def apply(trapExit: List[Class[_ <: Throwable]], maxNrOfRetries: Int, withinTimeRange: Int): OneForOneStrategy = + new OneForOneStrategy(trapExit, + if (maxNrOfRetries < 0) None else Some(maxNrOfRetries), if (withinTimeRange < 0) None else Some(withinTimeRange)) + } + + case class OneForOneStrategy(override val trapExit: List[Class[_ <: Throwable]], + maxNrOfRetries: Option[Int] = None, + withinTimeRange: Option[Int] = None) extends FaultHandlingStrategy(trapExit) { + def this(trapExit: List[Class[_ <: Throwable]], maxNrOfRetries: Int, withinTimeRange: Int) = + this(trapExit, + if (maxNrOfRetries < 0) None else Some(maxNrOfRetries), if (withinTimeRange < 0) None else Some(withinTimeRange)) + + def this(trapExit: Array[Class[_ <: Throwable]], maxNrOfRetries: Int, withinTimeRange: Int) = + this(trapExit.toList, + if (maxNrOfRetries < 0) None else Some(maxNrOfRetries), if (withinTimeRange < 0) None else Some(withinTimeRange)) + + def this(trapExit: java.util.List[Class[_ <: Throwable]], maxNrOfRetries: Int, withinTimeRange: Int) = + this(trapExit.toArray.toList.asInstanceOf[List[Class[_ <: Throwable]]], + if (maxNrOfRetries < 0) None else Some(maxNrOfRetries), if (withinTimeRange < 0) None else Some(withinTimeRange)) + } + + case object NoFaultHandlingStrategy extends FaultHandlingStrategy(Nil) + + //Scala API + case object Permanent extends LifeCycle + case object Temporary extends LifeCycle + case object UndefinedLifeCycle extends LifeCycle + + //Java API (& Scala if you fancy) + def permanent(): LifeCycle = Permanent + def temporary(): LifeCycle = Temporary + def undefinedLifeCycle(): LifeCycle = UndefinedLifeCycle + + //Java API + def noFaultHandlingStrategy = NoFaultHandlingStrategy + + case class SuperviseTypedActor(_intf: Class[_], + val target: Class[_], + val lifeCycle: LifeCycle, + val timeout: Long, + _dispatcher: MessageDispatcher, // optional + _remoteAddress: RemoteAddress // optional + ) extends Server { + val intf: Option[Class[_]] = Option(_intf) + val dispatcher: Option[MessageDispatcher] = Option(_dispatcher) + val remoteAddress: Option[RemoteAddress] = Option(_remoteAddress) + + def this(target: Class[_], lifeCycle: LifeCycle, timeout: Long) = + this(null: Class[_], target, lifeCycle, timeout, null: MessageDispatcher, null: RemoteAddress) + + def this(intf: Class[_], target: Class[_], lifeCycle: LifeCycle, timeout: Long) = + this(intf, target, lifeCycle, timeout, null: MessageDispatcher, null: RemoteAddress) + + def this(intf: Class[_], target: Class[_], lifeCycle: LifeCycle, timeout: Long, dispatcher: MessageDispatcher) = + this(intf, target, lifeCycle, timeout, dispatcher, null: RemoteAddress) + + def this(target: Class[_], lifeCycle: LifeCycle, timeout: Long, dispatcher: MessageDispatcher) = + this(null: Class[_], target, lifeCycle, timeout, dispatcher, null: RemoteAddress) + + def this(intf: Class[_], target: Class[_], lifeCycle: LifeCycle, timeout: Long, remoteAddress: RemoteAddress) = + this(intf, target, lifeCycle, timeout, null: MessageDispatcher, remoteAddress) + + def this(target: Class[_], lifeCycle: LifeCycle, timeout: Long, remoteAddress: RemoteAddress) = + this(null: Class[_], target, lifeCycle, timeout, null: MessageDispatcher, remoteAddress) + + def this(target: Class[_], lifeCycle: LifeCycle, timeout: Long, dispatcher: MessageDispatcher, remoteAddress: RemoteAddress) = + this(null: Class[_], target, lifeCycle, timeout, dispatcher, remoteAddress) + } +} diff --git a/test/disabled/presentation/akka/src/akka/dataflow/DataFlow.scala b/test/disabled/presentation/akka/src/akka/dataflow/DataFlow.scala new file mode 100644 index 0000000000..bca7936116 --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/dataflow/DataFlow.scala @@ -0,0 +1,165 @@ +/** + * Copyright (C) 2009-2011 Scalable Solutions AB + */ + +package akka.dataflow + +import java.util.concurrent.atomic.AtomicReference +import java.util.concurrent.{ ConcurrentLinkedQueue, LinkedBlockingQueue } + +import akka.event.EventHandler +import akka.actor.{ Actor, ActorRef } +import akka.actor.Actor._ +import akka.dispatch.CompletableFuture +import akka.AkkaException +import akka.japi.{ Function, Effect } + +/** + * Implements Oz-style dataflow (single assignment) variables. + * + * @author Jonas Bonér + */ +object DataFlow { + object Start + object Exit + + class DataFlowVariableException(message: String, cause: Throwable = null) extends AkkaException(message, cause) + + /** + * Executes the supplied thunk in another thread. + */ + def thread(body: => Unit): Unit = spawn(body) + + /** + * JavaAPI. + * Executes the supplied Effect in another thread. + */ + def thread(body: Effect): Unit = spawn(body.apply) + + /** + * Executes the supplied function in another thread. + */ + def thread[A <: AnyRef, R <: AnyRef](body: A => R) = + actorOf(new ReactiveEventBasedThread(body)).start() + + /** + * JavaAPI. + * Executes the supplied Function in another thread. + */ + def thread[A <: AnyRef, R <: AnyRef](body: Function[A, R]) = + actorOf(new ReactiveEventBasedThread(body.apply)).start() + + private class ReactiveEventBasedThread[A <: AnyRef, T <: AnyRef](body: A => T) + extends Actor { + def receive = { + case Exit => self.stop() + case message => self.reply(body(message.asInstanceOf[A])) + } + } + + private object DataFlowVariable { + private sealed abstract class DataFlowVariableMessage + private case class Set[T <: Any](value: T) extends DataFlowVariableMessage + private object Get extends DataFlowVariableMessage + } + + /** + * @author Jonas Bonér + */ + @deprecated("Superceeded by Future and CompletableFuture as of 1.1", "1.1") + sealed class DataFlowVariable[T <: Any](timeoutMs: Long) { + import DataFlowVariable._ + + def this() = this(1000 * 60) + + private val value = new AtomicReference[Option[T]](None) + private val blockedReaders = new ConcurrentLinkedQueue[ActorRef] + + private class In[T <: Any](dataFlow: DataFlowVariable[T]) extends Actor { + self.timeout = timeoutMs + def receive = { + case s@Set(v) => + if (dataFlow.value.compareAndSet(None, Some(v.asInstanceOf[T]))) { + while (dataFlow.blockedReaders.peek ne null) + dataFlow.blockedReaders.poll ! s + } else throw new DataFlowVariableException( + "Attempt to change data flow variable (from [" + dataFlow.value.get + "] to [" + v + "])") + case Exit => self.stop() + } + } + + private class Out[T <: Any](dataFlow: DataFlowVariable[T]) extends Actor { + self.timeout = timeoutMs + private var readerFuture: Option[CompletableFuture[Any]] = None + def receive = { + case Get => dataFlow.value.get match { + case Some(value) => self reply value + case None => readerFuture = self.senderFuture + } + case Set(v: T) => readerFuture.map(_ completeWithResult v) + case Exit => self.stop() + } + } + + private[this] val in = actorOf(new In(this)).start() + + /** + * Sets the value of this variable (if unset) with the value of the supplied variable. + */ + def <<(ref: DataFlowVariable[T]) { + if (this.value.get.isEmpty) in ! Set(ref()) + else throw new DataFlowVariableException( + "Attempt to change data flow variable (from [" + this.value.get + "] to [" + ref() + "])") + } + + /** + * JavaAPI. + * Sets the value of this variable (if unset) with the value of the supplied variable. + */ + def set(ref: DataFlowVariable[T]) { this << ref } + + /** + * Sets the value of this variable (if unset). + */ + def <<(value: T) { + if (this.value.get.isEmpty) in ! Set(value) + else throw new DataFlowVariableException( + "Attempt to change data flow variable (from [" + this.value.get + "] to [" + value + "])") + } + + /** + * JavaAPI. + * Sets the value of this variable (if unset) with the value of the supplied variable. + */ + def set(value: T) { this << value } + + /** + * Retrieves the value of variable, throws a DataFlowVariableException if it times out. + */ + def get(): T = this() + + /** + * Retrieves the value of variable, throws a DataFlowVariableException if it times out. + */ + def apply(): T = { + value.get getOrElse { + val out = actorOf(new Out(this)).start() + + val result = try { + blockedReaders offer out + (out !! Get).as[T] + } catch { + case e: Exception => + EventHandler.error(e, this, e.getMessage) + out ! Exit + throw e + } + + result.getOrElse(throw new DataFlowVariableException( + "Timed out (after " + timeoutMs + " milliseconds) while waiting for result")) + } + } + + def shutdown() { in ! Exit } + } +} diff --git a/test/disabled/presentation/akka/src/akka/dispatch/Dispatchers.scala b/test/disabled/presentation/akka/src/akka/dispatch/Dispatchers.scala new file mode 100644 index 0000000000..7dd1bf6218 --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/dispatch/Dispatchers.scala @@ -0,0 +1,227 @@ +/** + * Copyright (C) 2009-2011 Scalable Solutions AB + */ + +package akka.dispatch + +import akka.actor.{ Actor, ActorRef } +import akka.actor.newUuid +import akka.config.Config._ +import akka.util.{ Duration, ReflectiveAccess } + +import akka.config.Configuration + +import java.util.concurrent.TimeUnit + +/** + * Scala API. Dispatcher factory. + *

      + * Example usage: + *

      + *   val dispatcher = Dispatchers.newExecutorBasedEventDrivenDispatcher("name")
      + *   dispatcher
      + *     .withNewThreadPoolWithLinkedBlockingQueueWithCapacity(100)
      + *     .setCorePoolSize(16)
      + *     .setMaxPoolSize(128)
      + *     .setKeepAliveTimeInMillis(60000)
      + *     .setRejectionPolicy(new CallerRunsPolicy)
      + *     .build
      + * 
      + *

      + * Java API. Dispatcher factory. + *

      + * Example usage: + *

      + *   MessageDispatcher dispatcher = Dispatchers.newExecutorBasedEventDrivenDispatcher("name");
      + *   dispatcher
      + *     .withNewThreadPoolWithLinkedBlockingQueueWithCapacity(100)
      + *     .setCorePoolSize(16)
      + *     .setMaxPoolSize(128)
      + *     .setKeepAliveTimeInMillis(60000)
      + *     .setRejectionPolicy(new CallerRunsPolicy())
      + *     .build();
      + * 
      + *

      + * + * @author Jonas Bonér + */ +object Dispatchers { + val THROUGHPUT = config.getInt("akka.actor.throughput", 5) + val DEFAULT_SHUTDOWN_TIMEOUT = config.getLong("akka.actor.dispatcher-shutdown-timeout"). + map(time => Duration(time, TIME_UNIT)). + getOrElse(Duration(1000, TimeUnit.MILLISECONDS)) + val MAILBOX_CAPACITY = config.getInt("akka.actor.default-dispatcher.mailbox-capacity", -1) + val MAILBOX_PUSH_TIME_OUT = Duration(config.getInt("akka.actor.default-dispatcher.mailbox-push-timeout-time", 10), TIME_UNIT) + val THROUGHPUT_DEADLINE_TIME = Duration(config.getInt("akka.actor.throughput-deadline-time", -1), TIME_UNIT) + val THROUGHPUT_DEADLINE_TIME_MILLIS = THROUGHPUT_DEADLINE_TIME.toMillis.toInt + val MAILBOX_TYPE: MailboxType = if (MAILBOX_CAPACITY < 1) UnboundedMailbox() else BoundedMailbox() + + lazy val defaultGlobalDispatcher = { + config.getSection("akka.actor.default-dispatcher").flatMap(from).getOrElse(globalExecutorBasedEventDrivenDispatcher) + } + + object globalExecutorBasedEventDrivenDispatcher extends ExecutorBasedEventDrivenDispatcher("global", THROUGHPUT, THROUGHPUT_DEADLINE_TIME_MILLIS, MAILBOX_TYPE) + + /** + * Creates an thread based dispatcher serving a single actor through the same single thread. + * Uses the default timeout + *

      + * E.g. each actor consumes its own thread. + */ + def newThreadBasedDispatcher(actor: ActorRef) = new ThreadBasedDispatcher(actor) + + /** + * Creates an thread based dispatcher serving a single actor through the same single thread. + * Uses the default timeout + * If capacity is negative, it's Integer.MAX_VALUE + *

      + * E.g. each actor consumes its own thread. + */ + def newThreadBasedDispatcher(actor: ActorRef, mailboxCapacity: Int) = new ThreadBasedDispatcher(actor, mailboxCapacity) + + /** + * Creates an thread based dispatcher serving a single actor through the same single thread. + * If capacity is negative, it's Integer.MAX_VALUE + *

      + * E.g. each actor consumes its own thread. + */ + def newThreadBasedDispatcher(actor: ActorRef, mailboxCapacity: Int, pushTimeOut: Duration) = + new ThreadBasedDispatcher(actor, mailboxCapacity, pushTimeOut) + + /** + * Creates a executor-based event-driven dispatcher serving multiple (millions) of actors through a thread pool. + *

      + * Has a fluent builder interface for configuring its semantics. + */ + def newExecutorBasedEventDrivenDispatcher(name: String) = + ThreadPoolConfigDispatcherBuilder(config => new ExecutorBasedEventDrivenDispatcher(name, config), ThreadPoolConfig()) + + /** + * Creates a executor-based event-driven dispatcher serving multiple (millions) of actors through a thread pool. + *

      + * Has a fluent builder interface for configuring its semantics. + */ + def newExecutorBasedEventDrivenDispatcher(name: String, throughput: Int, mailboxType: MailboxType) = + ThreadPoolConfigDispatcherBuilder(config => + new ExecutorBasedEventDrivenDispatcher(name, throughput, THROUGHPUT_DEADLINE_TIME_MILLIS, mailboxType, config), ThreadPoolConfig()) + + /** + * Creates a executor-based event-driven dispatcher serving multiple (millions) of actors through a thread pool. + *

      + * Has a fluent builder interface for configuring its semantics. + */ + def newExecutorBasedEventDrivenDispatcher(name: String, throughput: Int, throughputDeadlineMs: Int, mailboxType: MailboxType) = + ThreadPoolConfigDispatcherBuilder(config => + new ExecutorBasedEventDrivenDispatcher(name, throughput, throughputDeadlineMs, mailboxType, config), ThreadPoolConfig()) + + /** + * Creates a executor-based event-driven dispatcher, with work-stealing, serving multiple (millions) of actors through a thread pool. + *

      + * Has a fluent builder interface for configuring its semantics. + */ + def newExecutorBasedEventDrivenWorkStealingDispatcher(name: String) = + ThreadPoolConfigDispatcherBuilder(config => new ExecutorBasedEventDrivenWorkStealingDispatcher(name, config), ThreadPoolConfig()) + + /** + * Creates a executor-based event-driven dispatcher, with work-stealing, serving multiple (millions) of actors through a thread pool. + *

      + * Has a fluent builder interface for configuring its semantics. + */ + def newExecutorBasedEventDrivenWorkStealingDispatcher(name: String, throughput: Int) = + ThreadPoolConfigDispatcherBuilder(config => + new ExecutorBasedEventDrivenWorkStealingDispatcher(name, throughput, THROUGHPUT_DEADLINE_TIME_MILLIS, MAILBOX_TYPE, config), ThreadPoolConfig()) + + /** + * Creates a executor-based event-driven dispatcher, with work-stealing, serving multiple (millions) of actors through a thread pool. + *

      + * Has a fluent builder interface for configuring its semantics. + */ + def newExecutorBasedEventDrivenWorkStealingDispatcher(name: String, throughput: Int, mailboxType: MailboxType) = + ThreadPoolConfigDispatcherBuilder(config => + new ExecutorBasedEventDrivenWorkStealingDispatcher(name, throughput, THROUGHPUT_DEADLINE_TIME_MILLIS, mailboxType, config), ThreadPoolConfig()) + + /** + * Creates a executor-based event-driven dispatcher, with work-stealing, serving multiple (millions) of actors through a thread pool. + *

      + * Has a fluent builder interface for configuring its semantics. + */ + def newExecutorBasedEventDrivenWorkStealingDispatcher(name: String, throughput: Int, throughputDeadlineMs: Int, mailboxType: MailboxType) = + ThreadPoolConfigDispatcherBuilder(config => + new ExecutorBasedEventDrivenWorkStealingDispatcher(name, throughput, throughputDeadlineMs, mailboxType, config), ThreadPoolConfig()) + /** + * Utility function that tries to load the specified dispatcher config from the akka.conf + * or else use the supplied default dispatcher + */ + def fromConfig(key: String, default: => MessageDispatcher = defaultGlobalDispatcher): MessageDispatcher = + config getSection key flatMap from getOrElse default + + /* + * Creates of obtains a dispatcher from a ConfigMap according to the format below + * + * default-dispatcher { + * type = "GlobalExecutorBasedEventDriven" # Must be one of the following, all "Global*" are non-configurable + * # (ExecutorBasedEventDrivenWorkStealing), ExecutorBasedEventDriven, + * # GlobalExecutorBasedEventDriven + * # A FQCN to a class inheriting MessageDispatcherConfigurator with a no-arg visible constructor + * keep-alive-time = 60 # Keep alive time for threads + * core-pool-size-factor = 1.0 # No of core threads ... ceil(available processors * factor) + * max-pool-size-factor = 4.0 # Max no of threads ... ceil(available processors * factor) + * executor-bounds = -1 # Makes the Executor bounded, -1 is unbounded + * allow-core-timeout = on # Allow core threads to time out + * rejection-policy = "caller-runs" # abort, caller-runs, discard-oldest, discard + * throughput = 5 # Throughput for ExecutorBasedEventDrivenDispatcher + * } + * ex: from(config.getConfigMap(identifier).get) + * + * Gotcha: Only configures the dispatcher if possible + * Returns: None if "type" isn't specified in the config + * Throws: IllegalArgumentException if the value of "type" is not valid + * IllegalArgumentException if it cannot + */ + def from(cfg: Configuration): Option[MessageDispatcher] = { + cfg.getString("type") map { + case "ExecutorBasedEventDriven" => new ExecutorBasedEventDrivenDispatcherConfigurator() + case "ExecutorBasedEventDrivenWorkStealing" => new ExecutorBasedEventDrivenWorkStealingDispatcherConfigurator() + case "GlobalExecutorBasedEventDriven" => GlobalExecutorBasedEventDrivenDispatcherConfigurator + case fqn => + ReflectiveAccess.getClassFor[MessageDispatcherConfigurator](fqn) match { + case r: Right[_, Class[MessageDispatcherConfigurator]] => + ReflectiveAccess.createInstance[MessageDispatcherConfigurator](r.b, Array[Class[_]](), Array[AnyRef]()) match { + case r: Right[Exception, MessageDispatcherConfigurator] => r.b + case l: Left[Exception, MessageDispatcherConfigurator] => + throw new IllegalArgumentException("Cannot instantiate MessageDispatcherConfigurator type [%s], make sure it has a default no-args constructor" format fqn, l.a) + } + case l: Left[Exception, _] => + throw new IllegalArgumentException("Unknown MessageDispatcherConfigurator type [%s]" format fqn, l.a) + } + } map { + _ configure cfg + } + } +} + +object GlobalExecutorBasedEventDrivenDispatcherConfigurator extends MessageDispatcherConfigurator { + def configure(config: Configuration): MessageDispatcher = Dispatchers.globalExecutorBasedEventDrivenDispatcher +} + +class ExecutorBasedEventDrivenDispatcherConfigurator extends MessageDispatcherConfigurator { + def configure(config: Configuration): MessageDispatcher = { + configureThreadPool(config, threadPoolConfig => new ExecutorBasedEventDrivenDispatcher( + config.getString("name", newUuid.toString), + config.getInt("throughput", Dispatchers.THROUGHPUT), + config.getInt("throughput-deadline-time", Dispatchers.THROUGHPUT_DEADLINE_TIME_MILLIS), + mailboxType(config), + threadPoolConfig)).build + } +} + +class ExecutorBasedEventDrivenWorkStealingDispatcherConfigurator extends MessageDispatcherConfigurator { + def configure(config: Configuration): MessageDispatcher = { + configureThreadPool(config, threadPoolConfig => new ExecutorBasedEventDrivenWorkStealingDispatcher( + config.getString("name", newUuid.toString), + config.getInt("throughput", Dispatchers.THROUGHPUT), + config.getInt("throughput-deadline-time", Dispatchers.THROUGHPUT_DEADLINE_TIME_MILLIS), + mailboxType(config), + threadPoolConfig)).build + } +} \ No newline at end of file diff --git a/test/disabled/presentation/akka/src/akka/dispatch/ExecutorBasedEventDrivenDispatcher.scala b/test/disabled/presentation/akka/src/akka/dispatch/ExecutorBasedEventDrivenDispatcher.scala new file mode 100644 index 0000000000..bc3f29ac68 --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/dispatch/ExecutorBasedEventDrivenDispatcher.scala @@ -0,0 +1,305 @@ +/** + * Copyright (C) 2009-2011 Scalable Solutions AB + */ + +package akka.dispatch + +import akka.event.EventHandler +import akka.actor.{ ActorRef, IllegalActorStateException } +import akka.util.{ ReflectiveAccess, Switch } + +import java.util.Queue +import java.util.concurrent.atomic.AtomicReference +import java.util.concurrent.{ TimeUnit, ExecutorService, RejectedExecutionException, ConcurrentLinkedQueue, LinkedBlockingQueue } + +/** + * Default settings are: + *

      + *   - withNewThreadPoolWithLinkedBlockingQueueWithUnboundedCapacity
      + *   - NR_START_THREADS = 16
      + *   - NR_MAX_THREADS = 128
      + *   - KEEP_ALIVE_TIME = 60000L // one minute
      + * 
      + *

      + * + * The dispatcher has a fluent builder interface to build up a thread pool to suite your use-case. + * There is a default thread pool defined but make use of the builder if you need it. Here are some examples. + *

      + * + * Scala API. + *

      + * Example usage: + *

      + *   val dispatcher = new ExecutorBasedEventDrivenDispatcher("name")
      + *   dispatcher
      + *     .withNewThreadPoolWithBoundedBlockingQueue(100)
      + *     .setCorePoolSize(16)
      + *     .setMaxPoolSize(128)
      + *     .setKeepAliveTimeInMillis(60000)
      + *     .setRejectionPolicy(new CallerRunsPolicy)
      + *     .buildThreadPool
      + * 
      + *

      + * + * Java API. + *

      + * Example usage: + *

      + *   ExecutorBasedEventDrivenDispatcher dispatcher = new ExecutorBasedEventDrivenDispatcher("name");
      + *   dispatcher
      + *     .withNewThreadPoolWithBoundedBlockingQueue(100)
      + *     .setCorePoolSize(16)
      + *     .setMaxPoolSize(128)
      + *     .setKeepAliveTimeInMillis(60000)
      + *     .setRejectionPolicy(new CallerRunsPolicy())
      + *     .buildThreadPool();
      + * 
      + *

      + * + * But the preferred way of creating dispatchers is to use + * the {@link akka.dispatch.Dispatchers} factory object. + * + * @author Jonas Bonér + * @param throughput positive integer indicates the dispatcher will only process so much messages at a time from the + * mailbox, without checking the mailboxes of other actors. Zero or negative means the dispatcher + * always continues until the mailbox is empty. + * Larger values (or zero or negative) increase throughput, smaller values increase fairness + */ +class ExecutorBasedEventDrivenDispatcher( + _name: String, + val throughput: Int = Dispatchers.THROUGHPUT, + val throughputDeadlineTime: Int = Dispatchers.THROUGHPUT_DEADLINE_TIME_MILLIS, + val mailboxType: MailboxType = Dispatchers.MAILBOX_TYPE, + val config: ThreadPoolConfig = ThreadPoolConfig()) + extends MessageDispatcher { + + def this(_name: String, throughput: Int, throughputDeadlineTime: Int, mailboxType: MailboxType) = + this(_name, throughput, throughputDeadlineTime, mailboxType, ThreadPoolConfig()) // Needed for Java API usage + + def this(_name: String, throughput: Int, mailboxType: MailboxType) = + this(_name, throughput, Dispatchers.THROUGHPUT_DEADLINE_TIME_MILLIS, mailboxType) // Needed for Java API usage + + def this(_name: String, throughput: Int) = + this(_name, throughput, Dispatchers.THROUGHPUT_DEADLINE_TIME_MILLIS, Dispatchers.MAILBOX_TYPE) // Needed for Java API usage + + def this(_name: String, _config: ThreadPoolConfig) = + this(_name, Dispatchers.THROUGHPUT, Dispatchers.THROUGHPUT_DEADLINE_TIME_MILLIS, Dispatchers.MAILBOX_TYPE, _config) + + def this(_name: String) = + this(_name, Dispatchers.THROUGHPUT, Dispatchers.THROUGHPUT_DEADLINE_TIME_MILLIS, Dispatchers.MAILBOX_TYPE) // Needed for Java API usage + + val name = "akka:event-driven:dispatcher:" + _name + + private[akka] val threadFactory = new MonitorableThreadFactory(name) + private[akka] val executorService = new AtomicReference[ExecutorService](config.createLazyExecutorService(threadFactory)) + + private[akka] def dispatch(invocation: MessageInvocation) = { + val mbox = getMailbox(invocation.receiver) + mbox enqueue invocation + registerForExecution(mbox) + } + + private[akka] def executeFuture(invocation: FutureInvocation[_]): Unit = if (active.isOn) { + try executorService.get() execute invocation + catch { + case e: RejectedExecutionException => + EventHandler.warning(this, e.toString) + throw e + } + } + + /** + * @return the mailbox associated with the actor + */ + protected def getMailbox(receiver: ActorRef) = receiver.mailbox.asInstanceOf[MessageQueue with ExecutableMailbox] + + override def mailboxSize(actorRef: ActorRef) = getMailbox(actorRef).size + + def createMailbox(actorRef: ActorRef): AnyRef = mailboxType match { + case b: UnboundedMailbox => + new ConcurrentLinkedQueue[MessageInvocation] with MessageQueue with ExecutableMailbox { + @inline + final def dispatcher = ExecutorBasedEventDrivenDispatcher.this + @inline + final def enqueue(m: MessageInvocation) = this.add(m) + @inline + final def dequeue(): MessageInvocation = this.poll() + } + case b: BoundedMailbox => + new DefaultBoundedMessageQueue(b.capacity, b.pushTimeOut) with ExecutableMailbox { + @inline + final def dispatcher = ExecutorBasedEventDrivenDispatcher.this + } + } + + private[akka] def start {} + + private[akka] def shutdown { + val old = executorService.getAndSet(config.createLazyExecutorService(threadFactory)) + if (old ne null) { + old.shutdownNow() + } + } + + private[akka] def registerForExecution(mbox: MessageQueue with ExecutableMailbox): Unit = { + if (mbox.dispatcherLock.tryLock()) { + if (active.isOn && !mbox.suspended.locked) { //If the dispatcher is active and the actor not suspended + try { + executorService.get() execute mbox + } catch { + case e: RejectedExecutionException => + EventHandler.warning(this, e.toString) + mbox.dispatcherLock.unlock() + throw e + } + } else { + mbox.dispatcherLock.unlock() //If the dispatcher isn't active or if the actor is suspended, unlock the dispatcher lock + } + } + } + + private[akka] def reRegisterForExecution(mbox: MessageQueue with ExecutableMailbox): Unit = + registerForExecution(mbox) + + override val toString = getClass.getSimpleName + "[" + name + "]" + + def suspend(actorRef: ActorRef) { + getMailbox(actorRef).suspended.tryLock + } + + def resume(actorRef: ActorRef) { + val mbox = getMailbox(actorRef) + mbox.suspended.tryUnlock + reRegisterForExecution(mbox) + } +} + +/** + * This is the behavior of an ExecutorBasedEventDrivenDispatchers mailbox. + */ +trait ExecutableMailbox extends Runnable { self: MessageQueue => + + def dispatcher: ExecutorBasedEventDrivenDispatcher + + final def run = { + try { + processMailbox() + } catch { + case ie: InterruptedException => + } + finally { + dispatcherLock.unlock() + } + if (!self.isEmpty) + dispatcher.reRegisterForExecution(this) + } + + /** + * Process the messages in the mailbox + * + * @return true if the processing finished before the mailbox was empty, due to the throughput constraint + */ + final def processMailbox() { + if (!self.suspended.locked) { + var nextMessage = self.dequeue + if (nextMessage ne null) { //If we have a message + if (dispatcher.throughput <= 1) //If we only run one message per process + nextMessage.invoke //Just run it + else { //But otherwise, if we are throttled, we need to do some book-keeping + var processedMessages = 0 + val isDeadlineEnabled = dispatcher.throughputDeadlineTime > 0 + val deadlineNs = if (isDeadlineEnabled) System.nanoTime + TimeUnit.MILLISECONDS.toNanos(dispatcher.throughputDeadlineTime) + else 0 + do { + nextMessage.invoke + nextMessage = + if (self.suspended.locked) { + null // If we are suspended, abort + } else { // If we aren't suspended, we need to make sure we're not overstepping our boundaries + processedMessages += 1 + if ((processedMessages >= dispatcher.throughput) || (isDeadlineEnabled && System.nanoTime >= deadlineNs)) // If we're throttled, break out + null //We reached our boundaries, abort + else self.dequeue //Dequeue the next message + } + } while (nextMessage ne null) + } + } + } + } +} + +object PriorityGenerator { + /** + * Creates a PriorityGenerator that uses the supplied function as priority generator + */ + def apply(priorityFunction: Any => Int): PriorityGenerator = new PriorityGenerator { + def gen(message: Any): Int = priorityFunction(message) + } +} + +/** + * A PriorityGenerator is a convenience API to create a Comparator that orders the messages of a + * PriorityExecutorBasedEventDrivenDispatcher + */ +abstract class PriorityGenerator extends java.util.Comparator[MessageInvocation] { + def gen(message: Any): Int + + final def compare(thisMessage: MessageInvocation, thatMessage: MessageInvocation): Int = + gen(thisMessage.message) - gen(thatMessage.message) +} + +/** + * A version of ExecutorBasedEventDrivenDispatcher that gives all actors registered to it a priority mailbox, + * prioritized according to the supplied comparator. + * + * The dispatcher will process the messages with the _lowest_ priority first. + */ +class PriorityExecutorBasedEventDrivenDispatcher( + name: String, + val comparator: java.util.Comparator[MessageInvocation], + throughput: Int = Dispatchers.THROUGHPUT, + throughputDeadlineTime: Int = Dispatchers.THROUGHPUT_DEADLINE_TIME_MILLIS, + mailboxType: MailboxType = Dispatchers.MAILBOX_TYPE, + config: ThreadPoolConfig = ThreadPoolConfig()) extends ExecutorBasedEventDrivenDispatcher(name, throughput, throughputDeadlineTime, mailboxType, config) with PriorityMailbox { + + def this(name: String, comparator: java.util.Comparator[MessageInvocation], throughput: Int, throughputDeadlineTime: Int, mailboxType: MailboxType) = + this(name, comparator, throughput, throughputDeadlineTime, mailboxType, ThreadPoolConfig()) // Needed for Java API usage + + def this(name: String, comparator: java.util.Comparator[MessageInvocation], throughput: Int, mailboxType: MailboxType) = + this(name, comparator, throughput, Dispatchers.THROUGHPUT_DEADLINE_TIME_MILLIS, mailboxType) // Needed for Java API usage + + def this(name: String, comparator: java.util.Comparator[MessageInvocation], throughput: Int) = + this(name, comparator, throughput, Dispatchers.THROUGHPUT_DEADLINE_TIME_MILLIS, Dispatchers.MAILBOX_TYPE) // Needed for Java API usage + + def this(name: String, comparator: java.util.Comparator[MessageInvocation], config: ThreadPoolConfig) = + this(name, comparator, Dispatchers.THROUGHPUT, Dispatchers.THROUGHPUT_DEADLINE_TIME_MILLIS, Dispatchers.MAILBOX_TYPE, config) + + def this(name: String, comparator: java.util.Comparator[MessageInvocation]) = + this(name, comparator, Dispatchers.THROUGHPUT, Dispatchers.THROUGHPUT_DEADLINE_TIME_MILLIS, Dispatchers.MAILBOX_TYPE) // Needed for Java API usage +} + +/** + * Can be used to give an ExecutorBasedEventDrivenDispatcher's actors priority-enabled mailboxes + * + * Usage: + * new ExecutorBasedEventDrivenDispatcher(...) with PriorityMailbox { + * val comparator = ...comparator that determines mailbox priority ordering... + * } + */ +trait PriorityMailbox { self: ExecutorBasedEventDrivenDispatcher => + def comparator: java.util.Comparator[MessageInvocation] + + override def createMailbox(actorRef: ActorRef): AnyRef = self.mailboxType match { + case b: UnboundedMailbox => + new UnboundedPriorityMessageQueue(comparator) with ExecutableMailbox { + @inline + final def dispatcher = self + } + + case b: BoundedMailbox => + new BoundedPriorityMessageQueue(b.capacity, b.pushTimeOut, comparator) with ExecutableMailbox { + @inline + final def dispatcher = self + } + } +} diff --git a/test/disabled/presentation/akka/src/akka/dispatch/ExecutorBasedEventDrivenWorkStealingDispatcher.scala b/test/disabled/presentation/akka/src/akka/dispatch/ExecutorBasedEventDrivenWorkStealingDispatcher.scala new file mode 100644 index 0000000000..4cba8eec8b --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/dispatch/ExecutorBasedEventDrivenWorkStealingDispatcher.scala @@ -0,0 +1,165 @@ +/** + * Copyright (C) 2009-2011 Scalable Solutions AB + */ + +package akka.dispatch + +import akka.actor.{ ActorRef, Actor, IllegalActorStateException } +import akka.util.{ ReflectiveAccess, Switch } + +import java.util.Queue +import java.util.concurrent.atomic.{ AtomicReference, AtomicInteger } +import java.util.concurrent.{ TimeUnit, ExecutorService, RejectedExecutionException, ConcurrentLinkedQueue, LinkedBlockingQueue } +import util.DynamicVariable + +/** + * An executor based event driven dispatcher which will try to redistribute work from busy actors to idle actors. It is assumed + * that all actors using the same instance of this dispatcher can process all messages that have been sent to one of the actors. I.e. the + * actors belong to a pool of actors, and to the client there is no guarantee about which actor instance actually processes a given message. + *

      + * Although the technique used in this implementation is commonly known as "work stealing", the actual implementation is probably + * best described as "work donating" because the actor of which work is being stolen takes the initiative. + *

      + * The preferred way of creating dispatchers is to use + * the {@link akka.dispatch.Dispatchers} factory object. + * + * @see akka.dispatch.ExecutorBasedEventDrivenWorkStealingDispatcher + * @see akka.dispatch.Dispatchers + * + * @author Viktor Klang + */ +class ExecutorBasedEventDrivenWorkStealingDispatcher( + _name: String, + throughput: Int = Dispatchers.THROUGHPUT, + throughputDeadlineTime: Int = Dispatchers.THROUGHPUT_DEADLINE_TIME_MILLIS, + mailboxType: MailboxType = Dispatchers.MAILBOX_TYPE, + config: ThreadPoolConfig = ThreadPoolConfig()) + extends ExecutorBasedEventDrivenDispatcher(_name, throughput, throughputDeadlineTime, mailboxType, config) { + + def this(_name: String, throughput: Int, throughputDeadlineTime: Int, mailboxType: MailboxType) = + this(_name, throughput, throughputDeadlineTime, mailboxType, ThreadPoolConfig()) // Needed for Java API usage + + def this(_name: String, throughput: Int, mailboxType: MailboxType) = + this(_name, throughput, Dispatchers.THROUGHPUT_DEADLINE_TIME_MILLIS, mailboxType) // Needed for Java API usage + + def this(_name: String, throughput: Int) = + this(_name, throughput, Dispatchers.THROUGHPUT_DEADLINE_TIME_MILLIS, Dispatchers.MAILBOX_TYPE) // Needed for Java API usage + + def this(_name: String, _config: ThreadPoolConfig) = + this(_name, Dispatchers.THROUGHPUT, Dispatchers.THROUGHPUT_DEADLINE_TIME_MILLIS, Dispatchers.MAILBOX_TYPE, _config) + + def this(_name: String, memberType: Class[_ <: Actor]) = + this(_name, Dispatchers.THROUGHPUT, Dispatchers.THROUGHPUT_DEADLINE_TIME_MILLIS, Dispatchers.MAILBOX_TYPE) // Needed for Java API usage + + def this(_name: String, mailboxType: MailboxType) = + this(_name, Dispatchers.THROUGHPUT, Dispatchers.THROUGHPUT_DEADLINE_TIME_MILLIS, mailboxType) // Needed for Java API usage + + @volatile + private var actorType: Option[Class[_]] = None + @volatile + private var members = Vector[ActorRef]() + private val donationInProgress = new DynamicVariable(false) + + private[akka] override def register(actorRef: ActorRef) = { + //Verify actor type conformity + actorType match { + case None => actorType = Some(actorRef.actor.getClass) + case Some(aType) => + if (aType != actorRef.actor.getClass) + throw new IllegalActorStateException(String.format( + "Can't register actor %s in a work stealing dispatcher which already knows actors of type %s", + actorRef, aType)) + } + + synchronized { members :+= actorRef } //Update members + super.register(actorRef) + } + + private[akka] override def unregister(actorRef: ActorRef) = { + synchronized { members = members.filterNot(actorRef eq) } //Update members + super.unregister(actorRef) + } + + override private[akka] def dispatch(invocation: MessageInvocation) = { + val mbox = getMailbox(invocation.receiver) + if (donationInProgress.value == false && (!mbox.isEmpty || mbox.dispatcherLock.locked) && attemptDonationOf(invocation, mbox)) { + //We were busy and we got to donate the message to some other lucky guy, we're done here + } else { + mbox enqueue invocation + registerForExecution(mbox) + } + } + + override private[akka] def reRegisterForExecution(mbox: MessageQueue with ExecutableMailbox): Unit = { + try { + donationInProgress.value = true + while (donateFrom(mbox)) {} //When we reregister, first donate messages to another actor + } finally { donationInProgress.value = false } + + if (!mbox.isEmpty) //If we still have messages left to process, reschedule for execution + super.reRegisterForExecution(mbox) + } + + /** + * Returns true if it successfully donated a message + */ + protected def donateFrom(donorMbox: MessageQueue with ExecutableMailbox): Boolean = { + val actors = members // copy to prevent concurrent modifications having any impact + + // we risk to pick a thief which is unregistered from the dispatcher in the meantime, but that typically means + // the dispatcher is being shut down... + // Starts at is seeded by current time + doFindDonorRecipient(donorMbox, actors, (System.currentTimeMillis % actors.size).asInstanceOf[Int]) match { + case null => false + case recipient => donate(donorMbox.dequeue, recipient) + } + } + + /** + * Returns true if the donation succeeded or false otherwise + */ + protected def attemptDonationOf(message: MessageInvocation, donorMbox: MessageQueue with ExecutableMailbox): Boolean = try { + donationInProgress.value = true + val actors = members // copy to prevent concurrent modifications having any impact + doFindDonorRecipient(donorMbox, actors, System.identityHashCode(message) % actors.size) match { + case null => false + case recipient => donate(message, recipient) + } + } finally { donationInProgress.value = false } + + /** + * Rewrites the message and adds that message to the recipients mailbox + * returns true if the message is non-null + */ + protected def donate(organ: MessageInvocation, recipient: ActorRef): Boolean = { + if (organ ne null) { + if (organ.senderFuture.isDefined) recipient.postMessageToMailboxAndCreateFutureResultWithTimeout[Any]( + organ.message, recipient.timeout, organ.sender, organ.senderFuture) + else if (organ.sender.isDefined) recipient.postMessageToMailbox(organ.message, organ.sender) + else recipient.postMessageToMailbox(organ.message, None) + true + } else false + } + + /** + * Returns an available recipient for the message, if any + */ + protected def doFindDonorRecipient(donorMbox: MessageQueue with ExecutableMailbox, potentialRecipients: Vector[ActorRef], startIndex: Int): ActorRef = { + val prSz = potentialRecipients.size + var i = 0 + var recipient: ActorRef = null + + while ((i < prSz) && (recipient eq null)) { + val actor = potentialRecipients((i + startIndex) % prSz) //Wrap-around, one full lap + val mbox = getMailbox(actor) + + if ((mbox ne donorMbox) && mbox.isEmpty) { //Don't donate to yourself + recipient = actor //Found! + } + + i += 1 + } + + recipient // nothing found, reuse same start index next time + } +} diff --git a/test/disabled/presentation/akka/src/akka/dispatch/Future.scala b/test/disabled/presentation/akka/src/akka/dispatch/Future.scala new file mode 100644 index 0000000000..1ad304d726 --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/dispatch/Future.scala @@ -0,0 +1,832 @@ +/** + * Copyright (C) 2009-2011 Scalable Solutions AB + */ + +package akka.dispatch + +import akka.AkkaException +import akka.event.EventHandler +import akka.actor.{ Actor, Channel } +import akka.util.Duration +import akka.japi.{ Procedure, Function => JFunc } + +import scala.util.continuations._ + +import java.util.concurrent.locks.ReentrantLock +import java.util.concurrent.{ ConcurrentLinkedQueue, TimeUnit, Callable } +import java.util.concurrent.TimeUnit.{ NANOSECONDS => NANOS, MILLISECONDS => MILLIS } +import java.util.concurrent.atomic.{ AtomicBoolean } +import java.lang.{ Iterable => JIterable } +import java.util.{ LinkedList => JLinkedList } +import scala.collection.mutable.Stack +import annotation.tailrec + +class FutureTimeoutException(message: String, cause: Throwable = null) extends AkkaException(message, cause) + +object Futures { + + /** + * Java API, equivalent to Future.apply + */ + def future[T](body: Callable[T]): Future[T] = + Future(body.call) + + /** + * Java API, equivalent to Future.apply + */ + def future[T](body: Callable[T], timeout: Long): Future[T] = + Future(body.call, timeout) + + /** + * Java API, equivalent to Future.apply + */ + def future[T](body: Callable[T], dispatcher: MessageDispatcher): Future[T] = + Future(body.call)(dispatcher) + + /** + * Java API, equivalent to Future.apply + */ + def future[T](body: Callable[T], timeout: Long, dispatcher: MessageDispatcher): Future[T] = + Future(body.call, timeout)(dispatcher) + + /** + * Returns a Future to the result of the first future in the list that is completed + */ + def firstCompletedOf[T](futures: Iterable[Future[T]], timeout: Long = Long.MaxValue): Future[T] = { + val futureResult = new DefaultCompletableFuture[T](timeout) + + val completeFirst: Future[T] => Unit = _.value.foreach(futureResult complete _) + for (f ← futures) f onComplete completeFirst + + futureResult + } + + /** + * Java API. + * Returns a Future to the result of the first future in the list that is completed + */ + def firstCompletedOf[T <: AnyRef](futures: java.lang.Iterable[Future[T]], timeout: Long): Future[T] = + firstCompletedOf(scala.collection.JavaConversions.iterableAsScalaIterable(futures), timeout) + + /** + * A non-blocking fold over the specified futures. + * The fold is performed on the thread where the last future is completed, + * the result will be the first failure of any of the futures, or any failure in the actual fold, + * or the result of the fold. + * Example: + *

      +   *   val result = Futures.fold(0)(futures)(_ + _).await.result
      +   * 
      + */ + def fold[T, R](zero: R, timeout: Long = Actor.TIMEOUT)(futures: Iterable[Future[T]])(foldFun: (R, T) => R): Future[R] = { + if (futures.isEmpty) { + new AlreadyCompletedFuture[R](Right(zero)) + } else { + val result = new DefaultCompletableFuture[R](timeout) + val results = new ConcurrentLinkedQueue[T]() + val allDone = futures.size + + val aggregate: Future[T] => Unit = f => if (!result.isCompleted) { //TODO: This is an optimization, is it premature? + f.value.get match { + case r: Right[Throwable, T] => + results add r.b + if (results.size == allDone) { //Only one thread can get here + try { + result completeWithResult scala.collection.JavaConversions.collectionAsScalaIterable(results).foldLeft(zero)(foldFun) + } catch { + case e: Exception => + EventHandler.error(e, this, e.getMessage) + result completeWithException e + } + finally { + results.clear + } + } + case l: Left[Throwable, T] => + result completeWithException l.a + results.clear + } + } + + futures foreach { _ onComplete aggregate } + result + } + } + + /** + * Java API + * A non-blocking fold over the specified futures. + * The fold is performed on the thread where the last future is completed, + * the result will be the first failure of any of the futures, or any failure in the actual fold, + * or the result of the fold. + */ + def fold[T <: AnyRef, R <: AnyRef](zero: R, timeout: Long, futures: java.lang.Iterable[Future[T]], fun: akka.japi.Function2[R, T, R]): Future[R] = + fold(zero, timeout)(scala.collection.JavaConversions.iterableAsScalaIterable(futures))(fun.apply _) + + /** + * Initiates a fold over the supplied futures where the fold-zero is the result value of the Future that's completed first + * Example: + *
      +   *   val result = Futures.reduce(futures)(_ + _).await.result
      +   * 
      + */ + def reduce[T, R >: T](futures: Iterable[Future[T]], timeout: Long = Actor.TIMEOUT)(op: (R, T) => T): Future[R] = { + if (futures.isEmpty) + new AlreadyCompletedFuture[R](Left(new UnsupportedOperationException("empty reduce left"))) + else { + val result = new DefaultCompletableFuture[R](timeout) + val seedFound = new AtomicBoolean(false) + val seedFold: Future[T] => Unit = f => { + if (seedFound.compareAndSet(false, true)) { //Only the first completed should trigger the fold + f.value.get match { + case r: Right[Throwable, T] => + result.completeWith(fold(r.b, timeout)(futures.filterNot(_ eq f))(op)) + case l: Left[Throwable, T] => + result.completeWithException(l.a) + } + } + } + for (f ← futures) f onComplete seedFold //Attach the listener to the Futures + result + } + } + + /** + * Java API. + * Initiates a fold over the supplied futures where the fold-zero is the result value of the Future that's completed first + */ + def reduce[T <: AnyRef, R >: T](futures: java.lang.Iterable[Future[T]], timeout: Long, fun: akka.japi.Function2[R, T, T]): Future[R] = + reduce(scala.collection.JavaConversions.iterableAsScalaIterable(futures), timeout)(fun.apply _) + + /** + * Java API. + * Simple version of Futures.traverse. Transforms a java.lang.Iterable[Future[A]] into a Future[java.util.LinkedList[A]]. + * Useful for reducing many Futures into a single Future. + */ + def sequence[A](in: JIterable[Future[A]], timeout: Long): Future[JLinkedList[A]] = + scala.collection.JavaConversions.iterableAsScalaIterable(in).foldLeft(Future(new JLinkedList[A]()))((fr, fa) => + for (r ← fr; a ← fa) yield { + r add a + r + }) + + /** + * Java API. + * Simple version of Futures.traverse. Transforms a java.lang.Iterable[Future[A]] into a Future[java.util.LinkedList[A]]. + * Useful for reducing many Futures into a single Future. + */ + def sequence[A](in: JIterable[Future[A]]): Future[JLinkedList[A]] = sequence(in, Actor.TIMEOUT) + + /** + * Java API. + * Transforms a java.lang.Iterable[A] into a Future[java.util.LinkedList[B]] using the provided Function A => Future[B]. + * This is useful for performing a parallel map. For example, to apply a function to all items of a list + * in parallel. + */ + def traverse[A, B](in: JIterable[A], timeout: Long, fn: JFunc[A, Future[B]]): Future[JLinkedList[B]] = + scala.collection.JavaConversions.iterableAsScalaIterable(in).foldLeft(Future(new JLinkedList[B]())) { (fr, a) => + val fb = fn(a) + for (r ← fr; b ← fb) yield { + r add b + r + } + } + + /** + * Java API. + * Transforms a java.lang.Iterable[A] into a Future[java.util.LinkedList[B]] using the provided Function A => Future[B]. + * This is useful for performing a parallel map. For example, to apply a function to all items of a list + * in parallel. + */ + def traverse[A, B](in: JIterable[A], fn: JFunc[A, Future[B]]): Future[JLinkedList[B]] = traverse(in, Actor.TIMEOUT, fn) + + // ===================================== + // Deprecations + // ===================================== + + /** + * (Blocking!) + */ + @deprecated("Will be removed after 1.1, if you must block, use: futures.foreach(_.await)", "1.1") + def awaitAll(futures: List[Future[_]]): Unit = futures.foreach(_.await) + + /** + * Returns the First Future that is completed (blocking!) + */ + @deprecated("Will be removed after 1.1, if you must block, use: firstCompletedOf(futures).await", "1.1") + def awaitOne(futures: List[Future[_]], timeout: Long = Long.MaxValue): Future[_] = firstCompletedOf[Any](futures, timeout).await + + /** + * Applies the supplied function to the specified collection of Futures after awaiting each future to be completed + */ + @deprecated("Will be removed after 1.1, if you must block, use: futures map { f => fun(f.await) }", "1.1") + def awaitMap[A, B](in: Traversable[Future[A]])(fun: (Future[A]) => B): Traversable[B] = + in map { f => fun(f.await) } + + /** + * Returns Future.resultOrException of the first completed of the 2 Futures provided (blocking!) + */ + @deprecated("Will be removed after 1.1, if you must block, use: firstCompletedOf(List(f1,f2)).await.resultOrException", "1.1") + def awaitEither[T](f1: Future[T], f2: Future[T]): Option[T] = firstCompletedOf[T](List(f1, f2)).await.resultOrException +} + +object Future { + /** + * This method constructs and returns a Future that will eventually hold the result of the execution of the supplied body + * The execution is performed by the specified Dispatcher. + */ + def apply[T](body: => T, timeout: Long = Actor.TIMEOUT)(implicit dispatcher: MessageDispatcher): Future[T] = + dispatcher.dispatchFuture(() => body, timeout) + + /** + * Construct a completable channel + */ + def channel(timeout: Long = Actor.TIMEOUT) = new Channel[Any] { + val future = empty[Any](timeout) + def !(msg: Any) = future completeWithResult msg + } + + /** + * Create an empty Future with default timeout + */ + def empty[T](timeout: Long = Actor.TIMEOUT) = new DefaultCompletableFuture[T](timeout) + + import scala.collection.mutable.Builder + import scala.collection.generic.CanBuildFrom + + /** + * Simple version of Futures.traverse. Transforms a Traversable[Future[A]] into a Future[Traversable[A]]. + * Useful for reducing many Futures into a single Future. + */ + def sequence[A, M[_] <: Traversable[_]](in: M[Future[A]], timeout: Long = Actor.TIMEOUT)(implicit cbf: CanBuildFrom[M[Future[A]], A, M[A]]): Future[M[A]] = + in.foldLeft(new DefaultCompletableFuture[Builder[A, M[A]]](timeout).completeWithResult(cbf(in)): Future[Builder[A, M[A]]])((fr, fa) => for (r ← fr; a ← fa.asInstanceOf[Future[A]]) yield (r += a)).map(_.result) + + /** + * Transforms a Traversable[A] into a Future[Traversable[B]] using the provided Function A => Future[B]. + * This is useful for performing a parallel map. For example, to apply a function to all items of a list + * in parallel: + *
      +   * val myFutureList = Futures.traverse(myList)(x => Future(myFunc(x)))
      +   * 
      + */ + def traverse[A, B, M[_] <: Traversable[_]](in: M[A], timeout: Long = Actor.TIMEOUT)(fn: A => Future[B])(implicit cbf: CanBuildFrom[M[A], B, M[B]]): Future[M[B]] = + in.foldLeft(new DefaultCompletableFuture[Builder[B, M[B]]](timeout).completeWithResult(cbf(in)): Future[Builder[B, M[B]]]) { (fr, a) => + val fb = fn(a.asInstanceOf[A]) + for (r ← fr; b ← fb) yield (r += b) + }.map(_.result) + + /** + * Captures a block that will be transformed into 'Continuation Passing Style' using Scala's Delimited + * Continuations plugin. + * + * Within the block, the result of a Future may be accessed by calling Future.apply. At that point + * execution is suspended with the rest of the block being stored in a continuation until the result + * of the Future is available. If an Exception is thrown while processing, it will be contained + * within the resulting Future. + * + * This allows working with Futures in an imperative style without blocking for each result. + * + * Completing a Future using 'CompletableFuture << Future' will also suspend execution until the + * value of the other Future is available. + * + * The Delimited Continuations compiler plugin must be enabled in order to use this method. + */ + def flow[A](body: => A @cps[Future[Any]], timeout: Long = Actor.TIMEOUT): Future[A] = { + val future = Promise[A](timeout) + (reset(future.asInstanceOf[CompletableFuture[Any]].completeWithResult(body)): Future[Any]) onComplete { f => + val opte = f.exception + if (opte.isDefined) future completeWithException (opte.get) + } + future + } + + private[akka] val callbacksPendingExecution = new ThreadLocal[Option[Stack[() => Unit]]]() { + override def initialValue = None + } +} + +sealed trait Future[+T] { + + /** + * For use only within a Future.flow block or another compatible Delimited Continuations reset block. + * + * Returns the result of this Future without blocking, by suspending execution and storing it as a + * continuation until the result is available. + * + * If this Future is untyped (a Future[Nothing]), a type parameter must be explicitly provided or + * execution will fail. The normal result of getting a Future from an ActorRef using !!! will return + * an untyped Future. + */ + def apply[A >: T](): A @cps[Future[Any]] = shift(this flatMap (_: A => Future[Any])) + + /** + * Blocks awaiting completion of this Future, then returns the resulting value, + * or throws the completed exception + * + * Scala & Java API + * + * throws FutureTimeoutException if this Future times out when waiting for completion + */ + def get: T = this.await.resultOrException.get + + /** + * Blocks the current thread until the Future has been completed or the + * timeout has expired. In the case of the timeout expiring a + * FutureTimeoutException will be thrown. + */ + def await: Future[T] + + /** + * Blocks the current thread until the Future has been completed or the + * timeout has expired. The timeout will be the least value of 'atMost' and the timeout + * supplied at the constructuion of this Future. + * In the case of the timeout expiring a FutureTimeoutException will be thrown. + */ + def await(atMost: Duration): Future[T] + + /** + * Blocks the current thread until the Future has been completed. Use + * caution with this method as it ignores the timeout and will block + * indefinitely if the Future is never completed. + */ + @deprecated("Will be removed after 1.1, it's dangerous and can cause deadlocks, agony and insanity.", "1.1") + def awaitBlocking: Future[T] + + /** + * Tests whether this Future has been completed. + */ + final def isCompleted: Boolean = value.isDefined + + /** + * Tests whether this Future's timeout has expired. + * + * Note that an expired Future may still contain a value, or it may be + * completed with a value. + */ + def isExpired: Boolean + + /** + * This Future's timeout in nanoseconds. + */ + def timeoutInNanos: Long + + /** + * The contained value of this Future. Before this Future is completed + * the value will be None. After completion the value will be Some(Right(t)) + * if it contains a valid result, or Some(Left(error)) if it contains + * an exception. + */ + def value: Option[Either[Throwable, T]] + + /** + * Returns the successful result of this Future if it exists. + */ + final def result: Option[T] = { + val v = value + if (v.isDefined) v.get.right.toOption + else None + } + + /** + * Returns the contained exception of this Future if it exists. + */ + final def exception: Option[Throwable] = { + val v = value + if (v.isDefined) v.get.left.toOption + else None + } + + /** + * When this Future is completed, apply the provided function to the + * Future. If the Future has already been completed, this will apply + * immediately. + */ + def onComplete(func: Future[T] => Unit): Future[T] + + /** + * When the future is completed with a valid result, apply the provided + * PartialFunction to the result. + *
      +   *   val result = future receive {
      +   *     case Foo => "foo"
      +   *     case Bar => "bar"
      +   *   }.await.result
      +   * 
      + */ + final def receive(pf: PartialFunction[Any, Unit]): Future[T] = onComplete { f => + val optr = f.result + if (optr.isDefined) { + val r = optr.get + if (pf.isDefinedAt(r)) pf(r) + } + } + + /** + * Creates a new Future by applying a PartialFunction to the successful + * result of this Future if a match is found, or else return a MatchError. + * If this Future is completed with an exception then the new Future will + * also contain this exception. + * Example: + *
      +   * val future1 = for {
      +   *   a <- actor !!! Req("Hello") collect { case Res(x: Int)    => x }
      +   *   b <- actor !!! Req(a)       collect { case Res(x: String) => x }
      +   *   c <- actor !!! Req(7)       collect { case Res(x: String) => x }
      +   * } yield b + "-" + c
      +   * 
      + */ + final def collect[A](pf: PartialFunction[Any, A]): Future[A] = { + val fa = new DefaultCompletableFuture[A](timeoutInNanos, NANOS) + onComplete { ft => + val v = ft.value.get + fa complete { + if (v.isLeft) v.asInstanceOf[Either[Throwable, A]] + else { + try { + val r = v.right.get + if (pf isDefinedAt r) Right(pf(r)) + else Left(new MatchError(r)) + } catch { + case e: Exception => + EventHandler.error(e, this, e.getMessage) + Left(e) + } + } + } + } + fa + } + + /** + * Creates a new Future that will handle any matching Throwable that this + * Future might contain. If there is no match, or if this Future contains + * a valid result then the new Future will contain the same. + * Example: + *
      +   * Future(6 / 0) failure { case e: ArithmeticException => 0 } // result: 0
      +   * Future(6 / 0) failure { case e: NotFoundException   => 0 } // result: exception
      +   * Future(6 / 2) failure { case e: ArithmeticException => 0 } // result: 3
      +   * 
      + */ + final def failure[A >: T](pf: PartialFunction[Throwable, A]): Future[A] = { + val fa = new DefaultCompletableFuture[A](timeoutInNanos, NANOS) + onComplete { ft => + val opte = ft.exception + fa complete { + if (opte.isDefined) { + val e = opte.get + try { + if (pf isDefinedAt e) Right(pf(e)) + else Left(e) + } catch { + case x: Exception => Left(x) + } + } else ft.value.get + } + } + fa + } + + /** + * Creates a new Future by applying a function to the successful result of + * this Future. If this Future is completed with an exception then the new + * Future will also contain this exception. + * Example: + *
      +   * val future1 = for {
      +   *   a: Int    <- actor !!! "Hello" // returns 5
      +   *   b: String <- actor !!! a       // returns "10"
      +   *   c: String <- actor !!! 7       // returns "14"
      +   * } yield b + "-" + c
      +   * 
      + */ + final def map[A](f: T => A): Future[A] = { + val fa = new DefaultCompletableFuture[A](timeoutInNanos, NANOS) + onComplete { ft => + val optv = ft.value + if (optv.isDefined) { + val v = optv.get + if (v.isLeft) + fa complete v.asInstanceOf[Either[Throwable, A]] + else { + fa complete (try { + Right(f(v.right.get)) + } catch { + case e: Exception => + EventHandler.error(e, this, e.getMessage) + Left(e) + }) + } + } + } + fa + } + + /** + * Creates a new Future by applying a function to the successful result of + * this Future, and returns the result of the function as the new Future. + * If this Future is completed with an exception then the new Future will + * also contain this exception. + * Example: + *
      +   * val future1 = for {
      +   *   a: Int    <- actor !!! "Hello" // returns 5
      +   *   b: String <- actor !!! a       // returns "10"
      +   *   c: String <- actor !!! 7       // returns "14"
      +   * } yield b + "-" + c
      +   * 
      + */ + final def flatMap[A](f: T => Future[A]): Future[A] = { + val fa = new DefaultCompletableFuture[A](timeoutInNanos, NANOS) + onComplete { ft => + val optv = ft.value + if (optv.isDefined) { + val v = optv.get + if (v.isLeft) + fa complete v.asInstanceOf[Either[Throwable, A]] + else { + try { + fa.completeWith(f(v.right.get)) + } catch { + case e: Exception => + EventHandler.error(e, this, e.getMessage) + fa completeWithException e + } + } + } + } + fa + } + + final def foreach(f: T => Unit): Unit = onComplete { ft => + val optr = ft.result + if (optr.isDefined) + f(optr.get) + } + + final def filter(p: Any => Boolean): Future[Any] = { + val f = new DefaultCompletableFuture[T](timeoutInNanos, NANOS) + onComplete { ft => + val optv = ft.value + if (optv.isDefined) { + val v = optv.get + if (v.isLeft) + f complete v + else { + val r = v.right.get + f complete (try { + if (p(r)) Right(r) + else Left(new MatchError(r)) + } catch { + case e: Exception => + EventHandler.error(e, this, e.getMessage) + Left(e) + }) + } + } + } + f + } + + /** + * Returns the current result, throws the exception is one has been raised, else returns None + */ + final def resultOrException: Option[T] = { + val v = value + if (v.isDefined) { + val r = v.get + if (r.isLeft) throw r.left.get + else r.right.toOption + } else None + } + + /* Java API */ + final def onComplete[A >: T](proc: Procedure[Future[A]]): Future[T] = onComplete(proc(_)) + + final def map[A >: T, B](f: JFunc[A, B]): Future[B] = map(f(_)) + + final def flatMap[A >: T, B](f: JFunc[A, Future[B]]): Future[B] = flatMap(f(_)) + + final def foreach[A >: T](proc: Procedure[A]): Unit = foreach(proc(_)) + + final def filter(p: JFunc[Any, Boolean]): Future[Any] = filter(p(_)) + +} + +object Promise { + + def apply[A](timeout: Long): CompletableFuture[A] = new DefaultCompletableFuture[A](timeout) + + def apply[A](): CompletableFuture[A] = apply(Actor.TIMEOUT) + +} + +/** + * Essentially this is the Promise (or write-side) of a Future (read-side). + */ +trait CompletableFuture[T] extends Future[T] { + /** + * Completes this Future with the specified result, if not already completed. + * @return this + */ + def complete(value: Either[Throwable, T]): Future[T] + + /** + * Completes this Future with the specified result, if not already completed. + * @return this + */ + final def completeWithResult(result: T): Future[T] = complete(Right(result)) + + /** + * Completes this Future with the specified exception, if not already completed. + * @return this + */ + final def completeWithException(exception: Throwable): Future[T] = complete(Left(exception)) + + /** + * Completes this Future with the specified other Future, when that Future is completed, + * unless this Future has already been completed. + * @return this. + */ + final def completeWith(other: Future[T]): Future[T] = { + other onComplete { f => complete(f.value.get) } + this + } + + final def <<(value: T): Future[T] @cps[Future[Any]] = shift { cont: (Future[T] => Future[Any]) => cont(complete(Right(value))) } + + final def <<(other: Future[T]): Future[T] @cps[Future[Any]] = shift { cont: (Future[T] => Future[Any]) => + val fr = new DefaultCompletableFuture[Any](Actor.TIMEOUT) + this completeWith other onComplete { f => + try { + fr completeWith cont(f) + } catch { + case e: Exception => + EventHandler.error(e, this, e.getMessage) + fr completeWithException e + } + } + fr + } + +} + +/** + * The default concrete Future implementation. + */ +class DefaultCompletableFuture[T](timeout: Long, timeunit: TimeUnit) extends CompletableFuture[T] { + + def this() = this(0, MILLIS) + + def this(timeout: Long) = this(timeout, MILLIS) + + val timeoutInNanos = timeunit.toNanos(timeout) + private val _startTimeInNanos = currentTimeInNanos + private val _lock = new ReentrantLock + private val _signal = _lock.newCondition + private var _value: Option[Either[Throwable, T]] = None + private var _listeners: List[Future[T] => Unit] = Nil + + /** + * Must be called inside _lock.lock<->_lock.unlock + */ + @tailrec + private def awaitUnsafe(waitTimeNanos: Long): Boolean = { + if (_value.isEmpty && waitTimeNanos > 0) { + val start = currentTimeInNanos + val remainingNanos = try { + _signal.awaitNanos(waitTimeNanos) + } catch { + case e: InterruptedException => + waitTimeNanos - (currentTimeInNanos - start) + } + awaitUnsafe(remainingNanos) + } else { + _value.isDefined + } + } + + def await(atMost: Duration) = { + _lock.lock + if (try { awaitUnsafe(atMost.toNanos min timeLeft()) } finally { _lock.unlock }) this + else throw new FutureTimeoutException("Futures timed out after [" + NANOS.toMillis(timeoutInNanos) + "] milliseconds") + } + + def await = { + _lock.lock + if (try { awaitUnsafe(timeLeft()) } finally { _lock.unlock }) this + else throw new FutureTimeoutException("Futures timed out after [" + NANOS.toMillis(timeoutInNanos) + "] milliseconds") + } + + def awaitBlocking = { + _lock.lock + try { + while (_value.isEmpty) { + _signal.await + } + this + } finally { + _lock.unlock + } + } + + def isExpired: Boolean = timeLeft() <= 0 + + def value: Option[Either[Throwable, T]] = { + _lock.lock + try { + _value + } finally { + _lock.unlock + } + } + + def complete(value: Either[Throwable, T]): DefaultCompletableFuture[T] = { + _lock.lock + val notifyTheseListeners = try { + if (_value.isEmpty && !isExpired) { //Only complete if we aren't expired + _value = Some(value) + val existingListeners = _listeners + _listeners = Nil + existingListeners + } else Nil + } finally { + _signal.signalAll + _lock.unlock + } + + if (notifyTheseListeners.nonEmpty) { // Steps to ensure we don't run into a stack-overflow situation + @tailrec + def runCallbacks(rest: List[Future[T] => Unit], callbacks: Stack[() => Unit]) { + if (rest.nonEmpty) { + notifyCompleted(rest.head) + while (callbacks.nonEmpty) { callbacks.pop().apply() } + runCallbacks(rest.tail, callbacks) + } + } + + val pending = Future.callbacksPendingExecution.get + if (pending.isDefined) { //Instead of nesting the calls to the callbacks (leading to stack overflow) + pending.get.push(() => { // Linearize/aggregate callbacks at top level and then execute + val doNotify = notifyCompleted _ //Hoist closure to avoid garbage + notifyTheseListeners foreach doNotify + }) + } else { + try { + val callbacks = Stack[() => Unit]() // Allocate new aggregator for pending callbacks + Future.callbacksPendingExecution.set(Some(callbacks)) // Specify the callback aggregator + runCallbacks(notifyTheseListeners, callbacks) // Execute callbacks, if they trigger new callbacks, they are aggregated + } finally { Future.callbacksPendingExecution.set(None) } // Ensure cleanup + } + } + + this + } + + def onComplete(func: Future[T] => Unit): CompletableFuture[T] = { + _lock.lock + val notifyNow = try { + if (_value.isEmpty) { + if (!isExpired) { //Only add the listener if the future isn't expired + _listeners ::= func + false + } else false //Will never run the callback since the future is expired + } else true + } finally { + _lock.unlock + } + + if (notifyNow) notifyCompleted(func) + + this + } + + private def notifyCompleted(func: Future[T] => Unit) { + try { + func(this) + } catch { + case e => EventHandler notify EventHandler.Error(e, this) + } + } + + @inline + private def currentTimeInNanos: Long = MILLIS.toNanos(System.currentTimeMillis) + @inline + private def timeLeft(): Long = timeoutInNanos - (currentTimeInNanos - _startTimeInNanos) +} + +/** + * An already completed Future is seeded with it's result at creation, is useful for when you are participating in + * a Future-composition but you already have a value to contribute. + */ +sealed class AlreadyCompletedFuture[T](suppliedValue: Either[Throwable, T]) extends CompletableFuture[T] { + val value = Some(suppliedValue) + + def complete(value: Either[Throwable, T]): CompletableFuture[T] = this + def onComplete(func: Future[T] => Unit): Future[T] = { func(this); this } + def await(atMost: Duration): Future[T] = this + def await: Future[T] = this + def awaitBlocking: Future[T] = this + def isExpired: Boolean = true + def timeoutInNanos: Long = 0 +} diff --git a/test/disabled/presentation/akka/src/akka/dispatch/MailboxHandling.scala b/test/disabled/presentation/akka/src/akka/dispatch/MailboxHandling.scala new file mode 100644 index 0000000000..4c00577157 --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/dispatch/MailboxHandling.scala @@ -0,0 +1,68 @@ +/** + * Copyright (C) 2009-2011 Scalable Solutions AB + */ + +package akka.dispatch + +import akka.AkkaException + +import java.util.{ Comparator, PriorityQueue } +import java.util.concurrent._ +import akka.util._ + +class MessageQueueAppendFailedException(message: String, cause: Throwable = null) extends AkkaException(message, cause) + +/** + * @author Jonas Bonér + */ +trait MessageQueue { + val dispatcherLock = new SimpleLock + val suspended = new SimpleLock + def enqueue(handle: MessageInvocation) + def dequeue(): MessageInvocation + def size: Int + def isEmpty: Boolean +} + +/** + * Mailbox configuration. + */ +sealed trait MailboxType + +case class UnboundedMailbox() extends MailboxType +case class BoundedMailbox( + val capacity: Int = { if (Dispatchers.MAILBOX_CAPACITY < 0) Int.MaxValue else Dispatchers.MAILBOX_CAPACITY }, + val pushTimeOut: Duration = Dispatchers.MAILBOX_PUSH_TIME_OUT) extends MailboxType { + if (capacity < 0) throw new IllegalArgumentException("The capacity for BoundedMailbox can not be negative") + if (pushTimeOut eq null) throw new IllegalArgumentException("The push time-out for BoundedMailbox can not be null") +} + +trait UnboundedMessageQueueSemantics extends MessageQueue { self: BlockingQueue[MessageInvocation] => + @inline + final def enqueue(handle: MessageInvocation): Unit = this add handle + @inline + final def dequeue(): MessageInvocation = this.poll() +} + +trait BoundedMessageQueueSemantics extends MessageQueue { self: BlockingQueue[MessageInvocation] => + def pushTimeOut: Duration + + final def enqueue(handle: MessageInvocation) { + if (pushTimeOut.length > 0) { + this.offer(handle, pushTimeOut.length, pushTimeOut.unit) || { + throw new MessageQueueAppendFailedException("Couldn't enqueue message " + handle + " to " + toString) + } + } else this put handle + } + + @inline + final def dequeue(): MessageInvocation = this.poll() +} + +class DefaultUnboundedMessageQueue extends LinkedBlockingQueue[MessageInvocation] with UnboundedMessageQueueSemantics + +class DefaultBoundedMessageQueue(capacity: Int, val pushTimeOut: Duration) extends LinkedBlockingQueue[MessageInvocation](capacity) with BoundedMessageQueueSemantics + +class UnboundedPriorityMessageQueue(cmp: Comparator[MessageInvocation]) extends PriorityBlockingQueue[MessageInvocation](11, cmp) with UnboundedMessageQueueSemantics + +class BoundedPriorityMessageQueue(capacity: Int, val pushTimeOut: Duration, cmp: Comparator[MessageInvocation]) extends BoundedBlockingQueue[MessageInvocation](capacity, new PriorityQueue[MessageInvocation](11, cmp)) with BoundedMessageQueueSemantics diff --git a/test/disabled/presentation/akka/src/akka/dispatch/MessageHandling.scala b/test/disabled/presentation/akka/src/akka/dispatch/MessageHandling.scala new file mode 100644 index 0000000000..20887c3867 --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/dispatch/MessageHandling.scala @@ -0,0 +1,260 @@ +/** + * Copyright (C) 2009-2011 Scalable Solutions AB + */ + +package akka.dispatch + +import java.util.concurrent._ +import java.util.concurrent.atomic.AtomicLong +import akka.event.EventHandler +import akka.config.Configuration +import akka.config.Config.TIME_UNIT +import akka.util.{ Duration, Switch, ReentrantGuard } +import java.util.concurrent.ThreadPoolExecutor.{ AbortPolicy, CallerRunsPolicy, DiscardOldestPolicy, DiscardPolicy } +import akka.actor._ + +/** + * @author Jonas Bonér + */ +final case class MessageInvocation(val receiver: ActorRef, + val message: Any, + val sender: Option[ActorRef], + val senderFuture: Option[CompletableFuture[Any]]) { + if (receiver eq null) throw new IllegalArgumentException("Receiver can't be null") + + def invoke = try { + receiver.invoke(this) + } catch { + case e: NullPointerException => throw new ActorInitializationException( + "Don't call 'self ! message' in the Actor's constructor (in Scala this means in the body of the class).") + } +} + +final case class FutureInvocation[T](future: CompletableFuture[T], function: () => T, cleanup: () => Unit) extends Runnable { + def run = { + future complete (try { + Right(function()) + } catch { + case e => + EventHandler.error(e, this, e.getMessage) + Left(e) + } + finally { + cleanup() + }) + } +} + +object MessageDispatcher { + val UNSCHEDULED = 0 + val SCHEDULED = 1 + val RESCHEDULED = 2 + + implicit def defaultGlobalDispatcher = Dispatchers.defaultGlobalDispatcher +} + +/** + * @author Jonas Bonér + */ +trait MessageDispatcher { + import MessageDispatcher._ + + protected val uuids = new ConcurrentSkipListSet[Uuid] + protected val futures = new AtomicLong(0L) + protected val guard = new ReentrantGuard + protected val active = new Switch(false) + + private var shutdownSchedule = UNSCHEDULED //This can be non-volatile since it is protected by guard withGuard + + /** + * Creates and returns a mailbox for the given actor. + */ + private[akka] def createMailbox(actorRef: ActorRef): AnyRef + + /** + * Attaches the specified actorRef to this dispatcher + */ + final def attach(actorRef: ActorRef): Unit = guard withGuard { + register(actorRef) + } + + /** + * Detaches the specified actorRef from this dispatcher + */ + final def detach(actorRef: ActorRef): Unit = guard withGuard { + unregister(actorRef) + } + + private[akka] final def dispatchMessage(invocation: MessageInvocation): Unit = dispatch(invocation) + + private[akka] final def dispatchFuture[T](block: () => T, timeout: Long): Future[T] = { + futures.getAndIncrement() + try { + val future = new DefaultCompletableFuture[T](timeout) + + if (active.isOff) + guard withGuard { active.switchOn { start } } + + executeFuture(FutureInvocation[T](future, block, futureCleanup)) + future + } catch { + case e => + futures.decrementAndGet + throw e + } + } + + private val futureCleanup: () => Unit = + () => if (futures.decrementAndGet() == 0) { + guard withGuard { + if (futures.get == 0 && uuids.isEmpty) { + shutdownSchedule match { + case UNSCHEDULED => + shutdownSchedule = SCHEDULED + Scheduler.scheduleOnce(shutdownAction, timeoutMs, TimeUnit.MILLISECONDS) + case SCHEDULED => + shutdownSchedule = RESCHEDULED + case RESCHEDULED => //Already marked for reschedule + } + } + } + } + + private[akka] def register(actorRef: ActorRef) { + if (actorRef.mailbox eq null) + actorRef.mailbox = createMailbox(actorRef) + + uuids add actorRef.uuid + if (active.isOff) { + active.switchOn { + start + } + } + } + + private[akka] def unregister(actorRef: ActorRef) = { + if (uuids remove actorRef.uuid) { + actorRef.mailbox = null + if (uuids.isEmpty && futures.get == 0) { + shutdownSchedule match { + case UNSCHEDULED => + shutdownSchedule = SCHEDULED + Scheduler.scheduleOnce(shutdownAction, timeoutMs, TimeUnit.MILLISECONDS) + case SCHEDULED => + shutdownSchedule = RESCHEDULED + case RESCHEDULED => //Already marked for reschedule + } + } + } + } + + /** + * Traverses the list of actors (uuids) currently being attached to this dispatcher and stops those actors + */ + def stopAllAttachedActors { + val i = uuids.iterator + while (i.hasNext()) { + val uuid = i.next() + Actor.registry.actorFor(uuid) match { + case Some(actor) => actor.stop() + case None => {} + } + } + } + + private val shutdownAction = new Runnable { + def run = guard withGuard { + shutdownSchedule match { + case RESCHEDULED => + shutdownSchedule = SCHEDULED + Scheduler.scheduleOnce(this, timeoutMs, TimeUnit.MILLISECONDS) + case SCHEDULED => + if (uuids.isEmpty && futures.get == 0) { + active switchOff { + shutdown // shut down in the dispatcher's references is zero + } + } + shutdownSchedule = UNSCHEDULED + case UNSCHEDULED => //Do nothing + } + } + } + + /** + * When the dispatcher no longer has any actors registered, how long will it wait until it shuts itself down, in Ms + * defaulting to your akka configs "akka.actor.dispatcher-shutdown-timeout" or otherwise, 1 Second + */ + private[akka] def timeoutMs: Long = Dispatchers.DEFAULT_SHUTDOWN_TIMEOUT.toMillis + + /** + * After the call to this method, the dispatcher mustn't begin any new message processing for the specified reference + */ + def suspend(actorRef: ActorRef): Unit + + /* + * After the call to this method, the dispatcher must begin any new message processing for the specified reference + */ + def resume(actorRef: ActorRef): Unit + + /** + * Will be called when the dispatcher is to queue an invocation for execution + */ + private[akka] def dispatch(invocation: MessageInvocation): Unit + + private[akka] def executeFuture(invocation: FutureInvocation[_]): Unit + + /** + * Called one time every time an actor is attached to this dispatcher and this dispatcher was previously shutdown + */ + private[akka] def start(): Unit + + /** + * Called one time every time an actor is detached from this dispatcher and this dispatcher has no actors left attached + */ + private[akka] def shutdown(): Unit + + /** + * Returns the size of the mailbox for the specified actor + */ + def mailboxSize(actorRef: ActorRef): Int + + /** + * Returns the amount of futures queued for execution + */ + def pendingFutures: Long = futures.get +} + +/** + * Trait to be used for hooking in new dispatchers into Dispatchers.fromConfig + */ +abstract class MessageDispatcherConfigurator { + /** + * Returns an instance of MessageDispatcher given a Configuration + */ + def configure(config: Configuration): MessageDispatcher + + def mailboxType(config: Configuration): MailboxType = { + val capacity = config.getInt("mailbox-capacity", Dispatchers.MAILBOX_CAPACITY) + if (capacity < 1) UnboundedMailbox() + else BoundedMailbox(capacity, Duration(config.getInt("mailbox-push-timeout-time", Dispatchers.MAILBOX_PUSH_TIME_OUT.toMillis.toInt), TIME_UNIT)) + } + + def configureThreadPool(config: Configuration, createDispatcher: => (ThreadPoolConfig) => MessageDispatcher): ThreadPoolConfigDispatcherBuilder = { + import ThreadPoolConfigDispatcherBuilder.conf_? + + //Apply the following options to the config if they are present in the config + ThreadPoolConfigDispatcherBuilder(createDispatcher, ThreadPoolConfig()).configure( + conf_?(config getInt "keep-alive-time")(time => _.setKeepAliveTime(Duration(time, TIME_UNIT))), + conf_?(config getDouble "core-pool-size-factor")(factor => _.setCorePoolSizeFromFactor(factor)), + conf_?(config getDouble "max-pool-size-factor")(factor => _.setMaxPoolSizeFromFactor(factor)), + conf_?(config getInt "executor-bounds")(bounds => _.setExecutorBounds(bounds)), + conf_?(config getBool "allow-core-timeout")(allow => _.setAllowCoreThreadTimeout(allow)), + conf_?(config getString "rejection-policy" map { + case "abort" => new AbortPolicy() + case "caller-runs" => new CallerRunsPolicy() + case "discard-oldest" => new DiscardOldestPolicy() + case "discard" => new DiscardPolicy() + case x => throw new IllegalArgumentException("[%s] is not a valid rejectionPolicy!" format x) + })(policy => _.setRejectionPolicy(policy))) + } +} diff --git a/test/disabled/presentation/akka/src/akka/dispatch/ThreadBasedDispatcher.scala b/test/disabled/presentation/akka/src/akka/dispatch/ThreadBasedDispatcher.scala new file mode 100644 index 0000000000..3169c70ef9 --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/dispatch/ThreadBasedDispatcher.scala @@ -0,0 +1,52 @@ +/** + * Copyright (C) 2009-2011 Scalable Solutions AB + */ + +package akka.dispatch + +import akka.actor.{ Actor, ActorRef } +import akka.config.Config.config +import akka.util.Duration + +import java.util.Queue +import java.util.concurrent.{ ConcurrentLinkedQueue, BlockingQueue, TimeUnit, LinkedBlockingQueue } +import akka.actor +import java.util.concurrent.atomic.AtomicReference + +/** + * Dedicates a unique thread for each actor passed in as reference. Served through its messageQueue. + * + * @author Jonas Bonér + */ +class ThreadBasedDispatcher(_actor: ActorRef, _mailboxType: MailboxType) + extends ExecutorBasedEventDrivenDispatcher( + _actor.uuid.toString, Dispatchers.THROUGHPUT, -1, _mailboxType, ThreadBasedDispatcher.oneThread) { + + private[akka] val owner = new AtomicReference[ActorRef](_actor) + + def this(actor: ActorRef) = + this(actor, UnboundedMailbox()) // For Java API + + def this(actor: ActorRef, capacity: Int) = + this(actor, BoundedMailbox(capacity)) //For Java API + + def this(actor: ActorRef, capacity: Int, pushTimeOut: Duration) = //For Java API + this(actor, BoundedMailbox(capacity, pushTimeOut)) + + override def register(actorRef: ActorRef) = { + val actor = owner.get() + if ((actor ne null) && actorRef != actor) throw new IllegalArgumentException("Cannot register to anyone but " + actor) + owner.compareAndSet(null, actorRef) //Register if unregistered + super.register(actorRef) + } + + override def unregister(actorRef: ActorRef) = { + super.unregister(actorRef) + owner.compareAndSet(actorRef, null) //Unregister (prevent memory leak) + } +} + +object ThreadBasedDispatcher { + val oneThread: ThreadPoolConfig = ThreadPoolConfig(allowCorePoolTimeout = true, corePoolSize = 1, maxPoolSize = 1) +} + diff --git a/test/disabled/presentation/akka/src/akka/dispatch/ThreadPoolBuilder.scala b/test/disabled/presentation/akka/src/akka/dispatch/ThreadPoolBuilder.scala new file mode 100644 index 0000000000..e847610c4c --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/dispatch/ThreadPoolBuilder.scala @@ -0,0 +1,259 @@ +/** + * Copyright (C) 2009-2011 Scalable Solutions AB + */ + +package akka.dispatch + +import java.util.Collection +import java.util.concurrent._ +import atomic.{ AtomicLong, AtomicInteger } +import ThreadPoolExecutor.CallerRunsPolicy + +import akka.util.Duration +import akka.event.EventHandler + +object ThreadPoolConfig { + type Bounds = Int + type FlowHandler = Either[RejectedExecutionHandler, Bounds] + type QueueFactory = () => BlockingQueue[Runnable] + + val defaultAllowCoreThreadTimeout: Boolean = false + val defaultCorePoolSize: Int = 16 + val defaultMaxPoolSize: Int = 128 + val defaultTimeout: Duration = Duration(60000L, TimeUnit.MILLISECONDS) + def defaultFlowHandler: FlowHandler = flowHandler(new CallerRunsPolicy) + + def flowHandler(rejectionHandler: RejectedExecutionHandler): FlowHandler = Left(rejectionHandler) + def flowHandler(bounds: Int): FlowHandler = Right(bounds) + + def fixedPoolSize(size: Int): Int = size + def scaledPoolSize(multiplier: Double): Int = + (Runtime.getRuntime.availableProcessors * multiplier).ceil.toInt + + def arrayBlockingQueue(capacity: Int, fair: Boolean): QueueFactory = + () => new ArrayBlockingQueue[Runnable](capacity, fair) + + def synchronousQueue(fair: Boolean): QueueFactory = + () => new SynchronousQueue[Runnable](fair) + + def linkedBlockingQueue(): QueueFactory = + () => new LinkedBlockingQueue[Runnable]() + + def linkedBlockingQueue(capacity: Int): QueueFactory = + () => new LinkedBlockingQueue[Runnable](capacity) + + def reusableQueue(queue: BlockingQueue[Runnable]): QueueFactory = + () => queue + + def reusableQueue(queueFactory: QueueFactory): QueueFactory = { + val queue = queueFactory() + () => queue + } +} + +case class ThreadPoolConfig(allowCorePoolTimeout: Boolean = ThreadPoolConfig.defaultAllowCoreThreadTimeout, + corePoolSize: Int = ThreadPoolConfig.defaultCorePoolSize, + maxPoolSize: Int = ThreadPoolConfig.defaultMaxPoolSize, + threadTimeout: Duration = ThreadPoolConfig.defaultTimeout, + flowHandler: ThreadPoolConfig.FlowHandler = ThreadPoolConfig.defaultFlowHandler, + queueFactory: ThreadPoolConfig.QueueFactory = ThreadPoolConfig.linkedBlockingQueue()) { + + final def createLazyExecutorService(threadFactory: ThreadFactory): ExecutorService = + new LazyExecutorServiceWrapper(createExecutorService(threadFactory)) + + final def createExecutorService(threadFactory: ThreadFactory): ExecutorService = { + flowHandler match { + case Left(rejectHandler) => + val service = new ThreadPoolExecutor(corePoolSize, maxPoolSize, threadTimeout.length, threadTimeout.unit, queueFactory(), threadFactory, rejectHandler) + service.allowCoreThreadTimeOut(allowCorePoolTimeout) + service + case Right(bounds) => + val service = new ThreadPoolExecutor(corePoolSize, maxPoolSize, threadTimeout.length, threadTimeout.unit, queueFactory(), threadFactory) + service.allowCoreThreadTimeOut(allowCorePoolTimeout) + new BoundedExecutorDecorator(service, bounds) + } + } +} + +trait DispatcherBuilder { + def build: MessageDispatcher +} + +object ThreadPoolConfigDispatcherBuilder { + def conf_?[T](opt: Option[T])(fun: (T) => ThreadPoolConfigDispatcherBuilder => ThreadPoolConfigDispatcherBuilder): Option[(ThreadPoolConfigDispatcherBuilder) => ThreadPoolConfigDispatcherBuilder] = opt map fun +} + +case class ThreadPoolConfigDispatcherBuilder(dispatcherFactory: (ThreadPoolConfig) => MessageDispatcher, config: ThreadPoolConfig) extends DispatcherBuilder { + import ThreadPoolConfig._ + def build = dispatcherFactory(config) + + //TODO remove this, for backwards compat only + @deprecated("Use .build instead", "1.1") + def buildThreadPool = build + + def withNewBoundedThreadPoolWithLinkedBlockingQueueWithUnboundedCapacity(bounds: Int): ThreadPoolConfigDispatcherBuilder = + this.copy(config = config.copy(flowHandler = flowHandler(bounds), queueFactory = linkedBlockingQueue())) + + def withNewThreadPoolWithCustomBlockingQueue(newQueueFactory: QueueFactory): ThreadPoolConfigDispatcherBuilder = + this.copy(config = config.copy(flowHandler = defaultFlowHandler, queueFactory = newQueueFactory)) + + def withNewThreadPoolWithCustomBlockingQueue(queue: BlockingQueue[Runnable]): ThreadPoolConfigDispatcherBuilder = + withNewThreadPoolWithCustomBlockingQueue(reusableQueue(queue)) + + def withNewThreadPoolWithLinkedBlockingQueueWithUnboundedCapacity: ThreadPoolConfigDispatcherBuilder = + this.copy(config = config.copy(queueFactory = linkedBlockingQueue(), flowHandler = defaultFlowHandler)) + + def withNewThreadPoolWithLinkedBlockingQueueWithCapacity(capacity: Int): ThreadPoolConfigDispatcherBuilder = + this.copy(config = config.copy(queueFactory = linkedBlockingQueue(capacity), flowHandler = defaultFlowHandler)) + + def withNewThreadPoolWithSynchronousQueueWithFairness(fair: Boolean): ThreadPoolConfigDispatcherBuilder = + this.copy(config = config.copy(queueFactory = synchronousQueue(fair), flowHandler = defaultFlowHandler)) + + def withNewThreadPoolWithArrayBlockingQueueWithCapacityAndFairness(capacity: Int, fair: Boolean): ThreadPoolConfigDispatcherBuilder = + this.copy(config = config.copy(queueFactory = arrayBlockingQueue(capacity, fair), flowHandler = defaultFlowHandler)) + + def setCorePoolSize(size: Int): ThreadPoolConfigDispatcherBuilder = + this.copy(config = config.copy(corePoolSize = size)) + + def setMaxPoolSize(size: Int): ThreadPoolConfigDispatcherBuilder = + this.copy(config = config.copy(maxPoolSize = size)) + + def setCorePoolSizeFromFactor(multiplier: Double): ThreadPoolConfigDispatcherBuilder = + setCorePoolSize(scaledPoolSize(multiplier)) + + def setMaxPoolSizeFromFactor(multiplier: Double): ThreadPoolConfigDispatcherBuilder = + setMaxPoolSize(scaledPoolSize(multiplier)) + + def setExecutorBounds(bounds: Int): ThreadPoolConfigDispatcherBuilder = + this.copy(config = config.copy(flowHandler = flowHandler(bounds))) + + def setKeepAliveTimeInMillis(time: Long): ThreadPoolConfigDispatcherBuilder = + setKeepAliveTime(Duration(time, TimeUnit.MILLISECONDS)) + + def setKeepAliveTime(time: Duration): ThreadPoolConfigDispatcherBuilder = + this.copy(config = config.copy(threadTimeout = time)) + + def setRejectionPolicy(policy: RejectedExecutionHandler): ThreadPoolConfigDispatcherBuilder = + setFlowHandler(flowHandler(policy)) + + def setFlowHandler(newFlowHandler: FlowHandler): ThreadPoolConfigDispatcherBuilder = + this.copy(config = config.copy(flowHandler = newFlowHandler)) + + def setAllowCoreThreadTimeout(allow: Boolean): ThreadPoolConfigDispatcherBuilder = + this.copy(config = config.copy(allowCorePoolTimeout = allow)) + + def configure(fs: Option[Function[ThreadPoolConfigDispatcherBuilder, ThreadPoolConfigDispatcherBuilder]]*): ThreadPoolConfigDispatcherBuilder = fs.foldLeft(this)((c, f) => f.map(_(c)).getOrElse(c)) +} + +/** + * @author Jonas Bonér + */ +class MonitorableThreadFactory(val name: String) extends ThreadFactory { + protected val counter = new AtomicLong + + def newThread(runnable: Runnable) = new MonitorableThread(runnable, name) +} + +/** + * @author Jonas Bonér + */ +object MonitorableThread { + val DEFAULT_NAME = "MonitorableThread" + + // FIXME use MonitorableThread.created and MonitorableThread.alive in monitoring + val created = new AtomicInteger + val alive = new AtomicInteger +} + +/** + * @author Jonas Bonér + */ +class MonitorableThread(runnable: Runnable, name: String) + extends Thread(runnable, name + "-" + MonitorableThread.created.incrementAndGet) { + + setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { + def uncaughtException(thread: Thread, cause: Throwable) = {} + }) + + override def run = { + try { + MonitorableThread.alive.incrementAndGet + super.run + } finally { + MonitorableThread.alive.decrementAndGet + } + } +} + +/** + * @author Jonas Bonér + */ +class BoundedExecutorDecorator(val executor: ExecutorService, bound: Int) extends ExecutorServiceDelegate { + protected val semaphore = new Semaphore(bound) + + override def execute(command: Runnable) = { + semaphore.acquire + try { + executor.execute(new Runnable() { + def run = { + try { + command.run + } finally { + semaphore.release + } + } + }) + } catch { + case e: RejectedExecutionException => + EventHandler.warning(this, e.toString) + semaphore.release + case e: Throwable => + EventHandler.error(e, this, e.getMessage) + throw e + } + } +} + +trait ExecutorServiceDelegate extends ExecutorService { + + def executor: ExecutorService + + def execute(command: Runnable) = executor.execute(command) + + def shutdown() { executor.shutdown() } + + def shutdownNow() = executor.shutdownNow() + + def isShutdown = executor.isShutdown + + def isTerminated = executor.isTerminated + + def awaitTermination(l: Long, timeUnit: TimeUnit) = executor.awaitTermination(l, timeUnit) + + def submit[T](callable: Callable[T]) = executor.submit(callable) + + def submit[T](runnable: Runnable, t: T) = executor.submit(runnable, t) + + def submit(runnable: Runnable) = executor.submit(runnable) + + def invokeAll[T](callables: Collection[_ <: Callable[T]]) = executor.invokeAll(callables) + + def invokeAll[T](callables: Collection[_ <: Callable[T]], l: Long, timeUnit: TimeUnit) = executor.invokeAll(callables, l, timeUnit) + + def invokeAny[T](callables: Collection[_ <: Callable[T]]) = executor.invokeAny(callables) + + def invokeAny[T](callables: Collection[_ <: Callable[T]], l: Long, timeUnit: TimeUnit) = executor.invokeAny(callables, l, timeUnit) +} + +trait LazyExecutorService extends ExecutorServiceDelegate { + + def createExecutor: ExecutorService + + lazy val executor = { + createExecutor + } +} + +class LazyExecutorServiceWrapper(executorFactory: => ExecutorService) extends LazyExecutorService { + def createExecutor = executorFactory +} diff --git a/test/disabled/presentation/akka/src/akka/event/EventHandler.scala b/test/disabled/presentation/akka/src/akka/event/EventHandler.scala new file mode 100644 index 0000000000..f3176b7c21 --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/event/EventHandler.scala @@ -0,0 +1,235 @@ +/** + * Copyright (C) 2009-2011 Scalable Solutions AB + */ + +package akka.event + +import akka.actor._ +import akka.config.Config._ +import akka.config.ConfigurationException +import akka.util.{ ListenerManagement, ReflectiveAccess } +import akka.AkkaException + +/** + * Event handler. + *

      + * Create, add and remove a listener: + *

      + * val eventHandlerListener = Actor.actorOf(new Actor {
      + *   self.dispatcher = EventHandler.EventHandlerDispatcher
      + *
      + *   def receive = {
      + *     case EventHandler.Error(cause, instance, message) => ...
      + *     case EventHandler.Warning(instance, message)      => ...
      + *     case EventHandler.Info(instance, message)         => ...
      + *     case EventHandler.Debug(instance, message)        => ...
      + *     case genericEvent                                 => ...
      + *   }
      + * })
      + *
      + * EventHandler.addListener(eventHandlerListener)
      + * ...
      + * EventHandler.removeListener(eventHandlerListener)
      + * 
      + *

      + * However best is probably to register the listener in the 'akka.conf' + * configuration file. + *

      + * Log an error event: + *

      + * EventHandler.notify(EventHandler.Error(exception, this, message))
      + * 
      + * Or use the direct methods (better performance): + *
      + * EventHandler.error(exception, this, message)
      + * 
      + * + * Shut down the EventHandler: + *
      + * EventHandler.shutdown()
      + * 
      + * + * @author Jonas Bonér + */ +object EventHandler extends ListenerManagement { + import java.io.{ StringWriter, PrintWriter } + import java.text.DateFormat + import java.util.Date + import akka.dispatch.Dispatchers + + val ErrorLevel = 1 + val WarningLevel = 2 + val InfoLevel = 3 + val DebugLevel = 4 + + sealed trait Event { + @transient + val thread: Thread = Thread.currentThread + val level: Int + } + case class Error(cause: Throwable, instance: AnyRef, message: Any = "") extends Event { + override val level = ErrorLevel + } + case class Warning(instance: AnyRef, message: Any = "") extends Event { + override val level = WarningLevel + } + case class Info(instance: AnyRef, message: Any = "") extends Event { + override val level = InfoLevel + } + case class Debug(instance: AnyRef, message: Any = "") extends Event { + override val level = DebugLevel + } + + val error = "[ERROR] [%s] [%s] [%s] %s\n%s".intern + val warning = "[WARN] [%s] [%s] [%s] %s".intern + val info = "[INFO] [%s] [%s] [%s] %s".intern + val debug = "[DEBUG] [%s] [%s] [%s] %s".intern + val generic = "[GENERIC] [%s] [%s]".intern + val ID = "event:handler".intern + + class EventHandlerException extends AkkaException + + lazy val EventHandlerDispatcher = Dispatchers.newExecutorBasedEventDrivenDispatcher(ID).build + + val level: Int = config.getString("akka.event-handler-level", "INFO") match { + case "ERROR" => ErrorLevel + case "WARNING" => WarningLevel + case "INFO" => InfoLevel + case "DEBUG" => DebugLevel + case unknown => throw new ConfigurationException( + "Configuration option 'akka.event-handler-level' is invalid [" + unknown + "]") + } + + /** + * Shuts down all event handler listeners including the event handle dispatcher. + */ + def shutdown() { + foreachListener(_.stop()) + EventHandlerDispatcher.shutdown() + } + + def notify(event: Any) { + if (event.isInstanceOf[Event]) { + if (level >= event.asInstanceOf[Event].level) notifyListeners(event) + } else + notifyListeners(event) + } + + def notify[T <: Event: ClassManifest](event: => T) { + if (level >= levelFor(classManifest[T].erasure.asInstanceOf[Class[_ <: Event]])) notifyListeners(event) + } + + def error(cause: Throwable, instance: AnyRef, message: => String) { + if (level >= ErrorLevel) notifyListeners(Error(cause, instance, message)) + } + + def error(cause: Throwable, instance: AnyRef, message: Any) { + if (level >= ErrorLevel) notifyListeners(Error(cause, instance, message)) + } + + def error(instance: AnyRef, message: => String) { + if (level >= ErrorLevel) notifyListeners(Error(new EventHandlerException, instance, message)) + } + + def error(instance: AnyRef, message: Any) { + if (level >= ErrorLevel) notifyListeners(Error(new EventHandlerException, instance, message)) + } + + def warning(instance: AnyRef, message: => String) { + if (level >= WarningLevel) notifyListeners(Warning(instance, message)) + } + + def warning(instance: AnyRef, message: Any) { + if (level >= WarningLevel) notifyListeners(Warning(instance, message)) + } + + def info(instance: AnyRef, message: => String) { + if (level >= InfoLevel) notifyListeners(Info(instance, message)) + } + + def info(instance: AnyRef, message: Any) { + if (level >= InfoLevel) notifyListeners(Info(instance, message)) + } + + def debug(instance: AnyRef, message: => String) { + if (level >= DebugLevel) notifyListeners(Debug(instance, message)) + } + + def debug(instance: AnyRef, message: Any) { + if (level >= DebugLevel) notifyListeners(Debug(instance, message)) + } + + def isInfoEnabled = level >= InfoLevel + + def isDebugEnabled = level >= DebugLevel + + def formattedTimestamp = DateFormat.getInstance.format(new Date) + + def stackTraceFor(e: Throwable) = { + val sw = new StringWriter + val pw = new PrintWriter(sw) + e.printStackTrace(pw) + sw.toString + } + + private def levelFor(eventClass: Class[_ <: Event]) = { + if (eventClass.isInstanceOf[Error]) ErrorLevel + else if (eventClass.isInstanceOf[Warning]) WarningLevel + else if (eventClass.isInstanceOf[Info]) InfoLevel + else if (eventClass.isInstanceOf[Debug]) DebugLevel + else DebugLevel + } + + class DefaultListener extends Actor { + self.id = ID + self.dispatcher = EventHandlerDispatcher + + def receive = { + case event@Error(cause, instance, message) => + println(error.format( + formattedTimestamp, + event.thread.getName, + instance.getClass.getSimpleName, + message, + stackTraceFor(cause))) + case event@Warning(instance, message) => + println(warning.format( + formattedTimestamp, + event.thread.getName, + instance.getClass.getSimpleName, + message)) + case event@Info(instance, message) => + println(info.format( + formattedTimestamp, + event.thread.getName, + instance.getClass.getSimpleName, + message)) + case event@Debug(instance, message) => + println(debug.format( + formattedTimestamp, + event.thread.getName, + instance.getClass.getSimpleName, + message)) + case event => + println(generic.format(formattedTimestamp, event.toString)) + } + } + + val defaultListeners = config.getList("akka.event-handlers") match { + case Nil => "akka.event.EventHandler$DefaultListener" :: Nil + case listeners => listeners + } + defaultListeners foreach { listenerName => + try { + ReflectiveAccess.getClassFor[Actor](listenerName) match { + case r: Right[_, Class[Actor]] => addListener(Actor.actorOf(r.b).start()) + case l: Left[Exception, _] => throw l.a + } + } catch { + case e: Exception => + throw new ConfigurationException( + "Event Handler specified in config can't be loaded [" + listenerName + + "] due to [" + e.toString + "]", e) + } + } +} diff --git a/test/disabled/presentation/akka/src/akka/event/JavaEventHandler.java b/test/disabled/presentation/akka/src/akka/event/JavaEventHandler.java new file mode 100644 index 0000000000..7e6e2d4143 --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/event/JavaEventHandler.java @@ -0,0 +1,35 @@ +package akka.event; + + +import akka.actor.ActorRef; + +/** + * Java API for Akka EventHandler + */ + +public class JavaEventHandler { + + + public static void notify(Object message){ + EventHandler$.MODULE$.notify(message); + } + + public static void debug(ActorRef instance, Object message){ + EventHandler$.MODULE$.debug(instance, message); + } + + public static void info(ActorRef instance, Object message){ + EventHandler$.MODULE$.info(instance,message); + } + + public static void warning(ActorRef instance, Object message){ + EventHandler$.MODULE$.warning(instance,message); + } + + public static void error(ActorRef instance, Object message){ + EventHandler$.MODULE$.debug(instance,message); + } + +} + + diff --git a/test/disabled/presentation/akka/src/akka/japi/JavaAPI.scala b/test/disabled/presentation/akka/src/akka/japi/JavaAPI.scala new file mode 100644 index 0000000000..f5c4ccdcaa --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/japi/JavaAPI.scala @@ -0,0 +1,108 @@ +package akka.japi + +/** + * A Function interface. Used to create first-class-functions is Java (sort of). + */ +trait Function[T, R] { + def apply(param: T): R +} + +/** + * A Function interface. Used to create 2-arg first-class-functions is Java (sort of). + */ +trait Function2[T1, T2, R] { + def apply(arg1: T1, arg2: T2): R +} + +/** + * A Procedure is like a Function, but it doesn't produce a return value + */ +trait Procedure[T] { + def apply(param: T): Unit +} + +/** + * A Procedure is like a Function, but it doesn't produce a return value + */ +trait Procedure2[T1, T2] { + def apply(param: T1, param2: T2): Unit +} + +/** + * An executable piece of code that takes no parameters and doesn't return any value. + */ +trait SideEffect { + def apply: Unit +} + +/** + * An executable piece of code that takes no parameters and doesn't return any value. + */ +trait Effect { + def apply: Unit +} + +/** + * + * A constructor/factory, takes no parameters but creates a new value of type T every call + * + + */ +trait Creator[T] { + def create: T +} + +/** + * This class represents optional values. Instances of Option + * are either instances of case class Some or it is case + * object None. + *

      + * Java API + */ +sealed abstract class Option[A] extends java.lang.Iterable[A] { + import scala.collection.JavaConversions._ + + def get: A + def isEmpty: Boolean + def isDefined = !isEmpty + def asScala: scala.Option[A] + def iterator = if (isEmpty) Iterator.empty else Iterator.single(get) +} + +object Option { + /** + * Option factory that creates Some + */ + def some[A](v: A): Option[A] = Some(v) + + /** + * Option factory that creates None + */ + def none[A] = None.asInstanceOf[Option[A]] + + /** + * Option factory that creates None if + * v is null, Some(v) otherwise. + */ + def option[A](v: A): Option[A] = if (v == null) none else some(v) + + /** + * Class Some[A] represents existing values of type + * A. + */ + final case class Some[A](v: A) extends Option[A] { + def get = v + def isEmpty = false + def asScala = scala.Some(v) + } + + /** + * This case object represents non-existent values. + */ + private case object None extends Option[Nothing] { + def get = throw new NoSuchElementException("None.get") + def isEmpty = true + def asScala = scala.None + } + + implicit def java2ScalaOption[A](o: Option[A]): scala.Option[A] = o.asScala + implicit def scala2JavaOption[A](o: scala.Option[A]): Option[A] = option(o.get) +} diff --git a/test/disabled/presentation/akka/src/akka/remoteinterface/RemoteEventHandler.scala b/test/disabled/presentation/akka/src/akka/remoteinterface/RemoteEventHandler.scala new file mode 100644 index 0000000000..1c75618301 --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/remoteinterface/RemoteEventHandler.scala @@ -0,0 +1,43 @@ +package akka.remoteinterface + +/** + * Copyright (C) 2009-2011 Scalable Solutions AB + */ + +import akka.actor.Actor +import akka.event.EventHandler + +/** + * Remote client and server event listener that pipes the events to the standard Akka EventHander. + * + * @author Jonas Bonér + */ +class RemoteEventHandler extends Actor { + import EventHandler._ + + self.id = ID + self.dispatcher = EventHandlerDispatcher + + def receive = { + + // client + case RemoteClientError(cause, client, address) => EventHandler.error(cause, client, "RemoteClientError - Address[%s]" format address.toString) + case RemoteClientWriteFailed(request, cause, client, address) => EventHandler.error(cause, client, "RemoteClientWriteFailed - Request[%s] Address[%s]".format(address.toString)) + case RemoteClientDisconnected(client, address) => EventHandler.info(client, "RemoteClientDisconnected - Address[%s]" format address.toString) + case RemoteClientConnected(client, address) => EventHandler.info(client, "RemoteClientConnected - Address[%s]" format address.toString) + case RemoteClientStarted(client, address) => EventHandler.info(client, "RemoteClientStarted - Address[%s]" format address.toString) + case RemoteClientShutdown(client, address) => EventHandler.info(client, "RemoteClientShutdown - Address[%s]" format address.toString) + + // server + case RemoteServerError(cause, server) => EventHandler.error(cause, server, "RemoteServerError") + case RemoteServerWriteFailed(request, cause, server, clientAddress) => EventHandler.error(cause, server, "RemoteServerWriteFailed - Request[%s] Address[%s]" format (request, clientAddress.toString)) + case RemoteServerStarted(server) => EventHandler.info(server, "RemoteServerStarted") + case RemoteServerShutdown(server) => EventHandler.info(server, "RemoteServerShutdown") + case RemoteServerClientConnected(server, clientAddress) => EventHandler.info(server, "RemoteServerClientConnected - Address[%s]" format clientAddress.toString) + case RemoteServerClientDisconnected(server, clientAddress) => EventHandler.info(server, "RemoteServerClientDisconnected - Address[%s]" format clientAddress.toString) + case RemoteServerClientClosed(server, clientAddress) => EventHandler.info(server, "RemoteServerClientClosed - Address[%s]" format clientAddress.toString) + + case _ => //ignore other + } +} + diff --git a/test/disabled/presentation/akka/src/akka/remoteinterface/RemoteInterface.scala b/test/disabled/presentation/akka/src/akka/remoteinterface/RemoteInterface.scala new file mode 100644 index 0000000000..0c5da82294 --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/remoteinterface/RemoteInterface.scala @@ -0,0 +1,493 @@ +/** + * Copyright (C) 2009-2010 Scalable Solutions AB + */ + +package akka.remoteinterface + +import akka.japi.Creator +import akka.actor._ +import akka.util._ +import akka.dispatch.CompletableFuture +import akka.AkkaException + +import scala.beans.BeanProperty + +import java.net.InetSocketAddress +import java.util.concurrent.ConcurrentHashMap +import java.io.{ PrintWriter, PrintStream } +import java.lang.reflect.InvocationTargetException + +trait RemoteModule { + val UUID_PREFIX = "uuid:".intern + + def optimizeLocalScoped_?(): Boolean //Apply optimizations for remote operations in local scope + protected[akka] def notifyListeners(message: => Any): Unit + + private[akka] def actors: ConcurrentHashMap[String, ActorRef] + private[akka] def actorsByUuid: ConcurrentHashMap[String, ActorRef] + private[akka] def actorsFactories: ConcurrentHashMap[String, () => ActorRef] + private[akka] def typedActors: ConcurrentHashMap[String, AnyRef] + private[akka] def typedActorsByUuid: ConcurrentHashMap[String, AnyRef] + private[akka] def typedActorsFactories: ConcurrentHashMap[String, () => AnyRef] + + /** Lookup methods **/ + + private[akka] def findActorById(id: String): ActorRef = actors.get(id) + + private[akka] def findActorByUuid(uuid: String): ActorRef = actorsByUuid.get(uuid) + + private[akka] def findActorFactory(id: String): () => ActorRef = actorsFactories.get(id) + + private[akka] def findTypedActorById(id: String): AnyRef = typedActors.get(id) + + private[akka] def findTypedActorFactory(id: String): () => AnyRef = typedActorsFactories.get(id) + + private[akka] def findTypedActorByUuid(uuid: String): AnyRef = typedActorsByUuid.get(uuid) + + private[akka] def findActorByIdOrUuid(id: String, uuid: String): ActorRef = { + var actorRefOrNull = if (id.startsWith(UUID_PREFIX)) findActorByUuid(id.substring(UUID_PREFIX.length)) + else findActorById(id) + if (actorRefOrNull eq null) actorRefOrNull = findActorByUuid(uuid) + actorRefOrNull + } + + private[akka] def findTypedActorByIdOrUuid(id: String, uuid: String): AnyRef = { + var actorRefOrNull = if (id.startsWith(UUID_PREFIX)) findTypedActorByUuid(id.substring(UUID_PREFIX.length)) + else findTypedActorById(id) + if (actorRefOrNull eq null) actorRefOrNull = findTypedActorByUuid(uuid) + actorRefOrNull + } +} + +/** + * Life-cycle events for RemoteClient. + */ +sealed trait RemoteClientLifeCycleEvent +case class RemoteClientError( + @BeanProperty cause: Throwable, + @BeanProperty client: RemoteClientModule, + @BeanProperty remoteAddress: InetSocketAddress) extends RemoteClientLifeCycleEvent +case class RemoteClientDisconnected( + @BeanProperty client: RemoteClientModule, + @BeanProperty remoteAddress: InetSocketAddress) extends RemoteClientLifeCycleEvent +case class RemoteClientConnected( + @BeanProperty client: RemoteClientModule, + @BeanProperty remoteAddress: InetSocketAddress) extends RemoteClientLifeCycleEvent +case class RemoteClientStarted( + @BeanProperty client: RemoteClientModule, + @BeanProperty remoteAddress: InetSocketAddress) extends RemoteClientLifeCycleEvent +case class RemoteClientShutdown( + @BeanProperty client: RemoteClientModule, + @BeanProperty remoteAddress: InetSocketAddress) extends RemoteClientLifeCycleEvent +case class RemoteClientWriteFailed( + @BeanProperty request: AnyRef, + @BeanProperty cause: Throwable, + @BeanProperty client: RemoteClientModule, + @BeanProperty remoteAddress: InetSocketAddress) extends RemoteClientLifeCycleEvent + +/** + * Life-cycle events for RemoteServer. + */ +sealed trait RemoteServerLifeCycleEvent +case class RemoteServerStarted( + @BeanProperty val server: RemoteServerModule) extends RemoteServerLifeCycleEvent +case class RemoteServerShutdown( + @BeanProperty val server: RemoteServerModule) extends RemoteServerLifeCycleEvent +case class RemoteServerError( + @BeanProperty val cause: Throwable, + @BeanProperty val server: RemoteServerModule) extends RemoteServerLifeCycleEvent +case class RemoteServerClientConnected( + @BeanProperty val server: RemoteServerModule, + @BeanProperty val clientAddress: Option[InetSocketAddress]) extends RemoteServerLifeCycleEvent +case class RemoteServerClientDisconnected( + @BeanProperty val server: RemoteServerModule, + @BeanProperty val clientAddress: Option[InetSocketAddress]) extends RemoteServerLifeCycleEvent +case class RemoteServerClientClosed( + @BeanProperty val server: RemoteServerModule, + @BeanProperty val clientAddress: Option[InetSocketAddress]) extends RemoteServerLifeCycleEvent +case class RemoteServerWriteFailed( + @BeanProperty request: AnyRef, + @BeanProperty cause: Throwable, + @BeanProperty server: RemoteServerModule, + @BeanProperty clientAddress: Option[InetSocketAddress]) extends RemoteServerLifeCycleEvent + +/** + * Thrown for example when trying to send a message using a RemoteClient that is either not started or shut down. + */ +class RemoteClientException private[akka] ( + message: String, + @BeanProperty val client: RemoteClientModule, + val remoteAddress: InetSocketAddress, cause: Throwable = null) extends AkkaException(message, cause) + +/** + * Thrown when the remote server actor dispatching fails for some reason. + */ +class RemoteServerException private[akka] (message: String) extends AkkaException(message) + +/** + * Thrown when a remote exception sent over the wire cannot be loaded and instantiated + */ +case class CannotInstantiateRemoteExceptionDueToRemoteProtocolParsingErrorException private[akka] (cause: Throwable, originalClassName: String, originalMessage: String) + extends AkkaException("\nParsingError[%s]\nOriginalException[%s]\nOriginalMessage[%s]" + .format(cause.toString, originalClassName, originalMessage)) { + override def printStackTrace = cause.printStackTrace + override def printStackTrace(printStream: PrintStream) = cause.printStackTrace(printStream) + override def printStackTrace(printWriter: PrintWriter) = cause.printStackTrace(printWriter) +} + +abstract class RemoteSupport extends ListenerManagement with RemoteServerModule with RemoteClientModule { + + lazy val eventHandler: ActorRef = { + val handler = Actor.actorOf[RemoteEventHandler].start() + // add the remote client and server listener that pipes the events to the event handler system + addListener(handler) + handler + } + + def shutdown() { + eventHandler.stop() + removeListener(eventHandler) + this.shutdownClientModule() + this.shutdownServerModule() + clear + } + + /** + * Creates a Client-managed ActorRef out of the Actor of the specified Class. + * If the supplied host and port is identical of the configured local node, it will be a local actor + *

      +   *   import Actor._
      +   *   val actor = actorOf(classOf[MyActor],"www.akka.io", 2552)
      +   *   actor.start()
      +   *   actor ! message
      +   *   actor.stop()
      +   * 
      + * You can create and start the actor in one statement like this: + *
      +   *   val actor = actorOf(classOf[MyActor],"www.akka.io", 2552).start()
      +   * 
      + */ + @deprecated("Will be removed after 1.1", "1.1") + def actorOf(factory: => Actor, host: String, port: Int): ActorRef = + Actor.remote.clientManagedActorOf(() => factory, host, port) + + /** + * Creates a Client-managed ActorRef out of the Actor of the specified Class. + * If the supplied host and port is identical of the configured local node, it will be a local actor + *
      +   *   import Actor._
      +   *   val actor = actorOf(classOf[MyActor],"www.akka.io",2552)
      +   *   actor.start()
      +   *   actor ! message
      +   *   actor.stop()
      +   * 
      + * You can create and start the actor in one statement like this: + *
      +   *   val actor = actorOf(classOf[MyActor],"www.akka.io",2552).start()
      +   * 
      + */ + @deprecated("Will be removed after 1.1", "1.1") + def actorOf(clazz: Class[_ <: Actor], host: String, port: Int): ActorRef = + clientManagedActorOf(() => createActorFromClass(clazz), host, port) + + /** + * Creates a Client-managed ActorRef out of the Actor of the specified Class. + * If the supplied host and port is identical of the configured local node, it will be a local actor + *
      +   *   import Actor._
      +   *   val actor = actorOf[MyActor]("www.akka.io",2552)
      +   *   actor.start()
      +   *   actor ! message
      +   *   actor.stop()
      +   * 
      + * You can create and start the actor in one statement like this: + *
      +   *   val actor = actorOf[MyActor]("www.akka.io",2552).start()
      +   * 
      + */ + @deprecated("Will be removed after 1.1", "1.1") + def actorOf[T <: Actor: Manifest](host: String, port: Int): ActorRef = + clientManagedActorOf(() => createActorFromClass(manifest.erasure), host, port) + + protected def createActorFromClass(clazz: Class[_]): Actor = { + import ReflectiveAccess.{ createInstance, noParams, noArgs } + createInstance[Actor](clazz, noParams, noArgs) match { + case Right(actor) => actor + case Left(exception) => + val cause = exception match { + case i: InvocationTargetException => i.getTargetException + case _ => exception + } + + throw new ActorInitializationException( + "Could not instantiate Actor of " + clazz + + "\nMake sure Actor is NOT defined inside a class/trait," + + "\nif so put it outside the class/trait, f.e. in a companion object," + + "\nOR try to change: 'actorOf[MyActor]' to 'actorOf(new MyActor)'.", cause) + } + } + + protected override def manageLifeCycleOfListeners = false + protected[akka] override def notifyListeners(message: => Any): Unit = super.notifyListeners(message) + + private[akka] val actors = new ConcurrentHashMap[String, ActorRef] + private[akka] val actorsByUuid = new ConcurrentHashMap[String, ActorRef] + private[akka] val actorsFactories = new ConcurrentHashMap[String, () => ActorRef] + private[akka] val typedActors = new ConcurrentHashMap[String, AnyRef] + private[akka] val typedActorsByUuid = new ConcurrentHashMap[String, AnyRef] + private[akka] val typedActorsFactories = new ConcurrentHashMap[String, () => AnyRef] + + def clear { + actors.clear + actorsByUuid.clear + typedActors.clear + typedActorsByUuid.clear + actorsFactories.clear + typedActorsFactories.clear + } +} + +/** + * This is the interface for the RemoteServer functionality, it's used in Actor.remote + */ +trait RemoteServerModule extends RemoteModule { + protected val guard = new ReentrantGuard + + /** + * Signals whether the server is up and running or not + */ + def isRunning: Boolean + + /** + * Gets the name of the server instance + */ + def name: String + + /** + * Gets the address of the server instance + */ + def address: InetSocketAddress + + /** + * Starts the server up + */ + def start(): RemoteServerModule = + start(ReflectiveAccess.Remote.configDefaultAddress.getAddress.getHostAddress, + ReflectiveAccess.Remote.configDefaultAddress.getPort, + None) + + /** + * Starts the server up + */ + def start(loader: ClassLoader): RemoteServerModule = + start(ReflectiveAccess.Remote.configDefaultAddress.getAddress.getHostAddress, + ReflectiveAccess.Remote.configDefaultAddress.getPort, + Option(loader)) + + /** + * Starts the server up + */ + def start(host: String, port: Int): RemoteServerModule = + start(host, port, None) + + /** + * Starts the server up + */ + def start(host: String, port: Int, loader: ClassLoader): RemoteServerModule = + start(host, port, Option(loader)) + + /** + * Starts the server up + */ + def start(host: String, port: Int, loader: Option[ClassLoader]): RemoteServerModule + + /** + * Shuts the server down + */ + def shutdownServerModule(): Unit + + /** + * Register typed actor by interface name. + */ + def registerTypedActor(intfClass: Class[_], typedActor: AnyRef): Unit = registerTypedActor(intfClass.getName, typedActor) + + /** + * Register remote typed actor by a specific id. + * @param id custom actor id + * @param typedActor typed actor to register + */ + def registerTypedActor(id: String, typedActor: AnyRef): Unit + + /** + * Register typed actor by interface name. + */ + def registerTypedPerSessionActor(intfClass: Class[_], factory: => AnyRef): Unit = registerTypedActor(intfClass.getName, factory) + + /** + * Register typed actor by interface name. + * Java API + */ + def registerTypedPerSessionActor(intfClass: Class[_], factory: Creator[AnyRef]): Unit = registerTypedActor(intfClass.getName, factory) + + /** + * Register remote typed actor by a specific id. + * @param id custom actor id + * @param typedActor typed actor to register + */ + def registerTypedPerSessionActor(id: String, factory: => AnyRef): Unit + + /** + * Register remote typed actor by a specific id. + * @param id custom actor id + * @param typedActor typed actor to register + * Java API + */ + def registerTypedPerSessionActor(id: String, factory: Creator[AnyRef]): Unit = registerTypedPerSessionActor(id, factory.create) + + /** + * Register Remote Actor by the Actor's 'id' field. It starts the Actor if it is not started already. + */ + def register(actorRef: ActorRef): Unit = register(actorRef.id, actorRef) + + /** + * Register Remote Actor by the Actor's uuid field. It starts the Actor if it is not started already. + */ + def registerByUuid(actorRef: ActorRef): Unit + + /** + * Register Remote Actor by a specific 'id' passed as argument. The actor is registered by UUID rather than ID + * when prefixing the handle with the “uuid:” protocol. + *

      + * NOTE: If you use this method to register your remote actor then you must unregister the actor by this ID yourself. + */ + def register(id: String, actorRef: ActorRef): Unit + + /** + * Register Remote Session Actor by a specific 'id' passed as argument. + *

      + * NOTE: If you use this method to register your remote actor then you must unregister the actor by this ID yourself. + */ + def registerPerSession(id: String, factory: => ActorRef): Unit + + /** + * Register Remote Session Actor by a specific 'id' passed as argument. + *

      + * NOTE: If you use this method to register your remote actor then you must unregister the actor by this ID yourself. + * Java API + */ + def registerPerSession(id: String, factory: Creator[ActorRef]): Unit = registerPerSession(id, factory.create) + + /** + * Unregister Remote Actor that is registered using its 'id' field (not custom ID). + */ + def unregister(actorRef: ActorRef): Unit + + /** + * Unregister Remote Actor by specific 'id'. + *

      + * NOTE: You need to call this method if you have registered an actor by a custom ID. + */ + def unregister(id: String): Unit + + /** + * Unregister Remote Actor by specific 'id'. + *

      + * NOTE: You need to call this method if you have registered an actor by a custom ID. + */ + def unregisterPerSession(id: String): Unit + + /** + * Unregister Remote Typed Actor by specific 'id'. + *

      + * NOTE: You need to call this method if you have registered an actor by a custom ID. + */ + def unregisterTypedActor(id: String): Unit + + /** + * Unregister Remote Typed Actor by specific 'id'. + *

      + * NOTE: You need to call this method if you have registered an actor by a custom ID. + */ + def unregisterTypedPerSessionActor(id: String): Unit +} + +trait RemoteClientModule extends RemoteModule { self: RemoteModule => + + def actorFor(classNameOrServiceId: String, hostname: String, port: Int): ActorRef = + actorFor(classNameOrServiceId, classNameOrServiceId, Actor.TIMEOUT, hostname, port, None) + + def actorFor(classNameOrServiceId: String, hostname: String, port: Int, loader: ClassLoader): ActorRef = + actorFor(classNameOrServiceId, classNameOrServiceId, Actor.TIMEOUT, hostname, port, Some(loader)) + + def actorFor(serviceId: String, className: String, hostname: String, port: Int): ActorRef = + actorFor(serviceId, className, Actor.TIMEOUT, hostname, port, None) + + def actorFor(serviceId: String, className: String, hostname: String, port: Int, loader: ClassLoader): ActorRef = + actorFor(serviceId, className, Actor.TIMEOUT, hostname, port, Some(loader)) + + def actorFor(classNameOrServiceId: String, timeout: Long, hostname: String, port: Int): ActorRef = + actorFor(classNameOrServiceId, classNameOrServiceId, timeout, hostname, port, None) + + def actorFor(classNameOrServiceId: String, timeout: Long, hostname: String, port: Int, loader: ClassLoader): ActorRef = + actorFor(classNameOrServiceId, classNameOrServiceId, timeout, hostname, port, Some(loader)) + + def actorFor(serviceId: String, className: String, timeout: Long, hostname: String, port: Int): ActorRef = + actorFor(serviceId, className, timeout, hostname, port, None) + + def typedActorFor[T](intfClass: Class[T], serviceIdOrClassName: String, hostname: String, port: Int): T = + typedActorFor(intfClass, serviceIdOrClassName, serviceIdOrClassName, Actor.TIMEOUT, hostname, port, None) + + def typedActorFor[T](intfClass: Class[T], serviceIdOrClassName: String, timeout: Long, hostname: String, port: Int): T = + typedActorFor(intfClass, serviceIdOrClassName, serviceIdOrClassName, timeout, hostname, port, None) + + def typedActorFor[T](intfClass: Class[T], serviceIdOrClassName: String, timeout: Long, hostname: String, port: Int, loader: ClassLoader): T = + typedActorFor(intfClass, serviceIdOrClassName, serviceIdOrClassName, timeout, hostname, port, Some(loader)) + + def typedActorFor[T](intfClass: Class[T], serviceId: String, implClassName: String, timeout: Long, hostname: String, port: Int, loader: ClassLoader): T = + typedActorFor(intfClass, serviceId, implClassName, timeout, hostname, port, Some(loader)) + + @deprecated("Will be removed after 1.1", "1.1") + def clientManagedActorOf(factory: () => Actor, host: String, port: Int): ActorRef + + /** + * Clean-up all open connections. + */ + def shutdownClientModule(): Unit + + /** + * Shuts down a specific client connected to the supplied remote address returns true if successful + */ + def shutdownClientConnection(address: InetSocketAddress): Boolean + + /** + * Restarts a specific client connected to the supplied remote address, but only if the client is not shut down + */ + def restartClientConnection(address: InetSocketAddress): Boolean + + /** Methods that needs to be implemented by a transport **/ + + protected[akka] def typedActorFor[T](intfClass: Class[T], serviceId: String, implClassName: String, timeout: Long, host: String, port: Int, loader: Option[ClassLoader]): T + + protected[akka] def actorFor(serviceId: String, className: String, timeout: Long, hostname: String, port: Int, loader: Option[ClassLoader]): ActorRef + + protected[akka] def send[T](message: Any, + senderOption: Option[ActorRef], + senderFuture: Option[CompletableFuture[T]], + remoteAddress: InetSocketAddress, + timeout: Long, + isOneWay: Boolean, + actorRef: ActorRef, + typedActorInfo: Option[Tuple2[String, String]], + actorType: ActorType, + loader: Option[ClassLoader]): Option[CompletableFuture[T]] + + private[akka] def registerSupervisorForActor(actorRef: ActorRef): ActorRef + + private[akka] def deregisterSupervisorForActor(actorRef: ActorRef): ActorRef + + @deprecated("Will be removed after 1.1", "1.1") + private[akka] def registerClientManagedActor(hostname: String, port: Int, uuid: Uuid): Unit + + @deprecated("Will be removed after 1.1", "1.1") + private[akka] def unregisterClientManagedActor(hostname: String, port: Int, uuid: Uuid): Unit +} diff --git a/test/disabled/presentation/akka/src/akka/routing/Iterators.scala b/test/disabled/presentation/akka/src/akka/routing/Iterators.scala new file mode 100644 index 0000000000..315e7bea51 --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/routing/Iterators.scala @@ -0,0 +1,49 @@ +/** + * Copyright (C) 2009-2011 Scalable Solutions AB + */ + +package akka.routing + +import akka.actor.ActorRef +import scala.collection.JavaConversions._ +import scala.collection.immutable.Seq + +/** + * An Iterator that is either always empty or yields an infinite number of Ts. + */ +trait InfiniteIterator[T] extends Iterator[T] { + val items: Seq[T] +} + +/** + * CyclicIterator is a round-robin style InfiniteIterator that cycles the supplied List. + */ +case class CyclicIterator[T](val items: Seq[T]) extends InfiniteIterator[T] { + def this(items: java.util.List[T]) = this(items.toList) + + @volatile + private[this] var current: Seq[T] = items + + def hasNext = items != Nil + + def next = { + val nc = if (current == Nil) items else current + current = nc.tail + nc.head + } + + override def exists(f: T => Boolean): Boolean = items.exists(f) +} + +/** + * This InfiniteIterator always returns the Actor that has the currently smallest mailbox + * useful for work-stealing. + */ +case class SmallestMailboxFirstIterator(val items: Seq[ActorRef]) extends InfiniteIterator[ActorRef] { + def this(items: java.util.List[ActorRef]) = this(items.toList) + def hasNext = items != Nil + + def next = items.reduceLeft((a1, a2) => if (a1.mailboxSize < a2.mailboxSize) a1 else a2) + + override def exists(f: ActorRef => Boolean): Boolean = items.exists(f) +} diff --git a/test/disabled/presentation/akka/src/akka/routing/Listeners.scala b/test/disabled/presentation/akka/src/akka/routing/Listeners.scala new file mode 100644 index 0000000000..04f6c1259f --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/routing/Listeners.scala @@ -0,0 +1,37 @@ +/** + * Copyright (C) 2009-2011 Scalable Solutions AB + */ + +package akka.routing + +import akka.actor.{ Actor, ActorRef } +import java.util.concurrent.ConcurrentSkipListSet +import scala.collection.JavaConversions._ + +sealed trait ListenerMessage +case class Listen(listener: ActorRef) extends ListenerMessage +case class Deafen(listener: ActorRef) extends ListenerMessage +case class WithListeners(f: (ActorRef) => Unit) extends ListenerMessage + +/** + * Listeners is a generic trait to implement listening capability on an Actor. + *

      + * Use the gossip(msg) method to have it sent to the listeners. + *

      + * Send Listen(self) to start listening. + *

      + * Send Deafen(self) to stop listening. + *

      + * Send WithListeners(fun) to traverse the current listeners. + */ +trait Listeners { self: Actor => + private val listeners = new ConcurrentSkipListSet[ActorRef] + + protected def listenerManagement: Receive = { + case Listen(l) => listeners add l + case Deafen(l) => listeners remove l + case WithListeners(f) => listeners foreach f + } + + protected def gossip(msg: Any) = listeners foreach (_ ! msg) +} diff --git a/test/disabled/presentation/akka/src/akka/routing/Pool.scala b/test/disabled/presentation/akka/src/akka/routing/Pool.scala new file mode 100644 index 0000000000..0fd1bc8f49 --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/routing/Pool.scala @@ -0,0 +1,292 @@ +/** + * Copyright (C) 2009-2011 Scalable Solutions AB + */ + +package akka.routing + +import akka.actor.{ Actor, ActorRef, PoisonPill } +import java.util.concurrent.TimeUnit + +/** + * Actor pooling + * + * An actor pool is an message router for a set of delegate actors. The pool is an actor itself. + * There are a handful of basic concepts that need to be understood when working with and defining your pool. + * + * Selectors - A selector is a trait that determines how and how many pooled actors will receive an incoming message. + * Capacitors - A capacitor is a trait that influences the size of pool. There are effectively two types. + * The first determines the size itself - either fixed or bounded. + * The second determines how to adjust of the pool according to some internal pressure characteristic. + * Filters - A filter can be used to refine the raw pressure value returned from a capacitor. + * + * It should be pointed out that all actors in the pool are treated as essentially equivalent. This is not to say + * that one couldn't instance different classes within the pool, only that the pool, when selecting and routing, + * will not take any type information into consideration. + * + * @author Garrick Evans + */ + +object ActorPool { + case object Stat + case class Stats(size: Int) +} + +/** + * Defines the nature of an actor pool. + */ +trait ActorPool { + def instance(): ActorRef //Question, Instance of what? + def capacity(delegates: Seq[ActorRef]): Int //Question, What is the semantics of this return value? + def select(delegates: Seq[ActorRef]): Tuple2[Iterator[ActorRef], Int] //Question, Why does select return this instead of an ordered Set? +} + +/** + * A default implementation of a pool, on each message to route, + * - checks the current capacity and adjusts accordingly if needed + * - routes the incoming message to a selection set of delegate actors + */ +trait DefaultActorPool extends ActorPool { this: Actor => + import ActorPool._ + import collection.mutable.LinkedList + import akka.actor.MaximumNumberOfRestartsWithinTimeRangeReached + + protected var _delegates = Vector[ActorRef]() + private var _lastCapacityChange = 0 + private var _lastSelectorCount = 0 + + override def postStop() = _delegates foreach { delegate => + try { + delegate ! PoisonPill + } catch { case e: Exception => } //Ignore any exceptions here + } + + protected def _route(): Receive = { + // for testing... + case Stat => + self reply_? Stats(_delegates length) + case max: MaximumNumberOfRestartsWithinTimeRangeReached => + _delegates = _delegates filterNot { _.uuid == max.victim.uuid } + case msg => + resizeIfAppropriate() + + select(_delegates) match { + case (selectedDelegates, count) => + _lastSelectorCount = count + selectedDelegates foreach { _ forward msg } //Should we really send the same message to several actors? + } + } + + private def resizeIfAppropriate() { + val requestedCapacity = capacity(_delegates) + val newDelegates = requestedCapacity match { + case qty if qty > 0 => + _delegates ++ { + for (i ← 0 until requestedCapacity) yield { + val delegate = instance() + self startLink delegate + delegate + } + } + case qty if qty < 0 => + _delegates.splitAt(_delegates.length + requestedCapacity) match { + case (keep, abandon) => + abandon foreach { _ ! PoisonPill } + keep + } + case _ => _delegates //No change + } + + _lastCapacityChange = requestedCapacity + _delegates = newDelegates + } +} + +/** + * Selectors + * These traits define how, when a message needs to be routed, delegate(s) are chosen from the pool + */ + +/** + * Returns the set of delegates with the least amount of message backlog. + */ +trait SmallestMailboxSelector { + def selectionCount: Int + def partialFill: Boolean + + def select(delegates: Seq[ActorRef]): Tuple2[Iterator[ActorRef], Int] = { + var set: Seq[ActorRef] = Nil + var take = if (partialFill) math.min(selectionCount, delegates.length) else selectionCount + + while (take > 0) { + set = delegates.sortWith(_.mailboxSize < _.mailboxSize).take(take) ++ set //Question, doesn't this risk selecting the same actor multiple times? + take -= set.size + } + + (set.iterator, set.size) + } +} + +/** + * Returns the set of delegates that occur sequentially 'after' the last delegate from the previous selection + */ +trait RoundRobinSelector { + private var _last: Int = -1; + + def selectionCount: Int + def partialFill: Boolean + + def select(delegates: Seq[ActorRef]): Tuple2[Iterator[ActorRef], Int] = { + val length = delegates.length + val take = if (partialFill) math.min(selectionCount, length) + else selectionCount + + val set = + for (i ← 0 until take) yield { + _last = (_last + 1) % length + delegates(_last) + } + + (set.iterator, set.size) + } +} + +/** + * Capacitors + * These traits define how to alter the size of the pool + */ + +/** + * Ensures a fixed number of delegates in the pool + */ +trait FixedSizeCapacitor { + def limit: Int + def capacity(delegates: Seq[ActorRef]): Int = (limit - delegates.size) max 0 +} + +/** + * Constrains the pool capacity to a bounded range + */ +trait BoundedCapacitor { + def lowerBound: Int + def upperBound: Int + + def capacity(delegates: Seq[ActorRef]): Int = { + val current = delegates length + val delta = _eval(delegates) + val proposed = current + delta + + if (proposed < lowerBound) delta + (lowerBound - proposed) + else if (proposed > upperBound) delta - (proposed - upperBound) + else delta + } + + protected def _eval(delegates: Seq[ActorRef]): Int +} + +/** + * Returns the number of delegates required to manage the current message backlogs + */ +trait MailboxPressureCapacitor { + def pressureThreshold: Int + def pressure(delegates: Seq[ActorRef]): Int = + delegates count { _.mailboxSize > pressureThreshold } +} + +/** + * Returns the number of delegates required to respond to the number of pending futures + */ +trait ActiveFuturesPressureCapacitor { + def pressure(delegates: Seq[ActorRef]): Int = + delegates count { _.senderFuture.isDefined } +} + +/** + */ +trait CapacityStrategy { + import ActorPool._ + + def pressure(delegates: Seq[ActorRef]): Int + def filter(pressure: Int, capacity: Int): Int + + protected def _eval(delegates: Seq[ActorRef]): Int = filter(pressure(delegates), delegates.size) +} + +trait FixedCapacityStrategy extends FixedSizeCapacitor +trait BoundedCapacityStrategy extends CapacityStrategy with BoundedCapacitor + +/** + * Filters + * These traits refine the raw pressure reading into a more appropriate capacity delta. + */ + +/** + * The basic filter trait that composes ramp-up and and back-off subfiltering. + */ +trait Filter { + def rampup(pressure: Int, capacity: Int): Int + def backoff(pressure: Int, capacity: Int): Int + + // pass through both filters just to be sure any internal counters + // are updated consistently. ramping up is always + and backing off + // is always - and each should return 0 otherwise... + def filter(pressure: Int, capacity: Int): Int = + rampup(pressure, capacity) + backoff(pressure, capacity) +} + +trait BasicFilter extends Filter with BasicRampup with BasicBackoff + +/** + * Filter performs steady incremental growth using only the basic ramp-up subfilter + */ +trait BasicNoBackoffFilter extends BasicRampup { + def filter(pressure: Int, capacity: Int): Int = rampup(pressure, capacity) +} + +/** + * Basic incremental growth as a percentage of the current pool capacity + */ +trait BasicRampup { + def rampupRate: Double + + def rampup(pressure: Int, capacity: Int): Int = + if (pressure < capacity) 0 else math.ceil(rampupRate * capacity) toInt +} + +/** + * Basic decrement as a percentage of the current pool capacity + */ +trait BasicBackoff { + def backoffThreshold: Double + def backoffRate: Double + + def backoff(pressure: Int, capacity: Int): Int = + if (capacity > 0 && pressure / capacity < backoffThreshold) math.ceil(-1.0 * backoffRate * capacity) toInt else 0 +} +/** + * This filter tracks the average pressure over the lifetime of the pool (or since last reset) and + * will begin to reduce capacity once this value drops below the provided threshold. The number of + * delegates to cull from the pool is determined by some scaling factor (the backoffRate) multiplied + * by the difference in capacity and pressure. + */ +trait RunningMeanBackoff { + def backoffThreshold: Double + def backoffRate: Double + + private var _pressure: Double = 0.0 + private var _capacity: Double = 0.0 + + def backoff(pressure: Int, capacity: Int): Int = { + _pressure += pressure + _capacity += capacity + + if (capacity > 0 && pressure / capacity < backoffThreshold + && _capacity > 0 && _pressure / _capacity < backoffThreshold) //Why does the entire clause need to be true? + math.floor(-1.0 * backoffRate * (capacity - pressure)).toInt + else 0 + } + + def backoffReset { + _pressure = 0.0 + _capacity = 0.0 + } +} diff --git a/test/disabled/presentation/akka/src/akka/routing/Routers.scala b/test/disabled/presentation/akka/src/akka/routing/Routers.scala new file mode 100644 index 0000000000..a4c34c5c67 --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/routing/Routers.scala @@ -0,0 +1,87 @@ +/** + * Copyright (C) 2009-2011 Scalable Solutions AB + */ + +package akka.routing + +import akka.actor.{ UntypedActor, Actor, ActorRef } + +/** + * A Dispatcher is a trait whose purpose is to route incoming messages to actors. + */ +trait Dispatcher { this: Actor => + + protected def transform(msg: Any): Any = msg + + protected def routes: PartialFunction[Any, ActorRef] + + protected def broadcast(message: Any) {} + + protected def dispatch: Receive = { + case Routing.Broadcast(message) => + broadcast(message) + case a if routes.isDefinedAt(a) => + if (isSenderDefined) routes(a).forward(transform(a))(someSelf) + else routes(a).!(transform(a))(None) + } + + def receive = dispatch + + private def isSenderDefined = self.senderFuture.isDefined || self.sender.isDefined +} + +/** + * An UntypedDispatcher is an abstract class whose purpose is to route incoming messages to actors. + */ +abstract class UntypedDispatcher extends UntypedActor { + protected def transform(msg: Any): Any = msg + + protected def route(msg: Any): ActorRef + + protected def broadcast(message: Any) {} + + private def isSenderDefined = self.senderFuture.isDefined || self.sender.isDefined + + @throws(classOf[Exception]) + def onReceive(msg: Any): Unit = { + if (msg.isInstanceOf[Routing.Broadcast]) broadcast(msg.asInstanceOf[Routing.Broadcast].message) + else { + val r = route(msg) + if (r eq null) throw new IllegalStateException("No route for " + msg + " defined!") + if (isSenderDefined) r.forward(transform(msg))(someSelf) + else r.!(transform(msg))(None) + } + } +} + +/** + * A LoadBalancer is a specialized kind of Dispatcher, that is supplied an InfiniteIterator of targets + * to dispatch incoming messages to. + */ +trait LoadBalancer extends Dispatcher { self: Actor => + protected def seq: InfiniteIterator[ActorRef] + + protected def routes = { + case x if seq.hasNext => seq.next + } + + override def broadcast(message: Any) = seq.items.foreach(_ ! message) + + override def isDefinedAt(msg: Any) = seq.exists(_.isDefinedAt(msg)) +} + +/** + * A UntypedLoadBalancer is a specialized kind of UntypedDispatcher, that is supplied an InfiniteIterator of targets + * to dispatch incoming messages to. + */ +abstract class UntypedLoadBalancer extends UntypedDispatcher { + protected def seq: InfiniteIterator[ActorRef] + + protected def route(msg: Any) = + if (seq.hasNext) seq.next + else null + + override def broadcast(message: Any) = seq.items.foreach(_ ! message) + + override def isDefinedAt(msg: Any) = seq.exists(_.isDefinedAt(msg)) +} diff --git a/test/disabled/presentation/akka/src/akka/routing/Routing.scala b/test/disabled/presentation/akka/src/akka/routing/Routing.scala new file mode 100644 index 0000000000..befc124248 --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/routing/Routing.scala @@ -0,0 +1,64 @@ +/** + * Copyright (C) 2009-2011 Scalable Solutions AB + */ + +package akka.routing + +import akka.actor.{ Actor, ActorRef } +import akka.actor.Actor._ + +object Routing { + + sealed trait RoutingMessage + case class Broadcast(message: Any) extends RoutingMessage + + type PF[A, B] = PartialFunction[A, B] + + /** + * Creates a new PartialFunction whose isDefinedAt is a combination + * of the two parameters, and whose apply is first to call filter.apply + * and then filtered.apply. + */ + def filter[A, B](filter: PF[A, Unit], filtered: PF[A, B]): PF[A, B] = { + case a: A if filtered.isDefinedAt(a) && filter.isDefinedAt(a) => + filter(a) + filtered(a) + } + + /** + * Interceptor is a filter(x,y) where x.isDefinedAt is considered to be always true. + */ + def intercept[A, B](interceptor: (A) => Unit, interceptee: PF[A, B]): PF[A, B] = + filter({ case a if a.isInstanceOf[A] => interceptor(a) }, interceptee) + + /** + * Creates a LoadBalancer from the thunk-supplied InfiniteIterator. + */ + def loadBalancerActor(actors: => InfiniteIterator[ActorRef]): ActorRef = + actorOf(new Actor with LoadBalancer { + val seq = actors + }).start() + + /** + * Creates a Dispatcher given a routing and a message-transforming function. + */ + def dispatcherActor(routing: PF[Any, ActorRef], msgTransformer: (Any) => Any): ActorRef = + actorOf(new Actor with Dispatcher { + override def transform(msg: Any) = msgTransformer(msg) + def routes = routing + }).start() + + /** + * Creates a Dispatcher given a routing. + */ + def dispatcherActor(routing: PF[Any, ActorRef]): ActorRef = actorOf(new Actor with Dispatcher { + def routes = routing + }).start() + + /** + * Creates an actor that pipes all incoming messages to + * both another actor and through the supplied function + */ + def loggerActor(actorToLog: ActorRef, logger: (Any) => Unit): ActorRef = + dispatcherActor({ case _ => actorToLog }, logger) +} diff --git a/test/disabled/presentation/akka/src/akka/util/Address.scala b/test/disabled/presentation/akka/src/akka/util/Address.scala new file mode 100644 index 0000000000..65b5c0a834 --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/util/Address.scala @@ -0,0 +1,29 @@ +/** + * Copyright (C) 2009-2011 Scalable Solutions AB + */ +package akka.util + +import java.net.InetSocketAddress + +object Address { + def apply(hostname: String, port: Int) = new Address(hostname, port) + def apply(inetAddress: InetSocketAddress): Address = inetAddress match { + case null => null + case inet => new Address(inet.getAddress.getHostAddress, inet.getPort) + } +} + +class Address(val hostname: String, val port: Int) { + override val hashCode: Int = { + var result = HashCode.SEED + result = HashCode.hash(result, hostname) + result = HashCode.hash(result, port) + result + } + + override def equals(that: Any): Boolean = { + that.isInstanceOf[Address] && + that.asInstanceOf[Address].hostname == hostname && + that.asInstanceOf[Address].port == port + } +} diff --git a/test/disabled/presentation/akka/src/akka/util/AkkaLoader.scala b/test/disabled/presentation/akka/src/akka/util/AkkaLoader.scala new file mode 100644 index 0000000000..cb246f2ecf --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/util/AkkaLoader.scala @@ -0,0 +1,94 @@ +/** + * Copyright (C) 2009-2011 Scalable Solutions AB + */ + +package akka.util + +import akka.config.Config +import akka.actor.Actor + +/* + * This class is responsible for booting up a stack of bundles and then shutting them down + */ +class AkkaLoader { + private val hasBooted = new Switch(false) + + @volatile + private var _bundles: Option[Bootable] = None + + def bundles = _bundles; + + /* + * Boot initializes the specified bundles + */ + def boot(withBanner: Boolean, b: Bootable): Unit = hasBooted switchOn { + if (withBanner) printBanner() + println("Starting Akka...") + b.onLoad + Thread.currentThread.setContextClassLoader(getClass.getClassLoader) + _bundles = Some(b) + println("Akka started successfully") + } + + /* + * Shutdown, well, shuts down the bundles used in boot + */ + def shutdown() { + hasBooted switchOff { + println("Shutting down Akka...") + _bundles.foreach(_.onUnload) + _bundles = None + Actor.shutdownHook.run + println("Akka succesfully shut down") + } + } + + private def printBanner() { + println(""" +============================================================================== + + ZZ: + ZZZZ + ZZZZZZ + ZZZ' ZZZ + ~7 7ZZ' ZZZ + :ZZZ: IZZ' ZZZ + ,OZZZZ.~ZZ? ZZZ + ZZZZ' 'ZZZ$ ZZZ + . $ZZZ ~ZZ$ ZZZ + .=Z?. .ZZZO ~ZZ7 OZZ + .ZZZZ7..:ZZZ~ 7ZZZ ZZZ~ + .$ZZZ$Z+.ZZZZ ZZZ: ZZZ$ + .,ZZZZ?' =ZZO= .OZZ 'ZZZ + .$ZZZZ+ .ZZZZ IZZZ ZZZ$ + .ZZZZZ' .ZZZZ' .ZZZ$ ?ZZZ + .ZZZZZZ' .OZZZ? ?ZZZ 'ZZZ$ + .?ZZZZZZ' .ZZZZ? .ZZZ? 'ZZZO + .+ZZZZZZ?' .7ZZZZ' .ZZZZ :ZZZZ + .ZZZZZZ$' .?ZZZZZ' .~ZZZZ 'ZZZZ. + + + NNNNN $NNNN+ + NNNNN $NNNN+ + NNNNN $NNNN+ + NNNNN $NNNN+ + NNNNN $NNNN+ + =NNNNNNNNND$ NNNNN DDDDDD: $NNNN+ DDDDDN NDDNNNNNNNN, + NNNNNNNNNNNNND NNNNN DNNNNN $NNNN+ 8NNNNN= :NNNNNNNNNNNNNN + NNNNN$ DNNNNN NNNNN $NNNNN~ $NNNN+ NNNNNN NNNNN, :NNNNN+ + ?DN~ NNNNN NNNNN MNNNNN $NNNN+:NNNNN7 $ND =NNNNN + DNNNNN NNNNNDNNNN$ $NNNNDNNNNN :DNNNNN + ZNDNNNNNNNNND NNNNNNNNNND, $NNNNNNNNNNN DNDNNNNNNNNNN + NNNNNNNDDINNNNN NNNNNNNNNNND $NNNNNNNNNNND ONNNNNNND8+NNNNN + :NNNND NNNNN NNNNNN DNNNN, $NNNNNO 7NNNND NNNNNO :NNNNN + DNNNN NNNNN NNNNN DNNNN $NNNN+ 8NNNNN NNNNN $NNNNN + DNNNNO NNNNNN NNNNN NNNNN $NNNN+ NNNNN$ NNNND, ,NNNNND + NNNNNNDDNNNNNNNN NNNNN =NNNNN $NNNN+ DNNNN? DNNNNNNDNNNNNNNND + NNNNNNNNN NNNN$ NNNNN 8NNNND $NNNN+ NNNNN= ,DNNNNNNND NNNNN$ + +============================================================================== + Running version %s +============================================================================== +""".format(Config.VERSION)) + } +} diff --git a/test/disabled/presentation/akka/src/akka/util/Bootable.scala b/test/disabled/presentation/akka/src/akka/util/Bootable.scala new file mode 100644 index 0000000000..d07643e1ac --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/util/Bootable.scala @@ -0,0 +1,10 @@ +/** + * Copyright (C) 2009-2011 Scalable Solutions AB + */ + +package akka.util + +trait Bootable { + def onLoad() {} + def onUnload() {} +} diff --git a/test/disabled/presentation/akka/src/akka/util/BoundedBlockingQueue.scala b/test/disabled/presentation/akka/src/akka/util/BoundedBlockingQueue.scala new file mode 100644 index 0000000000..f8deda746c --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/util/BoundedBlockingQueue.scala @@ -0,0 +1,326 @@ +/** + * Copyright (C) 2009-2011 Scalable Solutions AB + */ + +package akka.util + +import java.util.concurrent.locks.ReentrantLock +import java.util.concurrent.{ TimeUnit, BlockingQueue } +import java.util.{ AbstractQueue, Queue, Collection, Iterator } + +class BoundedBlockingQueue[E <: AnyRef]( + val maxCapacity: Int, private val backing: Queue[E]) extends AbstractQueue[E] with BlockingQueue[E] { + + backing match { + case null => throw new IllegalArgumentException("Backing Queue may not be null") + case b: BlockingQueue[_] => + require(maxCapacity > 0) + require(b.size() == 0) + require(b.remainingCapacity >= maxCapacity) + case b: Queue[_] => + require(b.size() == 0) + require(maxCapacity > 0) + } + + protected val lock = new ReentrantLock(false) + + private val notEmpty = lock.newCondition() + private val notFull = lock.newCondition() + + def put(e: E): Unit = { //Blocks until not full + if (e eq null) throw new NullPointerException + lock.lock() + try { + while (backing.size() == maxCapacity) + notFull.await() + require(backing.offer(e)) + notEmpty.signal() + } finally { + lock.unlock() + } + } + + def take(): E = { //Blocks until not empty + lock.lockInterruptibly() + try { + while (backing.size() == 0) + notEmpty.await() + val e = backing.poll() + require(e ne null) + notFull.signal() + e + } finally { + lock.unlock() + } + } + + def offer(e: E): Boolean = { //Tries to do it immediately, if fail return false + if (e eq null) throw new NullPointerException + lock.lock() + try { + if (backing.size() == maxCapacity) false + else { + require(backing.offer(e)) //Should never fail + notEmpty.signal() + true + } + } finally { + lock.unlock() + } + } + + def offer(e: E, timeout: Long, unit: TimeUnit): Boolean = { //Tries to do it within the timeout, return false if fail + if (e eq null) throw new NullPointerException + var nanos = unit.toNanos(timeout) + lock.lockInterruptibly() + try { + while (backing.size() == maxCapacity) { + if (nanos <= 0) + return false + else + nanos = notFull.awaitNanos(nanos) + } + require(backing.offer(e)) //Should never fail + notEmpty.signal() + true + } finally { + lock.unlock() + } + } + + def poll(timeout: Long, unit: TimeUnit): E = { //Tries to do it within the timeout, returns null if fail + var nanos = unit.toNanos(timeout) + lock.lockInterruptibly() + try { + var result: E = null.asInstanceOf[E] + var hasResult = false + while (!hasResult) { + hasResult = backing.poll() match { + case null if nanos <= 0 => + result = null.asInstanceOf[E] + true + case null => + try { + nanos = notEmpty.awaitNanos(nanos) + } catch { + case ie: InterruptedException => + notEmpty.signal() + throw ie + } + false + case e => + notFull.signal() + result = e + true + } + } + result + } finally { + lock.unlock() + } + } + + def poll(): E = { //Tries to remove the head of the queue immediately, if fail, return null + lock.lock() + try { + backing.poll() match { + case null => null.asInstanceOf[E] + case e => + notFull.signal() + e + } + } finally { + lock.unlock + } + } + + override def remove(e: AnyRef): Boolean = { //Tries to do it immediately, if fail, return false + if (e eq null) throw new NullPointerException + lock.lock() + try { + if (backing remove e) { + notFull.signal() + true + } else false + } finally { + lock.unlock() + } + } + + override def contains(e: AnyRef): Boolean = { + if (e eq null) throw new NullPointerException + lock.lock() + try { + backing contains e + } finally { + lock.unlock() + } + } + + override def clear(): Unit = { + lock.lock() + try { + backing.clear + } finally { + lock.unlock() + } + } + + def remainingCapacity(): Int = { + lock.lock() + try { + maxCapacity - backing.size() + } finally { + lock.unlock() + } + } + + def size(): Int = { + lock.lock() + try { + backing.size() + } finally { + lock.unlock() + } + } + + def peek(): E = { + lock.lock() + try { + backing.peek() + } finally { + lock.unlock() + } + } + + def drainTo(c: Collection[_ >: E]): Int = drainTo(c, Int.MaxValue) + + def drainTo(c: Collection[_ >: E], maxElements: Int): Int = { + if (c eq null) throw new NullPointerException + if (c eq this) throw new IllegalArgumentException + if (maxElements <= 0) 0 + else { + lock.lock() + try { + var n = 0 + var e: E = null.asInstanceOf[E] + while (n < maxElements) { + backing.poll() match { + case null => return n + case e => + c add e + n += 1 + } + } + n + } finally { + lock.unlock() + } + } + } + + override def containsAll(c: Collection[_]): Boolean = { + lock.lock() + try { + backing containsAll c + } finally { + lock.unlock() + } + } + + override def removeAll(c: Collection[_]): Boolean = { + lock.lock() + try { + if (backing.removeAll(c)) { + val sz = backing.size() + if (sz < maxCapacity) notFull.signal() + if (sz > 0) notEmpty.signal() //FIXME needed? + true + } else false + } finally { + lock.unlock() + } + } + + override def retainAll(c: Collection[_]): Boolean = { + lock.lock() + try { + if (backing.retainAll(c)) { + val sz = backing.size() + if (sz < maxCapacity) notFull.signal() //FIXME needed? + if (sz > 0) notEmpty.signal() + true + } else false + } finally { + lock.unlock() + } + } + + def iterator(): Iterator[E] = { + lock.lock + try { + val elements = backing.toArray + new Iterator[E] { + var at = 0 + var last = -1 + + def hasNext(): Boolean = at < elements.length + + def next(): E = { + if (at >= elements.length) throw new NoSuchElementException + last = at + at += 1 + elements(last).asInstanceOf[E] + } + + def remove(): Unit = { + if (last < 0) throw new IllegalStateException + val target = elements(last) + last = -1 //To avoid 2 subsequent removes without a next in between + lock.lock() + try { + val i = backing.iterator() + while (i.hasNext) { + if (i.next eq target) { + i.remove() + notFull.signal() + return () + } + } + } finally { + lock.unlock() + } + } + } + } finally { + lock.unlock + } + } + + override def toArray(): Array[AnyRef] = { + lock.lock() + try { + backing.toArray + } finally { + lock.unlock() + } + } + + override def isEmpty(): Boolean = { + lock.lock() + try { + backing.isEmpty() + } finally { + lock.unlock() + } + } + + override def toArray[X](a: Array[X with AnyRef]) = { + lock.lock() + try { + backing.toArray[X](a) + } finally { + lock.unlock() + } + } +} diff --git a/test/disabled/presentation/akka/src/akka/util/Crypt.scala b/test/disabled/presentation/akka/src/akka/util/Crypt.scala new file mode 100644 index 0000000000..3ce2d559a2 --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/util/Crypt.scala @@ -0,0 +1,44 @@ +/** + * Copyright (C) 2009-2011 Scalable Solutions AB + */ + +package akka.util + +import java.security.{ MessageDigest, SecureRandom } + +/** + * @author Jonas Bonér + */ +object Crypt { + val hex = "0123456789ABCDEF" + val lineSeparator = System.getProperty("line.separator") + + lazy val random = SecureRandom.getInstance("SHA1PRNG") + + def md5(text: String): String = md5(unifyLineSeparator(text).getBytes("ASCII")) + + def md5(bytes: Array[Byte]): String = digest(bytes, MessageDigest.getInstance("MD5")) + + def sha1(text: String): String = sha1(unifyLineSeparator(text).getBytes("ASCII")) + + def sha1(bytes: Array[Byte]): String = digest(bytes, MessageDigest.getInstance("SHA1")) + + def generateSecureCookie: String = { + val bytes = Array.fill(32)(0.byteValue) + random.nextBytes(bytes) + sha1(bytes) + } + + def digest(bytes: Array[Byte], md: MessageDigest): String = { + md.update(bytes) + hexify(md.digest) + } + + def hexify(bytes: Array[Byte]): String = { + val builder = new StringBuilder + bytes.foreach { byte => builder.append(hex.charAt((byte & 0xF) >> 4)).append(hex.charAt(byte & 0xF)) } + builder.toString + } + + private def unifyLineSeparator(text: String): String = text.replaceAll(lineSeparator, "\n") +} diff --git a/test/disabled/presentation/akka/src/akka/util/Duration.scala b/test/disabled/presentation/akka/src/akka/util/Duration.scala new file mode 100644 index 0000000000..316cb86689 --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/util/Duration.scala @@ -0,0 +1,437 @@ +/** + * Copyright (C) 2009-2011 Scalable Solutions AB + */ + +package akka.util + +import java.util.concurrent.TimeUnit +import TimeUnit._ +import java.lang.{ Long => JLong, Double => JDouble } + +object Duration { + def apply(length: Long, unit: TimeUnit): Duration = new FiniteDuration(length, unit) + def apply(length: Double, unit: TimeUnit): Duration = fromNanos(unit.toNanos(1) * length) + def apply(length: Long, unit: String): Duration = new FiniteDuration(length, timeUnit(unit)) + + def fromNanos(nanos: Long): Duration = { + if (nanos % 86400000000000L == 0) { + Duration(nanos / 86400000000000L, DAYS) + } else if (nanos % 3600000000000L == 0) { + Duration(nanos / 3600000000000L, HOURS) + } else if (nanos % 60000000000L == 0) { + Duration(nanos / 60000000000L, MINUTES) + } else if (nanos % 1000000000L == 0) { + Duration(nanos / 1000000000L, SECONDS) + } else if (nanos % 1000000L == 0) { + Duration(nanos / 1000000L, MILLISECONDS) + } else if (nanos % 1000L == 0) { + Duration(nanos / 1000L, MICROSECONDS) + } else { + Duration(nanos, NANOSECONDS) + } + } + + def fromNanos(nanos: Double): Duration = fromNanos((nanos + 0.5).asInstanceOf[Long]) + + /** + * Construct a Duration by parsing a String. In case of a format error, a + * RuntimeException is thrown. See `unapply(String)` for more information. + */ + def apply(s: String): Duration = unapply(s) getOrElse sys.error("format error") + + /** + * Deconstruct a Duration into length and unit if it is finite. + */ + def unapply(d: Duration): Option[(Long, TimeUnit)] = { + if (d.finite_?) { + Some((d.length, d.unit)) + } else { + None + } + } + + private val RE = ("""^\s*(\d+(?:\.\d+)?)\s*""" + // length part + "(?:" + // units are distinguished in separate match groups + "(d|day|days)|" + + "(h|hour|hours)|" + + "(min|minute|minutes)|" + + "(s|sec|second|seconds)|" + + "(ms|milli|millis|millisecond|milliseconds)|" + + "(µs|micro|micros|microsecond|microseconds)|" + + "(ns|nano|nanos|nanosecond|nanoseconds)" + + """)\s*$""").r // close the non-capturing group + private val REinf = """^\s*Inf\s*$""".r + private val REminf = """^\s*(?:-\s*|Minus)Inf\s*""".r + + /** + * Parse String, return None if no match. Format is `""`, where + * whitespace is allowed before, between and after the parts. Infinities are + * designated by `"Inf"` and `"-Inf"` or `"MinusInf"`. + */ + def unapply(s: String): Option[Duration] = s match { + case RE(length, d, h, m, s, ms, mus, ns) => + if (d ne null) Some(Duration(JDouble.parseDouble(length), DAYS)) else if (h ne null) Some(Duration(JDouble.parseDouble(length), HOURS)) else if (m ne null) Some(Duration(JDouble.parseDouble(length), MINUTES)) else if (s ne null) Some(Duration(JDouble.parseDouble(length), SECONDS)) else if (ms ne null) Some(Duration(JDouble.parseDouble(length), MILLISECONDS)) else if (mus ne null) Some(Duration(JDouble.parseDouble(length), MICROSECONDS)) else if (ns ne null) Some(Duration(JDouble.parseDouble(length), NANOSECONDS)) else + sys.error("made some error in regex (should not be possible)") + case REinf() => Some(Inf) + case REminf() => Some(MinusInf) + case _ => None + } + + /** + * Parse TimeUnit from string representation. + */ + def timeUnit(unit: String) = unit.toLowerCase match { + case "d" | "day" | "days" => DAYS + case "h" | "hour" | "hours" => HOURS + case "min" | "minute" | "minutes" => MINUTES + case "s" | "sec" | "second" | "seconds" => SECONDS + case "ms" | "milli" | "millis" | "millisecond" | "milliseconds" => MILLISECONDS + case "µs" | "micro" | "micros" | "microsecond" | "microseconds" => MICROSECONDS + case "ns" | "nano" | "nanos" | "nanosecond" | "nanoseconds" => NANOSECONDS + } + + val Zero: Duration = new FiniteDuration(0, NANOSECONDS) + + trait Infinite { + this: Duration => + + override def equals(other: Any) = false + + def +(other: Duration): Duration = + other match { + case _: this.type => this + case _: Infinite => throw new IllegalArgumentException("illegal addition of infinities") + case _ => this + } + def -(other: Duration): Duration = + other match { + case _: this.type => throw new IllegalArgumentException("illegal subtraction of infinities") + case _ => this + } + def *(factor: Double): Duration = this + def /(factor: Double): Duration = this + def /(other: Duration): Double = + other match { + case _: Infinite => throw new IllegalArgumentException("illegal division of infinities") + // maybe questionable but pragmatic: Inf / 0 => Inf + case x => Double.PositiveInfinity * (if ((this > Zero) ^ (other >= Zero)) -1 else 1) + } + + def finite_? = false + + def length: Long = throw new IllegalArgumentException("length not allowed on infinite Durations") + def unit: TimeUnit = throw new IllegalArgumentException("unit not allowed on infinite Durations") + def toNanos: Long = throw new IllegalArgumentException("toNanos not allowed on infinite Durations") + def toMicros: Long = throw new IllegalArgumentException("toMicros not allowed on infinite Durations") + def toMillis: Long = throw new IllegalArgumentException("toMillis not allowed on infinite Durations") + def toSeconds: Long = throw new IllegalArgumentException("toSeconds not allowed on infinite Durations") + def toMinutes: Long = throw new IllegalArgumentException("toMinutes not allowed on infinite Durations") + def toHours: Long = throw new IllegalArgumentException("toHours not allowed on infinite Durations") + def toDays: Long = throw new IllegalArgumentException("toDays not allowed on infinite Durations") + def toUnit(unit: TimeUnit): Double = throw new IllegalArgumentException("toUnit not allowed on infinite Durations") + + def printHMS = toString + } + + /** + * Infinite duration: greater than any other and not equal to any other, + * including itself. + */ + val Inf: Duration = new Duration with Infinite { + override def toString = "Duration.Inf" + def >(other: Duration) = true + def >=(other: Duration) = true + def <(other: Duration) = false + def <=(other: Duration) = false + def unary_- : Duration = MinusInf + } + + /** + * Infinite negative duration: lesser than any other and not equal to any other, + * including itself. + */ + val MinusInf: Duration = new Duration with Infinite { + override def toString = "Duration.MinusInf" + def >(other: Duration) = false + def >=(other: Duration) = false + def <(other: Duration) = true + def <=(other: Duration) = true + def unary_- : Duration = Inf + } + + // Java Factories + def create(length: Long, unit: TimeUnit): Duration = apply(length, unit) + def create(length: Double, unit: TimeUnit): Duration = apply(length, unit) + def create(length: Long, unit: String): Duration = apply(length, unit) + def parse(s: String): Duration = unapply(s).get +} + +/** + * Utility for working with java.util.concurrent.TimeUnit durations. + * + *

      + * Examples of usage from Java: + *

      + * import akka.util.FiniteDuration;
      + * import java.util.concurrent.TimeUnit;
      + *
      + * Duration duration = new FiniteDuration(100, MILLISECONDS);
      + * Duration duration = new FiniteDuration(5, "seconds");
      + *
      + * duration.toNanos();
      + * 
      + * + *

      + * Examples of usage from Scala: + *

      + * import akka.util.Duration
      + * import java.util.concurrent.TimeUnit
      + *
      + * val duration = Duration(100, MILLISECONDS)
      + * val duration = Duration(100, "millis")
      + *
      + * duration.toNanos
      + * duration < 1.second
      + * duration <= Duration.Inf
      + * 
      + * + *

      + * Implicits are also provided for Int, Long and Double. Example usage: + *

      + * import akka.util.duration._
      + *
      + * val duration = 100 millis
      + * 
      + * + * Extractors, parsing and arithmetic are also included: + *
      + * val d = Duration("1.2 µs")
      + * val Duration(length, unit) = 5 millis
      + * val d2 = d * 2.5
      + * val d3 = d2 + 1.millisecond
      + * 
      + */ +abstract class Duration { + def length: Long + def unit: TimeUnit + def toNanos: Long + def toMicros: Long + def toMillis: Long + def toSeconds: Long + def toMinutes: Long + def toHours: Long + def toDays: Long + def toUnit(unit: TimeUnit): Double + def printHMS: String + def <(other: Duration): Boolean + def <=(other: Duration): Boolean + def >(other: Duration): Boolean + def >=(other: Duration): Boolean + def +(other: Duration): Duration + def -(other: Duration): Duration + def *(factor: Double): Duration + def /(factor: Double): Duration + def /(other: Duration): Double + def unary_- : Duration + def finite_? : Boolean + + // Java API + def lt(other: Duration) = this < other + def lteq(other: Duration) = this <= other + def gt(other: Duration) = this > other + def gteq(other: Duration) = this >= other + def plus(other: Duration) = this + other + def minus(other: Duration) = this - other + def mul(factor: Double) = this * factor + def div(factor: Double) = this / factor + def div(other: Duration) = this / other + def neg() = -this + def isFinite() = finite_? +} + +class FiniteDuration(val length: Long, val unit: TimeUnit) extends Duration { + import Duration._ + + def this(length: Long, unit: String) = this(length, Duration.timeUnit(unit)) + + def toNanos = unit.toNanos(length) + def toMicros = unit.toMicros(length) + def toMillis = unit.toMillis(length) + def toSeconds = unit.toSeconds(length) + def toMinutes = unit.toMinutes(length) + def toHours = unit.toHours(length) + def toDays = unit.toDays(length) + def toUnit(u: TimeUnit) = long2double(toNanos) / NANOSECONDS.convert(1, u) + + override def toString = this match { + case Duration(1, DAYS) => "1 day" + case Duration(x, DAYS) => x + " days" + case Duration(1, HOURS) => "1 hour" + case Duration(x, HOURS) => x + " hours" + case Duration(1, MINUTES) => "1 minute" + case Duration(x, MINUTES) => x + " minutes" + case Duration(1, SECONDS) => "1 second" + case Duration(x, SECONDS) => x + " seconds" + case Duration(1, MILLISECONDS) => "1 millisecond" + case Duration(x, MILLISECONDS) => x + " milliseconds" + case Duration(1, MICROSECONDS) => "1 microsecond" + case Duration(x, MICROSECONDS) => x + " microseconds" + case Duration(1, NANOSECONDS) => "1 nanosecond" + case Duration(x, NANOSECONDS) => x + " nanoseconds" + } + + def printHMS = "%02d:%02d:%06.3f".format(toHours, toMinutes % 60, toMillis / 1000. % 60) + + def <(other: Duration) = { + if (other.finite_?) { + toNanos < other.asInstanceOf[FiniteDuration].toNanos + } else { + other > this + } + } + + def <=(other: Duration) = { + if (other.finite_?) { + toNanos <= other.asInstanceOf[FiniteDuration].toNanos + } else { + other >= this + } + } + + def >(other: Duration) = { + if (other.finite_?) { + toNanos > other.asInstanceOf[FiniteDuration].toNanos + } else { + other < this + } + } + + def >=(other: Duration) = { + if (other.finite_?) { + toNanos >= other.asInstanceOf[FiniteDuration].toNanos + } else { + other <= this + } + } + + def +(other: Duration) = { + if (!other.finite_?) { + other + } else { + val nanos = toNanos + other.asInstanceOf[FiniteDuration].toNanos + fromNanos(nanos) + } + } + + def -(other: Duration) = { + if (!other.finite_?) { + other + } else { + val nanos = toNanos - other.asInstanceOf[FiniteDuration].toNanos + fromNanos(nanos) + } + } + + def *(factor: Double) = fromNanos(long2double(toNanos) * factor) + + def /(factor: Double) = fromNanos(long2double(toNanos) / factor) + + def /(other: Duration) = if (other.finite_?) long2double(toNanos) / other.toNanos else 0 + + def unary_- = Duration(-length, unit) + + def finite_? = true + + override def equals(other: Any) = + other.isInstanceOf[FiniteDuration] && + toNanos == other.asInstanceOf[FiniteDuration].toNanos + + override def hashCode = toNanos.asInstanceOf[Int] +} + +class DurationInt(n: Int) { + def nanoseconds = Duration(n, NANOSECONDS) + def nanos = Duration(n, NANOSECONDS) + def nanosecond = Duration(n, NANOSECONDS) + def nano = Duration(n, NANOSECONDS) + + def microseconds = Duration(n, MICROSECONDS) + def micros = Duration(n, MICROSECONDS) + def microsecond = Duration(n, MICROSECONDS) + def micro = Duration(n, MICROSECONDS) + + def milliseconds = Duration(n, MILLISECONDS) + def millis = Duration(n, MILLISECONDS) + def millisecond = Duration(n, MILLISECONDS) + def milli = Duration(n, MILLISECONDS) + + def seconds = Duration(n, SECONDS) + def second = Duration(n, SECONDS) + + def minutes = Duration(n, MINUTES) + def minute = Duration(n, MINUTES) + + def hours = Duration(n, HOURS) + def hour = Duration(n, HOURS) + + def days = Duration(n, DAYS) + def day = Duration(n, DAYS) +} + +class DurationLong(n: Long) { + def nanoseconds = Duration(n, NANOSECONDS) + def nanos = Duration(n, NANOSECONDS) + def nanosecond = Duration(n, NANOSECONDS) + def nano = Duration(n, NANOSECONDS) + + def microseconds = Duration(n, MICROSECONDS) + def micros = Duration(n, MICROSECONDS) + def microsecond = Duration(n, MICROSECONDS) + def micro = Duration(n, MICROSECONDS) + + def milliseconds = Duration(n, MILLISECONDS) + def millis = Duration(n, MILLISECONDS) + def millisecond = Duration(n, MILLISECONDS) + def milli = Duration(n, MILLISECONDS) + + def seconds = Duration(n, SECONDS) + def second = Duration(n, SECONDS) + + def minutes = Duration(n, MINUTES) + def minute = Duration(n, MINUTES) + + def hours = Duration(n, HOURS) + def hour = Duration(n, HOURS) + + def days = Duration(n, DAYS) + def day = Duration(n, DAYS) +} + +class DurationDouble(d: Double) { + def nanoseconds = Duration(d, NANOSECONDS) + def nanos = Duration(d, NANOSECONDS) + def nanosecond = Duration(d, NANOSECONDS) + def nano = Duration(d, NANOSECONDS) + + def microseconds = Duration(d, MICROSECONDS) + def micros = Duration(d, MICROSECONDS) + def microsecond = Duration(d, MICROSECONDS) + def micro = Duration(d, MICROSECONDS) + + def milliseconds = Duration(d, MILLISECONDS) + def millis = Duration(d, MILLISECONDS) + def millisecond = Duration(d, MILLISECONDS) + def milli = Duration(d, MILLISECONDS) + + def seconds = Duration(d, SECONDS) + def second = Duration(d, SECONDS) + + def minutes = Duration(d, MINUTES) + def minute = Duration(d, MINUTES) + + def hours = Duration(d, HOURS) + def hour = Duration(d, HOURS) + + def days = Duration(d, DAYS) + def day = Duration(d, DAYS) +} diff --git a/test/disabled/presentation/akka/src/akka/util/HashCode.scala b/test/disabled/presentation/akka/src/akka/util/HashCode.scala new file mode 100644 index 0000000000..d015f12f5d --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/util/HashCode.scala @@ -0,0 +1,57 @@ +/** + * Copyright (C) 2009-2011 Scalable Solutions AB + */ + +package akka.util + +import java.lang.reflect.{ Array => JArray } +import java.lang.{ Float => JFloat, Double => JDouble } + +/** + * Set of methods which allow easy implementation of hashCode. + * + * Example: + *
      + *  override def hashCode: Int = {
      + *    var result = HashCode.SEED
      + *    //collect the contributions of various fields
      + *    result = HashCode.hash(result, fPrimitive)
      + *    result = HashCode.hash(result, fObject)
      + *    result = HashCode.hash(result, fArray)
      + *    result
      + *  }
      + * 
      + * + * @author Jonas Bonér + */ +object HashCode { + val SEED = 23 + + def hash(seed: Int, any: Any): Int = any match { + case value: Boolean => hash(seed, value) + case value: Char => hash(seed, value) + case value: Short => hash(seed, value) + case value: Int => hash(seed, value) + case value: Long => hash(seed, value) + case value: Float => hash(seed, value) + case value: Double => hash(seed, value) + case value: Byte => hash(seed, value) + case value: AnyRef => + var result = seed + if (value eq null) result = hash(result, 0) + else if (!isArray(value)) result = hash(result, value.hashCode()) + else for (id ← 0 until JArray.getLength(value)) result = hash(result, JArray.get(value, id)) // is an array + result + } + def hash(seed: Int, value: Boolean): Int = firstTerm(seed) + (if (value) 1 else 0) + def hash(seed: Int, value: Char): Int = firstTerm(seed) + value.asInstanceOf[Int] + def hash(seed: Int, value: Int): Int = firstTerm(seed) + value + def hash(seed: Int, value: Long): Int = firstTerm(seed) + (value ^ (value >>> 32)).asInstanceOf[Int] + def hash(seed: Int, value: Float): Int = hash(seed, JFloat.floatToIntBits(value)) + def hash(seed: Int, value: Double): Int = hash(seed, JDouble.doubleToLongBits(value)) + + private def firstTerm(seed: Int): Int = PRIME * seed + private def isArray(anyRef: AnyRef): Boolean = anyRef.getClass.isArray + private val PRIME = 37 +} + diff --git a/test/disabled/presentation/akka/src/akka/util/Helpers.scala b/test/disabled/presentation/akka/src/akka/util/Helpers.scala new file mode 100644 index 0000000000..48477426c9 --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/util/Helpers.scala @@ -0,0 +1,99 @@ +/** + * Copyright (C) 2009-2011 Scalable Solutions AB + */ + +package akka.util + +/** + * @author Jonas Bonér + */ +object Helpers { + + implicit def null2Option[T](t: T): Option[T] = Option(t) + + def intToBytes(value: Int): Array[Byte] = { + val bytes = new Array[Byte](4) + bytes(0) = (value >>> 24).asInstanceOf[Byte] + bytes(1) = (value >>> 16).asInstanceOf[Byte] + bytes(2) = (value >>> 8).asInstanceOf[Byte] + bytes(3) = value.asInstanceOf[Byte] + bytes + } + + def bytesToInt(bytes: Array[Byte], offset: Int): Int = { + (0 until 4).foldLeft(0)((value, index) => value + ((bytes(index + offset) & 0x000000FF) << ((4 - 1 - index) * 8))) + } + + /** + * Convenience helper to cast the given Option of Any to an Option of the given type. Will throw a ClassCastException + * if the actual type is not assignable from the given one. + */ + def narrow[T](o: Option[Any]): Option[T] = { + require((o ne null), "Option to be narrowed must not be null!") + o.asInstanceOf[Option[T]] + } + + /** + * Convenience helper to cast the given Option of Any to an Option of the given type. Will swallow a possible + * ClassCastException and return None in that case. + */ + def narrowSilently[T: Manifest](o: Option[Any]): Option[T] = + try { + narrow(o) + } catch { + case e: ClassCastException => + None + } + + /** + * Reference that can hold either a typed value or an exception. + * + * Usage: + *
      +   * scala> ResultOrError(1)
      +   * res0: ResultOrError[Int] = ResultOrError@a96606
      +   *
      +   * scala> res0()
      +   * res1: Int = 1
      +   *
      +   * scala> res0() = 3
      +   *
      +   * scala> res0()
      +   * res3: Int = 3
      +   *
      +   * scala> res0() = { println("Hello world"); 3}
      +   * Hello world
      +   *
      +   * scala> res0()
      +   * res5: Int = 3
      +   *
      +   * scala> res0() = error("Lets see what happens here...")
      +   *
      +   * scala> res0()
      +   * java.lang.RuntimeException: Lets see what happens here...
      +   *    at ResultOrError.apply(Helper.scala:11)
      +   *    at .(:6)
      +   *    at .()
      +   *    at Re...
      +   * 
      + */ + class ResultOrError[R](result: R) { + private[this] var contents: Either[R, Throwable] = Left(result) + + def update(value: => R) = { + contents = try { + Left(value) + } catch { + case (error: Throwable) => Right(error) + } + } + + def apply() = contents match { + case Left(result) => result + case Right(error) => throw error.fillInStackTrace + } + } + object ResultOrError { + def apply[R](result: R) = new ResultOrError(result) + } +} diff --git a/test/disabled/presentation/akka/src/akka/util/ListenerManagement.scala b/test/disabled/presentation/akka/src/akka/util/ListenerManagement.scala new file mode 100644 index 0000000000..7065397a45 --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/util/ListenerManagement.scala @@ -0,0 +1,81 @@ +/** + * Copyright (C) 2009-2011 Scalable Solutions AB + */ + +package akka.util + +import java.util.concurrent.ConcurrentSkipListSet +import akka.actor.{ ActorInitializationException, ActorRef } + +/** + * A manager for listener actors. Intended for mixin by observables. + * + * @author Martin Krasser + */ +trait ListenerManagement { + + private val listeners = new ConcurrentSkipListSet[ActorRef] + + /** + * Specifies whether listeners should be started when added and stopped when removed or not + */ + protected def manageLifeCycleOfListeners: Boolean = true + + /** + * Adds the listener this this registry's listener list. + * The listener is started by this method if manageLifeCycleOfListeners yields true. + */ + def addListener(listener: ActorRef) { + if (manageLifeCycleOfListeners) listener.start() + listeners add listener + } + + /** + * Removes the listener this this registry's listener list. + * The listener is stopped by this method if manageLifeCycleOfListeners yields true. + */ + def removeListener(listener: ActorRef) { + listeners remove listener + if (manageLifeCycleOfListeners) listener.stop() + } + + /* + * Returns whether there are any listeners currently + */ + def hasListeners: Boolean = !listeners.isEmpty + + /** + * Checks if a specific listener is registered. ActorInitializationException leads to removal of listener if that + * one isShutdown. + */ + def hasListener(listener: ActorRef): Boolean = listeners.contains(listener) + + protected[akka] def notifyListeners(message: => Any) { + if (hasListeners) { + val msg = message + val iterator = listeners.iterator + while (iterator.hasNext) { + val listener = iterator.next + // Uncomment if those exceptions are so frequent as to bottleneck + // if (listener.isShutdown) iterator.remove() else + try { + listener ! msg + } catch { + case e: ActorInitializationException => + if (listener.isShutdown) iterator.remove() + } + } + } + } + + /** + * Execute f with each listener as argument. ActorInitializationException is not handled. + */ + protected[akka] def foreachListener(f: (ActorRef) => Unit) { + val iterator = listeners.iterator + while (iterator.hasNext) { + val listener = iterator.next + if (listener.isRunning) f(listener) + } + } +} diff --git a/test/disabled/presentation/akka/src/akka/util/LockUtil.scala b/test/disabled/presentation/akka/src/akka/util/LockUtil.scala new file mode 100644 index 0000000000..4aaefadc4a --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/util/LockUtil.scala @@ -0,0 +1,197 @@ +/** + * Copyright (C) 2009-2011 Scalable Solutions AB + */ + +package akka.util + +import java.util.concurrent.locks.{ ReentrantReadWriteLock, ReentrantLock } +import java.util.concurrent.atomic.{ AtomicBoolean } +import akka.event.EventHandler + +/** + * @author Jonas Bonér + */ +final class ReentrantGuard { + val lock = new ReentrantLock + + final def withGuard[T](body: => T): T = { + lock.lock + try { + body + } finally { + lock.unlock + } + } + + final def tryWithGuard[T](body: => T): T = { + while (!lock.tryLock) { Thread.sleep(10) } // wait on the monitor to be unlocked + try { + body + } finally { + lock.unlock + } + } +} + +/** + * @author Jonas Bonér + */ +class ReadWriteGuard { + private val rwl = new ReentrantReadWriteLock + val readLock = rwl.readLock + val writeLock = rwl.writeLock + + def withWriteGuard[T](body: => T): T = { + writeLock.lock + try { + body + } finally { + writeLock.unlock + } + } + + def withReadGuard[T](body: => T): T = { + readLock.lock + try { + body + } finally { + readLock.unlock + } + } +} + +/** + * A very simple lock that uses CCAS (Compare Compare-And-Swap) + * Does not keep track of the owner and isn't Reentrant, so don't nest and try to stick to the if*-methods + */ +class SimpleLock { + val acquired = new AtomicBoolean(false) + + def ifPossible(perform: () => Unit): Boolean = { + if (tryLock()) { + try { + perform + } finally { + unlock() + } + true + } else false + } + + def ifPossibleYield[T](perform: () => T): Option[T] = { + if (tryLock()) { + try { + Some(perform()) + } finally { + unlock() + } + } else None + } + + def ifPossibleApply[T, R](value: T)(function: (T) => R): Option[R] = { + if (tryLock()) { + try { + Some(function(value)) + } finally { + unlock() + } + } else None + } + + def tryLock() = { + if (acquired.get) false + else acquired.compareAndSet(false, true) + } + + def tryUnlock() = { + acquired.compareAndSet(true, false) + } + + def locked = acquired.get + + def unlock() { + acquired.set(false) + } +} + +/** + * An atomic switch that can be either on or off + */ +class Switch(startAsOn: Boolean = false) { + private val switch = new AtomicBoolean(startAsOn) + + protected def transcend(from: Boolean, action: => Unit): Boolean = synchronized { + if (switch.compareAndSet(from, !from)) { + try { + action + } catch { + case e: Throwable => + EventHandler.error(e, this, e.getMessage) + switch.compareAndSet(!from, from) // revert status + throw e + } + true + } else false + } + + def switchOff(action: => Unit): Boolean = transcend(from = true, action) + def switchOn(action: => Unit): Boolean = transcend(from = false, action) + + def switchOff: Boolean = synchronized { switch.compareAndSet(true, false) } + def switchOn: Boolean = synchronized { switch.compareAndSet(false, true) } + + def ifOnYield[T](action: => T): Option[T] = { + if (switch.get) Some(action) + else None + } + + def ifOffYield[T](action: => T): Option[T] = { + if (!switch.get) Some(action) + else None + } + + def ifOn(action: => Unit): Boolean = { + if (switch.get) { + action + true + } else false + } + + def ifOff(action: => Unit): Boolean = { + if (!switch.get) { + action + true + } else false + } + + def whileOnYield[T](action: => T): Option[T] = synchronized { + if (switch.get) Some(action) + else None + } + + def whileOffYield[T](action: => T): Option[T] = synchronized { + if (!switch.get) Some(action) + else None + } + + def whileOn(action: => Unit): Boolean = synchronized { + if (switch.get) { + action + true + } else false + } + + def whileOff(action: => Unit): Boolean = synchronized { + if (switch.get) { + action + true + } else false + } + + def ifElseYield[T](on: => T)(off: => T) = synchronized { + if (switch.get) on else off + } + + def isOn = switch.get + def isOff = !isOn +} diff --git a/test/disabled/presentation/akka/src/akka/util/ReflectiveAccess.scala b/test/disabled/presentation/akka/src/akka/util/ReflectiveAccess.scala new file mode 100644 index 0000000000..f38d1f9b98 --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/util/ReflectiveAccess.scala @@ -0,0 +1,232 @@ +/** + * Copyright (C) 2009-2011 Scalable Solutions AB + */ + +package akka.util + +import akka.dispatch.{ Future, CompletableFuture, MessageInvocation } +import akka.config.{ Config, ModuleNotAvailableException } + +import java.net.InetSocketAddress +import akka.remoteinterface.RemoteSupport +import akka.actor._ +import akka.event.EventHandler + +/** + * Helper class for reflective access to different modules in order to allow optional loading of modules. + * + * @author Jonas Bonér + */ +object ReflectiveAccess { + + val loader = getClass.getClassLoader + + def isRemotingEnabled = Remote.isEnabled + lazy val isTypedActorEnabled = TypedActorModule.isEnabled + + def ensureRemotingEnabled = Remote.ensureEnabled + def ensureTypedActorEnabled = TypedActorModule.ensureEnabled + + /** + * Reflective access to the RemoteClient module. + * + * @author Jonas Bonér + */ + object Remote { + val TRANSPORT = Config.config.getString("akka.remote.layer", "akka.remote.netty.NettyRemoteSupport") + + private[akka] val configDefaultAddress = + new InetSocketAddress(Config.config.getString("akka.remote.server.hostname", "localhost"), + Config.config.getInt("akka.remote.server.port", 2552)) + + lazy val isEnabled = remoteSupportClass.isDefined + + def ensureEnabled = if (!isEnabled) { + val e = new ModuleNotAvailableException("Can't load the remoting module, make sure that akka-remote.jar is on the classpath") + EventHandler.debug(this, e.toString) + throw e + } + val remoteSupportClass = getClassFor[RemoteSupport](TRANSPORT) match { + case Right(value) => Some(value) + case Left(exception) => + EventHandler.debug(this, exception.toString) + None + } + + protected[akka] val defaultRemoteSupport: Option[() => RemoteSupport] = + remoteSupportClass map { remoteClass => + () => createInstance[RemoteSupport]( + remoteClass, + Array[Class[_]](), + Array[AnyRef]()) match { + case Right(value) => value + case Left(exception) => + val e = new ModuleNotAvailableException( + "Can't instantiate [%s] - make sure that akka-remote.jar is on the classpath".format(remoteClass.getName), exception) + EventHandler.debug(this, e.toString) + throw e + } + } + } + + /** + * Reflective access to the TypedActors module. + * + * @author Jonas Bonér + */ + object TypedActorModule { + + type TypedActorObject = { + def isJoinPoint(message: Any): Boolean + def isJoinPointAndOneWay(message: Any): Boolean + def actorFor(proxy: AnyRef): Option[ActorRef] + def proxyFor(actorRef: ActorRef): Option[AnyRef] + def stop(anyRef: AnyRef): Unit + } + + lazy val isEnabled = typedActorObjectInstance.isDefined + + def ensureEnabled = if (!isTypedActorEnabled) throw new ModuleNotAvailableException( + "Can't load the typed actor module, make sure that akka-typed-actor.jar is on the classpath") + + val typedActorObjectInstance: Option[TypedActorObject] = + getObjectFor[TypedActorObject]("akka.actor.TypedActor$") match { + case Right(value) => Some(value) + case Left(exception) => + EventHandler.debug(this, exception.toString) + None + } + + def resolveFutureIfMessageIsJoinPoint(message: Any, future: Future[_]): Boolean = { + ensureEnabled + if (typedActorObjectInstance.get.isJoinPointAndOneWay(message)) { + future.asInstanceOf[CompletableFuture[Option[_]]].completeWithResult(None) + } + typedActorObjectInstance.get.isJoinPoint(message) + } + } + + object AkkaCloudModule { + + type Mailbox = { + def enqueue(message: MessageInvocation) + def dequeue: MessageInvocation + } + + type Serializer = { + def toBinary(obj: AnyRef): Array[Byte] + def fromBinary(bytes: Array[Byte], clazz: Option[Class[_]]): AnyRef + } + + lazy val isEnabled = clusterObjectInstance.isDefined + + val clusterObjectInstance: Option[AnyRef] = + getObjectFor[AnyRef]("akka.cloud.cluster.Cluster$") match { + case Right(value) => Some(value) + case Left(exception) => + EventHandler.debug(this, exception.toString) + None + } + + val serializerClass: Option[Class[_]] = + getClassFor("akka.serialization.Serializer") match { + case Right(value) => Some(value) + case Left(exception) => + EventHandler.debug(this, exception.toString) + None + } + + def ensureEnabled = if (!isEnabled) throw new ModuleNotAvailableException( + "Feature is only available in Akka Cloud") + } + + val noParams = Array[Class[_]]() + val noArgs = Array[AnyRef]() + + def createInstance[T](clazz: Class[_], + params: Array[Class[_]], + args: Array[AnyRef]): Either[Exception, T] = try { + assert(clazz ne null) + assert(params ne null) + assert(args ne null) + val ctor = clazz.getDeclaredConstructor(params: _*) + ctor.setAccessible(true) + Right(ctor.newInstance(args: _*).asInstanceOf[T]) + } catch { + case e: Exception => Left(e) + } + + def createInstance[T](fqn: String, + params: Array[Class[_]], + args: Array[AnyRef], + classloader: ClassLoader = loader): Either[Exception, T] = try { + assert(params ne null) + assert(args ne null) + getClassFor(fqn) match { + case Right(value) => + val ctor = value.getDeclaredConstructor(params: _*) + ctor.setAccessible(true) + Right(ctor.newInstance(args: _*).asInstanceOf[T]) + case Left(exception) => Left(exception) //We could just cast this to Either[Exception, T] but it's ugly + } + } catch { + case e: Exception => + Left(e) + } + + //Obtains a reference to fqn.MODULE$ + def getObjectFor[T](fqn: String, classloader: ClassLoader = loader): Either[Exception, T] = try { + getClassFor(fqn) match { + case Right(value) => + val instance = value.getDeclaredField("MODULE$") + instance.setAccessible(true) + val obj = instance.get(null) + if (obj eq null) Left(new NullPointerException) else Right(obj.asInstanceOf[T]) + case Left(exception) => Left(exception) //We could just cast this to Either[Exception, T] but it's ugly + } + } catch { + case e: Exception => + Left(e) + } + + def getClassFor[T](fqn: String, classloader: ClassLoader = loader): Either[Exception, Class[T]] = try { + assert(fqn ne null) + + // First, use the specified CL + val first = try { + Right(classloader.loadClass(fqn).asInstanceOf[Class[T]]) + } catch { + case c: ClassNotFoundException => Left(c) + } + + if (first.isRight) first + else { + // Second option is to use the ContextClassLoader + val second = try { + Right(Thread.currentThread.getContextClassLoader.loadClass(fqn).asInstanceOf[Class[T]]) + } catch { + case c: ClassNotFoundException => Left(c) + } + + if (second.isRight) second + else { + val third = try { + if (classloader ne loader) Right(loader.loadClass(fqn).asInstanceOf[Class[T]]) else Left(null) //Horrid + } catch { + case c: ClassNotFoundException => Left(c) + } + + if (third.isRight) third + else { + try { + Right(Class.forName(fqn).asInstanceOf[Class[T]]) // Last option is Class.forName + } catch { + case c: ClassNotFoundException => Left(c) + } + } + } + } + } catch { + case e: Exception => Left(e) + } +} diff --git a/test/disabled/presentation/akka/src/akka/util/package.scala b/test/disabled/presentation/akka/src/akka/util/package.scala new file mode 100644 index 0000000000..26a24929c9 --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/util/package.scala @@ -0,0 +1,27 @@ +/** + * Copyright (C) 2009-2011 Scalable Solutions AB + */ + +package akka.util + +import java.util.concurrent.TimeUnit + +package object duration { + implicit def intToDurationInt(n: Int) = new DurationInt(n) + implicit def longToDurationLong(n: Long) = new DurationLong(n) + implicit def doubleToDurationDouble(d: Double) = new DurationDouble(d) + + implicit def pairIntToDuration(p: (Int, TimeUnit)) = Duration(p._1, p._2) + implicit def pairLongToDuration(p: (Long, TimeUnit)) = Duration(p._1, p._2) + implicit def durationToPair(d: Duration) = (d.length, d.unit) + + implicit def intMult(i: Int) = new { + def *(d: Duration) = d * i + } + implicit def longMult(l: Long) = new { + def *(d: Duration) = d * l + } + implicit def doubleMult(f: Double) = new { + def *(d: Duration) = d * f + } +} diff --git a/test/disabled/presentation/akka/src/com/eaio/util/lang/Hex.java b/test/disabled/presentation/akka/src/com/eaio/util/lang/Hex.java new file mode 100644 index 0000000000..7794059517 --- /dev/null +++ b/test/disabled/presentation/akka/src/com/eaio/util/lang/Hex.java @@ -0,0 +1,215 @@ +/* + * Hex.java + * + * Created 04.07.2003. + * + * eaio: UUID - an implementation of the UUID specification Copyright (c) 2003-2009 Johann Burkard (jb@eaio.com) + * http://eaio.com. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +package com.eaio.util.lang; + +import java.io.IOException; + +/** + * Number-to-hexadecimal and hexadecimal-to-number conversions. + * + * @see UUID + * @author Johann Burkard + * @version $Id: Hex.java 1888 2009-03-15 12:43:24Z johann $ + */ +public final class Hex { + + /** + * No instances needed. + */ + private Hex() { + super(); + } + + private static final char[] DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', + 'f' }; + + /** + * Turns a short into hex octets. + * + * @param a the {@link Appendable}, may not be null + * @param in the integer + * @return {@link Appendable} + */ + public static Appendable append(Appendable a, short in) { + return append(a, (long) in, 4); + } + + /** + * Turns a short into hex octets. + * + * @param a the {@link Appendable}, may not be null + * @param in the integer + * @param length the number of octets to produce + * @return {@link Appendable} + */ + public static Appendable append(Appendable a, short in, int length) { + return append(a, (long) in, length); + } + + /** + * Turns an int into hex octets. + * + * @param a the {@link Appendable}, may not be null + * @param in the integer + * @return {@link Appendable} + */ + public static Appendable append(Appendable a, int in) { + return append(a, (long) in, 8); + } + + /** + * Turns an int into hex octets. + * + * @param a the {@link Appendable}, may not be null + * @param in the integer + * @param length the number of octets to produce + * @return {@link Appendable} + */ + public static Appendable append(Appendable a, int in, int length) { + return append(a, (long) in, length); + } + + /** + * Turns a long into hex octets. + * + * @param a the {@link Appendable}, may not be null + * @param in the long + * @return {@link Appendable} + */ + public static Appendable append(Appendable a, long in) { + return append(a, in, 16); + } + + /** + * Turns a long into hex octets. + * + * @param a the {@link Appendable}, may not be null + * @param in the long + * @param length the number of octets to produce + * @return {@link Appendable} + */ + public static Appendable append(Appendable a, long in, int length) { + try { + int lim = (length << 2) - 4; + while (lim >= 0) { + a.append(DIGITS[(byte) (in >> lim) & 0x0f]); + lim -= 4; + } + } + catch (IOException ex) { + // Bla + } + return a; + } + + /** + * Turns a byte array into hex octets. + * + * @param a the {@link Appendable}, may not be null + * @param bytes the byte array + * @return {@link Appendable} + */ + public static Appendable append(Appendable a, byte[] bytes) { + try { + for (byte b : bytes) { + a.append(DIGITS[(byte) ((b & 0xF0) >> 4)]); + a.append(DIGITS[(byte) (b & 0x0F)]); + } + } + catch (IOException ex) { + // Bla + } + return a; + } + + /** + * Parses a long from a hex encoded number. This method will skip all characters that are not 0-9, + * A-F and a-f. + *

      + * Returns 0 if the {@link CharSequence} does not contain any interesting characters. + * + * @param s the {@link CharSequence} to extract a long from, may not be null + * @return a long + * @throws NullPointerException if the {@link CharSequence} is null + */ + public static long parseLong(CharSequence s) { + long out = 0; + byte shifts = 0; + char c; + for (int i = 0; i < s.length() && shifts < 16; i++) { + c = s.charAt(i); + if ((c > 47) && (c < 58)) { + ++shifts; + out <<= 4; + out |= c - 48; + } + else if ((c > 64) && (c < 71)) { + ++shifts; + out <<= 4; + out |= c - 55; + } + else if ((c > 96) && (c < 103)) { + ++shifts; + out <<= 4; + out |= c - 87; + } + } + return out; + } + + /** + * Parses a short from a hex encoded number. This method will skip all characters that are not 0-9, + * A-F and a-f. + *

      + * Returns 0 if the {@link CharSequence} does not contain any interesting characters. + * + * @param s the {@link CharSequence} to extract a short from, may not be null + * @return a short + * @throws NullPointerException if the {@link CharSequence} is null + */ + public static short parseShort(String s) { + short out = 0; + byte shifts = 0; + char c; + for (int i = 0; i < s.length() && shifts < 4; i++) { + c = s.charAt(i); + if ((c > 47) && (c < 58)) { + ++shifts; + out <<= 4; + out |= c - 48; + } + else if ((c > 64) && (c < 71)) { + ++shifts; + out <<= 4; + out |= c - 55; + } + else if ((c > 96) && (c < 103)) { + ++shifts; + out <<= 4; + out |= c - 87; + } + } + return out; + } + +} diff --git a/test/disabled/presentation/akka/src/com/eaio/uuid/MACAddressParser.java b/test/disabled/presentation/akka/src/com/eaio/uuid/MACAddressParser.java new file mode 100644 index 0000000000..c077147470 --- /dev/null +++ b/test/disabled/presentation/akka/src/com/eaio/uuid/MACAddressParser.java @@ -0,0 +1,116 @@ +/* + * MACAddressParserTest.java + * + * Created 30.01.2006. + * + * eaio: UUID - an implementation of the UUID specification + * Copyright (c) 2003-2009 Johann Burkard (jb@eaio.com) http://eaio.com. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +package com.eaio.uuid; + +/** + * The MAC address parser attempts to find the following patterns: + *

        + *
      • .{1,2}:.{1,2}:.{1,2}:.{1,2}:.{1,2}:.{1,2}
      • + *
      • .{1,2}-.{1,2}-.{1,2}-.{1,2}-.{1,2}-.{1,2}
      • + *
      + * + * @see UUID + * @author Johann Burkard + * @version $Id: MACAddressParser.java 1888 2009-03-15 12:43:24Z johann $ + */ +class MACAddressParser { + + /** + * No instances needed. + */ + private MACAddressParser() { + super(); + } + + /** + * Attempts to find a pattern in the given String. + * + * @param in the String, may not be null + * @return the substring that matches this pattern or null + */ + static String parse(String in) { + + String out = in; + + // lanscan + + int hexStart = out.indexOf("0x"); + if (hexStart != -1 && out.indexOf("ETHER") != -1) { + int hexEnd = out.indexOf(' ', hexStart); + if (hexEnd > hexStart + 2) { + out = out.substring(hexStart, hexEnd); + } + } + + else { + + int octets = 0; + int lastIndex, old, end; + + if (out.indexOf('-') > -1) { + out = out.replace('-', ':'); + } + + lastIndex = out.lastIndexOf(':'); + + if (lastIndex > out.length() - 2) { + out = null; + } + else { + + end = Math.min(out.length(), lastIndex + 3); + + ++octets; + old = lastIndex; + while (octets != 5 && lastIndex != -1 && lastIndex > 1) { + lastIndex = out.lastIndexOf(':', --lastIndex); + if (old - lastIndex == 3 || old - lastIndex == 2) { + ++octets; + old = lastIndex; + } + } + + if (octets == 5 && lastIndex > 1) { + out = out.substring(lastIndex - 2, end).trim(); + } + else { + out = null; + } + + } + + } + + if (out != null && out.startsWith("0x")) { + out = out.substring(2); + } + + return out; + } + +} diff --git a/test/disabled/presentation/akka/src/com/eaio/uuid/UUID.java b/test/disabled/presentation/akka/src/com/eaio/uuid/UUID.java new file mode 100644 index 0000000000..6c49bcd1c8 --- /dev/null +++ b/test/disabled/presentation/akka/src/com/eaio/uuid/UUID.java @@ -0,0 +1,311 @@ +/* + * UUID.java + * + * Created 07.02.2003 + * + * eaio: UUID - an implementation of the UUID specification + * Copyright (c) 2003-2009 Johann Burkard (jb@eaio.com) http://eaio.com. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +package com.eaio.uuid; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; + +import org.omg.CORBA.portable.IDLEntity; + +import com.eaio.util.lang.Hex; + +/** + * Creates UUIDs according to the DCE Universal Token Identifier specification. + *

      + * All you need to know: + *

      + * UUID u = new UUID();
      + * 
      + * + * @see + * http://www.opengroup.org/onlinepubs/9629399/apdxa.htm + * + * @see + * http://www.uddi.org/pubs/draft-leach-uuids-guids-01.txt + * + * @see UUID + * @author Johann Burkard + * @version $Id: UUID.java 1888 2009-03-15 12:43:24Z johann $ + */ +public class UUID implements Comparable, Serializable, Cloneable, + IDLEntity { + + /** + * Hasn't ever changed between versions. + */ + static final long serialVersionUID = 7435962790062944603L; + + /** + * The time field of the UUID. + * + * @serial + */ + public long time; + + /** + * The clock sequence and node field of the UUID. + * + * @serial + */ + public long clockSeqAndNode; + + /** + * Constructor for UUID. Constructs a new, unique UUID. + * + * @see UUIDGen#newTime() + * @see UUIDGen#getClockSeqAndNode() + */ + public UUID() { + this(UUIDGen.newTime(), UUIDGen.getClockSeqAndNode()); + } + + /** + * Constructor for UUID. Constructs a UUID from two long values. + * + * @param time the upper 64 bits + * @param clockSeqAndNode the lower 64 bits + */ + public UUID(long time, long clockSeqAndNode) { + this.time = time; + this.clockSeqAndNode = clockSeqAndNode; + } + + /** + * Copy constructor for UUID. Values of the given UUID are copied. + * + * @param u the UUID, may not be null + */ + public UUID(UUID u) { + this(u.time, u.clockSeqAndNode); + } + + /** + * Parses a textual representation of a UUID. + *

      + * No validation is performed. If the {@link CharSequence} is shorter than 36 characters, + * {@link ArrayIndexOutOfBoundsException}s will be thrown. + * + * @param s the {@link CharSequence}, may not be null + */ + public UUID(CharSequence s) { + this(Hex.parseLong(s.subSequence(0, 18)), Hex.parseLong(s.subSequence( + 19, 36))); + } + + /** + * Compares this UUID to another Object. Throws a {@link ClassCastException} if + * the other Object is not an instance of the UUID class. Returns a value + * smaller than zero if the other UUID is "larger" than this UUID and a value + * larger than zero if the other UUID is "smaller" than this UUID. + * + * @param t the other UUID, may not be null + * @return a value < 0, 0 or a value > 0 + * @see java.lang.Comparable#compareTo(java.lang.Object) + * @throws ClassCastException + */ + public int compareTo(UUID t) { + if (this == t) { + return 0; + } + if (time > t.time) { + return 1; + } + if (time < t.time) { + return -1; + } + if (clockSeqAndNode > t.clockSeqAndNode) { + return 1; + } + if (clockSeqAndNode < t.clockSeqAndNode) { + return -1; + } + return 0; + } + + /** + * Tweaked Serialization routine. + * + * @param out the ObjectOutputStream + * @throws IOException + */ + private void writeObject(ObjectOutputStream out) throws IOException { + out.writeLong(time); + out.writeLong(clockSeqAndNode); + } + + /** + * Tweaked Serialization routine. + * + * @param in the ObjectInputStream + * @throws IOException + */ + private void readObject(ObjectInputStream in) throws IOException { + time = in.readLong(); + clockSeqAndNode = in.readLong(); + } + + /** + * Returns this UUID as a String. + * + * @return a String, never null + * @see java.lang.Object#toString() + * @see #toAppendable(Appendable) + */ + @Override + public final String toString() { + return toAppendable(null).toString(); + } + + /** + * Appends a String representation of this to the given {@link StringBuffer} or + * creates a new one if none is given. + * + * @param in the StringBuffer to append to, may be null + * @return a StringBuffer, never null + * @see #toAppendable(Appendable) + */ + public StringBuffer toStringBuffer(StringBuffer in) { + StringBuffer out = in; + if (out == null) { + out = new StringBuffer(36); + } + else { + out.ensureCapacity(out.length() + 36); + } + return (StringBuffer) toAppendable(out); + } + + /** + * Appends a String representation of this object to the given {@link Appendable} object. + *

      + * For reasons I'll probably never understand, Sun has decided to have a number of I/O classes implement + * Appendable which forced them to destroy an otherwise nice and simple interface with {@link IOException}s. + *

      + * I decided to ignore any possible IOExceptions in this method. + * + * @param a the Appendable object, may be null + * @return an Appendable object, defaults to a {@link StringBuilder} if a is null + */ + public Appendable toAppendable(Appendable a) { + Appendable out = a; + if (out == null) { + out = new StringBuilder(36); + } + try { + Hex.append(out, (int) (time >> 32)).append('-'); + Hex.append(out, (short) (time >> 16)).append('-'); + Hex.append(out, (short) time).append('-'); + Hex.append(out, (short) (clockSeqAndNode >> 48)).append('-'); + Hex.append(out, clockSeqAndNode, 12); + } + catch (IOException ex) { + // What were they thinking? + } + return out; + } + + /** + * Returns a hash code of this UUID. The hash code is calculated by XOR'ing the + * upper 32 bits of the time and clockSeqAndNode fields and the lower 32 bits of + * the time and clockSeqAndNode fields. + * + * @return an int representing the hash code + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + return (int) ((time >> 32) ^ time ^ (clockSeqAndNode >> 32) ^ clockSeqAndNode); + } + + /** + * Clones this UUID. + * + * @return a new UUID with identical values, never null + */ + @Override + public Object clone() { + try { + return super.clone(); + } + catch (CloneNotSupportedException ex) { + // One of Sun's most epic fails. + return null; + } + } + + /** + * Returns the time field of the UUID (upper 64 bits). + * + * @return the time field + */ + public final long getTime() { + return time; + } + + /** + * Returns the clock and node field of the UUID (lower 64 bits). + * + * @return the clockSeqAndNode field + */ + public final long getClockSeqAndNode() { + return clockSeqAndNode; + } + + /** + * Compares two Objects for equality. + * + * @see java.lang.Object#equals(Object) + * @param obj the Object to compare this UUID with, may be null + * @return true if the other Object is equal to this UUID, + * false if not + */ + @Override + public boolean equals(Object obj) { + if (!(obj instanceof UUID)) { + return false; + } + return compareTo((UUID) obj) == 0; + } + + /** + * Returns the nil UUID (a UUID whose values are both set to zero). + *

      + * Starting with version 2.0, this method does return a new UUID instance every + * time it is called. Earlier versions returned one instance. This has now been + * changed because this UUID has public, non-final instance fields. Returning a + * new instance is therefore more safe. + * + * @return a nil UUID, never null + */ + public static UUID nilUUID() { + return new UUID(0, 0); + } + +} diff --git a/test/disabled/presentation/akka/src/com/eaio/uuid/UUIDGen.java b/test/disabled/presentation/akka/src/com/eaio/uuid/UUIDGen.java new file mode 100644 index 0000000000..7b63f65447 --- /dev/null +++ b/test/disabled/presentation/akka/src/com/eaio/uuid/UUIDGen.java @@ -0,0 +1,364 @@ +/* + * UUIDGen.java + * + * Created on 09.08.2003. + * + * eaio: UUID - an implementation of the UUID specification + * Copyright (c) 2003-2009 Johann Burkard (jb@eaio.com) http://eaio.com. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +package com.eaio.uuid; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.InetAddress; +import java.net.InterfaceAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.net.UnknownHostException; +import java.util.Enumeration; + +import com.eaio.util.lang.Hex; + +/** + * This class contains methods to generate UUID fields. These methods have been + * refactored out of {@link com.eaio.uuid.UUID}. + *

      + * Starting with version 2, this implementation tries to obtain the MAC address + * of the network card. Under Microsoft Windows, the ifconfig + * command is used which may pop up a command window in Java Virtual Machines + * prior to 1.4 once this class is initialized. The command window is closed + * automatically. + *

      + * The MAC address code has been tested extensively in Microsoft Windows, + * Linux, Solaris 8, HP-UX 11, but should work in MacOS X and BSDs, too. + *

      + * If you use JDK 6 or later, the code in {@link InterfaceAddress} will be used. + * + * @see UUID + * @author Johann Burkard + * @version $Id: UUIDGen.java 2914 2010-04-23 11:35:00Z johann $ + * @see com.eaio.uuid.UUID + */ +public final class UUIDGen { + + /** + * No instances needed. + */ + private UUIDGen() { + super(); + } + + /** + * The last time value. Used to remove duplicate UUIDs. + */ + private static long lastTime = Long.MIN_VALUE; + + /** + * The cached MAC address. + */ + private static String macAddress = null; + + /** + * The current clock and node value. + */ + private static long clockSeqAndNode = 0x8000000000000000L; + + static { + + try { + Class.forName("java.net.InterfaceAddress"); + macAddress = Class.forName( + "com.eaio.uuid.UUIDGen$HardwareAddressLookup").newInstance().toString(); + } + catch (ExceptionInInitializerError err) { + // Ignored. + } + catch (ClassNotFoundException ex) { + // Ignored. + } + catch (LinkageError err) { + // Ignored. + } + catch (IllegalAccessException ex) { + // Ignored. + } + catch (InstantiationException ex) { + // Ignored. + } + catch (SecurityException ex) { + // Ignored. + } + + if (macAddress == null) { + + Process p = null; + BufferedReader in = null; + + try { + String osname = System.getProperty("os.name", ""); + + if (osname.startsWith("Windows")) { + p = Runtime.getRuntime().exec( + new String[] { "ipconfig", "/all" }, null); + } + // Solaris code must appear before the generic code + else if (osname.startsWith("Solaris") + || osname.startsWith("SunOS")) { + String hostName = getFirstLineOfCommand( + "uname", "-n" ); + if (hostName != null) { + p = Runtime.getRuntime().exec( + new String[] { "/usr/sbin/arp", hostName }, + null); + } + } + else if (new File("/usr/sbin/lanscan").exists()) { + p = Runtime.getRuntime().exec( + new String[] { "/usr/sbin/lanscan" }, null); + } + else if (new File("/sbin/ifconfig").exists()) { + p = Runtime.getRuntime().exec( + new String[] { "/sbin/ifconfig", "-a" }, null); + } + + if (p != null) { + in = new BufferedReader(new InputStreamReader( + p.getInputStream()), 128); + String l = null; + while ((l = in.readLine()) != null) { + macAddress = MACAddressParser.parse(l); + if (macAddress != null + && Hex.parseShort(macAddress) != 0xff) { + break; + } + } + } + + } + catch (SecurityException ex) { + // Ignore it. + } + catch (IOException ex) { + // Ignore it. + } + finally { + if (p != null) { + if (in != null) { + try { + in.close(); + } + catch (IOException ex) { + // Ignore it. + } + } + try { + p.getErrorStream().close(); + } + catch (IOException ex) { + // Ignore it. + } + try { + p.getOutputStream().close(); + } + catch (IOException ex) { + // Ignore it. + } + p.destroy(); + } + } + + } + + if (macAddress != null) { + clockSeqAndNode |= Hex.parseLong(macAddress); + } + else { + try { + byte[] local = InetAddress.getLocalHost().getAddress(); + clockSeqAndNode |= (local[0] << 24) & 0xFF000000L; + clockSeqAndNode |= (local[1] << 16) & 0xFF0000; + clockSeqAndNode |= (local[2] << 8) & 0xFF00; + clockSeqAndNode |= local[3] & 0xFF; + } + catch (UnknownHostException ex) { + clockSeqAndNode |= (long) (Math.random() * 0x7FFFFFFF); + } + } + + // Skip the clock sequence generation process and use random instead. + + clockSeqAndNode |= (long) (Math.random() * 0x3FFF) << 48; + + } + + /** + * Returns the current clockSeqAndNode value. + * + * @return the clockSeqAndNode value + * @see UUID#getClockSeqAndNode() + */ + public static long getClockSeqAndNode() { + return clockSeqAndNode; + } + + /** + * Generates a new time field. Each time field is unique and larger than the + * previously generated time field. + * + * @return a new time value + * @see UUID#getTime() + */ + public static long newTime() { + return createTime(System.currentTimeMillis()); + } + + /** + * Creates a new time field from the given timestamp. Note that even identical + * values of currentTimeMillis will produce different time fields. + * + * @param currentTimeMillis the timestamp + * @return a new time value + * @see UUID#getTime() + */ + public static synchronized long createTime(long currentTimeMillis) { + + long time; + + // UTC time + + long timeMillis = (currentTimeMillis * 10000) + 0x01B21DD213814000L; + + if (timeMillis > lastTime) { + lastTime = timeMillis; + } + else { + timeMillis = ++lastTime; + } + + // time low + + time = timeMillis << 32; + + // time mid + + time |= (timeMillis & 0xFFFF00000000L) >> 16; + + // time hi and version + + time |= 0x1000 | ((timeMillis >> 48) & 0x0FFF); // version 1 + + return time; + + } + + /** + * Returns the MAC address. Not guaranteed to return anything. + * + * @return the MAC address, may be null + */ + public static String getMACAddress() { + return macAddress; + } + + /** + * Returns the first line of the shell command. + * + * @param commands the commands to run + * @return the first line of the command + * @throws IOException + */ + static String getFirstLineOfCommand(String... commands) throws IOException { + + Process p = null; + BufferedReader reader = null; + + try { + p = Runtime.getRuntime().exec(commands); + reader = new BufferedReader(new InputStreamReader( + p.getInputStream()), 128); + + return reader.readLine(); + } + finally { + if (p != null) { + if (reader != null) { + try { + reader.close(); + } + catch (IOException ex) { + // Ignore it. + } + } + try { + p.getErrorStream().close(); + } + catch (IOException ex) { + // Ignore it. + } + try { + p.getOutputStream().close(); + } + catch (IOException ex) { + // Ignore it. + } + p.destroy(); + } + } + + } + + /** + * Scans MAC addresses for good ones. + */ + static class HardwareAddressLookup { + + /** + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + String out = null; + try { + Enumeration ifs = NetworkInterface.getNetworkInterfaces(); + if (ifs != null) { + while (ifs.hasMoreElements()) { + NetworkInterface iface = ifs.nextElement(); + byte[] hardware = iface.getHardwareAddress(); + if (hardware != null && hardware.length == 6 + && hardware[1] != (byte) 0xff) { + out = Hex.append(new StringBuilder(36), hardware).toString(); + break; + } + } + } + } + catch (SocketException ex) { + // Ignore it. + } + return out; + } + + } + +} diff --git a/test/disabled/presentation/akka/src/com/eaio/uuid/UUIDHelper.java b/test/disabled/presentation/akka/src/com/eaio/uuid/UUIDHelper.java new file mode 100644 index 0000000000..7abbe85895 --- /dev/null +++ b/test/disabled/presentation/akka/src/com/eaio/uuid/UUIDHelper.java @@ -0,0 +1,86 @@ +package com.eaio.uuid; + + +/** +* com/eaio/uuid/UUIDHelper.java . +* Generated by the IDL-to-Java compiler (portable), version "3.1" +* from uuid.idl +* Sonntag, 7. März 2004 21.35 Uhr CET +*/ + + +/** + * The UUID struct. + */ +abstract public class UUIDHelper +{ + private static String _id = "IDL:com/eaio/uuid/UUID:1.0"; + + public static void insert (org.omg.CORBA.Any a, com.eaio.uuid.UUID that) + { + org.omg.CORBA.portable.OutputStream out = a.create_output_stream (); + a.type (type ()); + write (out, that); + a.read_value (out.create_input_stream (), type ()); + } + + public static com.eaio.uuid.UUID extract (org.omg.CORBA.Any a) + { + return read (a.create_input_stream ()); + } + + private static org.omg.CORBA.TypeCode __typeCode = null; + private static boolean __active = false; + synchronized public static org.omg.CORBA.TypeCode type () + { + if (__typeCode == null) + { + synchronized (org.omg.CORBA.TypeCode.class) + { + if (__typeCode == null) + { + if (__active) + { + return org.omg.CORBA.ORB.init().create_recursive_tc ( _id ); + } + __active = true; + org.omg.CORBA.StructMember[] _members0 = new org.omg.CORBA.StructMember [2]; + org.omg.CORBA.TypeCode _tcOf_members0 = null; + _tcOf_members0 = org.omg.CORBA.ORB.init ().get_primitive_tc (org.omg.CORBA.TCKind.tk_longlong); + _members0[0] = new org.omg.CORBA.StructMember ( + "time", + _tcOf_members0, + null); + _tcOf_members0 = org.omg.CORBA.ORB.init ().get_primitive_tc (org.omg.CORBA.TCKind.tk_longlong); + _members0[1] = new org.omg.CORBA.StructMember ( + "clockSeqAndNode", + _tcOf_members0, + null); + __typeCode = org.omg.CORBA.ORB.init ().create_struct_tc (com.eaio.uuid.UUIDHelper.id (), "UUID", _members0); + __active = false; + } + } + } + return __typeCode; + } + + public static String id () + { + return _id; + } + + public static com.eaio.uuid.UUID read (org.omg.CORBA.portable.InputStream istream) + { + com.eaio.uuid.UUID value = new com.eaio.uuid.UUID (); + value.time = istream.read_longlong (); + value.clockSeqAndNode = istream.read_longlong (); + return value; + } + + public static void write (org.omg.CORBA.portable.OutputStream ostream, com.eaio.uuid.UUID value) + { + ostream.write_longlong (value.time); + ostream.write_longlong (value.clockSeqAndNode); + } + +} diff --git a/test/disabled/presentation/akka/src/com/eaio/uuid/UUIDHolder.java b/test/disabled/presentation/akka/src/com/eaio/uuid/UUIDHolder.java new file mode 100644 index 0000000000..d5531f5e00 --- /dev/null +++ b/test/disabled/presentation/akka/src/com/eaio/uuid/UUIDHolder.java @@ -0,0 +1,42 @@ +package com.eaio.uuid; + +/** +* com/eaio/uuid/UUIDHolder.java . +* Generated by the IDL-to-Java compiler (portable), version "3.1" +* from uuid.idl +* Sonntag, 7. März 2004 21.35 Uhr CET +*/ + + +/** + * The UUID struct. + */ +public final class UUIDHolder implements org.omg.CORBA.portable.Streamable +{ + public com.eaio.uuid.UUID value = null; + + public UUIDHolder () + { + } + + public UUIDHolder (com.eaio.uuid.UUID initialValue) + { + value = initialValue; + } + + public void _read (org.omg.CORBA.portable.InputStream i) + { + value = com.eaio.uuid.UUIDHelper.read (i); + } + + public void _write (org.omg.CORBA.portable.OutputStream o) + { + com.eaio.uuid.UUIDHelper.write (o, value); + } + + public org.omg.CORBA.TypeCode _type () + { + return com.eaio.uuid.UUIDHelper.type (); + } + +} diff --git a/test/disabled/presentation/akka/src/pi.scala b/test/disabled/presentation/akka/src/pi.scala new file mode 100644 index 0000000000..b4c644052c --- /dev/null +++ b/test/disabled/presentation/akka/src/pi.scala @@ -0,0 +1,108 @@ + +import akka.actor.{Actor, PoisonPill} +import Actor._ +import akka.routing.{Routing, CyclicIterator} +import Routing._ + +import java.util.concurrent.CountDownLatch + +object Pi extends App { + + calculate/*#*/(nrOfWorkers = 4, nrOfElements = 10000, nrOfMessages = 10000) + + // ==================== + // ===== Messages ===== + // ==================== + sealed trait PiMessage + case object Calculate extends PiMessage/*#*/ + case class Work(start: Int, nrOfElements: Int) extends PiMessage + case class Result(value: Double) extends PiMessage + + // ================== + // ===== Worker ===== + // ================== + class Worker extends Actor/*#*/ { + + // define the work + def calculatePiFor(start: Int, nrOfElements: Int): Double = { + var acc = 0.0 + for (i <- start until (start + nrOfElements)) + acc += 4.0 * (1 - (i % 2) * 2) / (2 * i + 1) + acc + } + + def receive /*?*/ = { + case Work(start, nrOfElements) => + self reply/*#*/ Result(calculatePiFor(start, nrOfElements)) // perform the work // TODO: this currently returns wrong position for the symbol + } + } + + // ================== + // ===== Master ===== + // ================== + class Master( + nrOfWorkers: Int, nrOfMessages: Int, nrOfElements: Int, latch: CountDownLatch) + extends Actor { + + var pi: Double = _ + var nrOfResults: Int = _ + var start: Long = _ + + // create the workers + val workers = Vector.fill(nrOfWorkers)(actorOf[Worker]./*!*/start()) + + // wrap them with a load-balancing router + val router = Routing./*!*/loadBalancerActor(CyclicIterator(workers))./*!*/start() + + // message handler + def receive = { + case Calculate => + // schedule work + //for (start <- 0 until nrOfMessages) router ! Work(start, nrOfElements) + for (i <- 0 until nrOfMessages) router ! Work(i * nrOfElements, nrOfElements) + + // send a PoisonPill to all workers telling them to shut down themselves + router./*!*/!(Broadcast(PoisonPill)) + + // send a PoisonPill to the router, telling him to shut himself down + router ! PoisonPill + + case Result(value) => + // handle result from the worker + pi += value + nrOfResults/*#*/ += 1 + if (nrOfResults == nrOfMessages) self./*!*/stop() + } + + override def preStart() { + start = System.currentTimeMillis + } + + override def postStop() { + // tell the world that the calculation is complete + println( + "\n\tPi estimate: \t\t%s\n\tCalculation time: \t%s millis" + .format(pi, (System.currentTimeMillis - start))) + latch/*#*/.countDown() + } + } + + // ================== + // ===== Run it ===== + // ================== + 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) + + // create the master + val master = actorOf( + new Master(nrOfWorkers, nrOfMessages, nrOfElements, latch)).start() + + // start the calculation + master ! Calculate + + // wait for master to shut down + latch.await() + } +} diff --git a/test/disabled/presentation/timeofday.check b/test/disabled/presentation/timeofday.check new file mode 100644 index 0000000000..2a09d0bcfc --- /dev/null +++ b/test/disabled/presentation/timeofday.check @@ -0,0 +1,100 @@ +reload: timeofday.scala + +askTypeCompletion at timeofday.scala(26,33) +================================================================================ +[response] aksTypeCompletion at (26,33) +retrieved 45 members +`method !=(x$1: Any)Boolean` +`method !=(x$1: AnyRef)Boolean` +`method ##()Int` +`method +(other: String)String` +`method ->[B](y: B)(timeofday.TimeOfDayVar, B)` +`method ==(x$1: Any)Boolean` +`method ==(x$1: AnyRef)Boolean` +`method asInstanceOf[T0]=> T0` +`method clone()Object` +`method ensuring(cond: Boolean)timeofday.TimeOfDayVar` +`method ensuring(cond: Boolean, msg: => Any)timeofday.TimeOfDayVar` +`method ensuring(cond: timeofday.TimeOfDayVar => Boolean)timeofday.TimeOfDayVar` +`method ensuring(cond: timeofday.TimeOfDayVar => Boolean, msg: => Any)timeofday.TimeOfDayVar` +`method eq(x$1: AnyRef)Boolean` +`method equals(x$1: Any)Boolean` +`method finalize()Unit` +`method formatted(fmtstr: String)String` +`method hashCode()Int` +`method hours=> Int` +`method hours_=(h: Int)Unit` +`method isInstanceOf[T0]=> Boolean` +`method minutes=> Int` +`method minutes_=(m: Int)Unit` +`method ne(x$1: AnyRef)Boolean` +`method notify()Unit` +`method notifyAll()Unit` +`method seconds=> Int` +`method seconds_=(s: Int)Unit` +`method synchronized[T0](x$1: T0)T0` +`method toString()String` +`method wait()Unit` +`method wait(x$1: Long)Unit` +`method wait(x$1: Long, x$2: Int)Unit` +`method x=> timeofday.TimeOfDayVar` +`method →[B](y: B)(timeofday.TimeOfDayVar, B)` +`value __leftOfArrowtimeofday.TimeOfDayVar` +`value __resultOfEnsuringtimeofday.TimeOfDayVar` +`value selfAny` +`variable hInt` +`variable mInt` +`variable sInt` +================================================================================ + +askTypeCompletion at timeofday.scala(32,19) +================================================================================ +[response] aksTypeCompletion at (32,19) +retrieved 45 members +`method !=(x$1: Any)Boolean` +`method !=(x$1: AnyRef)Boolean` +`method ##()Int` +`method +(other: String)String` +`method ->[B](y: B)(timeofday.TimeOfDayVar, B)` +`method ==(x$1: Any)Boolean` +`method ==(x$1: AnyRef)Boolean` +`method asInstanceOf[T0]=> T0` +`method clone()Object` +`method ensuring(cond: Boolean)timeofday.TimeOfDayVar` +`method ensuring(cond: Boolean, msg: => Any)timeofday.TimeOfDayVar` +`method ensuring(cond: timeofday.TimeOfDayVar => Boolean)timeofday.TimeOfDayVar` +`method ensuring(cond: timeofday.TimeOfDayVar => Boolean, msg: => Any)timeofday.TimeOfDayVar` +`method eq(x$1: AnyRef)Boolean` +`method equals(x$1: Any)Boolean` +`method finalize()Unit` +`method formatted(fmtstr: String)String` +`method hashCode()Int` +`method hours=> Int` +`method hours_=(h: Int)Unit` +`method isInstanceOf[T0]=> Boolean` +`method minutes=> Int` +`method minutes_=(m: Int)Unit` +`method ne(x$1: AnyRef)Boolean` +`method notify()Unit` +`method notifyAll()Unit` +`method seconds=> Int` +`method seconds_=(s: Int)Unit` +`method synchronized[T0](x$1: T0)T0` +`method toString()String` +`method wait()Unit` +`method wait(x$1: Long)Unit` +`method wait(x$1: Long, x$2: Int)Unit` +`method x=> timeofday.TimeOfDayVar` +`method →[B](y: B)(timeofday.TimeOfDayVar, B)` +`value __leftOfArrowtimeofday.TimeOfDayVar` +`value __resultOfEnsuringtimeofday.TimeOfDayVar` +`value selfAny` +`variable hInt` +`variable mInt` +`variable sInt` +================================================================================ + +askHyperlinkPos for `hours` at (33,11) timeofday.scala +================================================================================ +[response] found askHyperlinkPos for `hours` at (10,9) timeofday.scala +================================================================================ diff --git a/test/disabled/presentation/timeofday/Runner.scala b/test/disabled/presentation/timeofday/Runner.scala new file mode 100644 index 0000000000..1c03e3d5ba --- /dev/null +++ b/test/disabled/presentation/timeofday/Runner.scala @@ -0,0 +1,3 @@ +import scala.tools.nsc.interactive.tests._ + +object Test extends InteractiveTest diff --git a/test/disabled/presentation/timeofday/src/timeofday.scala b/test/disabled/presentation/timeofday/src/timeofday.scala new file mode 100644 index 0000000000..d6355097f1 --- /dev/null +++ b/test/disabled/presentation/timeofday/src/timeofday.scala @@ -0,0 +1,35 @@ +object timeofday { + class DateError extends Exception + + /** Simulating properties in Scala + * (example 4.2.1 in ScalaReference.pdf) + */ + class TimeOfDayVar { + private var h, m, s: Int = 0 + + def hours = h + + /** A method 'ident_=' is a setter for 'ident'. 'code.ident = ...' will + * be translated to a call to 'ident_=' + */ + def hours_= (h: Int) = + if (0 <= h && h < 24) this.h = h + else throw new DateError() + + def minutes = m + def minutes_= (m: Int) = + if (0 <= m && m < 60) this.m = m + else throw new DateError() + + def seconds = s + def seconds_= (s: Int) = + if (0 <= s && s < 60) this./*!*/s = s + else throw new DateError() + } + + def main(args: Array[String]) { + val d = new TimeOfDayVar + d.hours = 8; d./*!*/minutes = 30; d.seconds = 0 + d.hours/*#*/ = 25 // throws a DateError exception + } +} \ No newline at end of file diff --git a/test/files/presentation/akka.check b/test/files/presentation/akka.check deleted file mode 100644 index 9cd20ffb1c..0000000000 --- a/test/files/presentation/akka.check +++ /dev/null @@ -1,492 +0,0 @@ -reload: Actor.scala, ActorRef.scala, ActorRegistry.scala, Actors.java, Address.scala, AkkaException.scala, AkkaLoader.scala, Bootable.scala, BootableActorLoaderService.scala, BoundedBlockingQueue.scala, Config.scala, ConfigParser.scala, Configuration.scala, Configurator.scala, Crypt.scala, DataFlow.scala, Dispatchers.scala, Duration.scala, EventHandler.scala, ExecutorBasedEventDrivenDispatcher.scala, ExecutorBasedEventDrivenWorkStealingDispatcher.scala, FSM.scala, Future.scala, HashCode.scala, Helpers.scala, Hex.java, Importer.scala, Iterators.scala, JavaAPI.scala, JavaEventHandler.java, ListenerManagement.scala, Listeners.scala, LockUtil.scala, MACAddressParser.java, MailboxHandling.scala, MessageHandling.scala, Pool.scala, ReflectiveAccess.scala, RemoteEventHandler.scala, RemoteInterface.scala, Routers.scala, Routing.scala, Scheduler.scala, SupervisionConfig.scala, Supervisor.scala, ThreadBasedDispatcher.scala, ThreadPoolBuilder.scala, UUID.java, UUIDGen.java, UUIDHelper.java, UUIDHolder.java, UntypedActor.scala, package.scala, package.scala, pi.scala - -askTypeCompletion at pi.scala(52,59) -================================================================================ -[response] aksTypeCompletion at (52,59) -retrieved 0 members - -================================================================================ - -askTypeCompletion at pi.scala(55,25) -================================================================================ -[response] aksTypeCompletion at (55,25) -retrieved 45 members -`class Broadcastakka.routing.Routing.Broadcast` -`method !=(x$1: Any)Boolean` -`method !=(x$1: AnyRef)Boolean` -`method ##()Int` -`method +(other: String)String` -`method ->[B](y: B)(akka.routing.Routing.type, B)` -`method ==(x$1: Any)Boolean` -`method ==(x$1: AnyRef)Boolean` -`method asInstanceOf[T0]=> T0` -`method clone()Object` -`method dispatcherActor(routing: akka.routing.Routing.PF[Any,akka.actor.ActorRef])akka.actor.ActorRef` -`method dispatcherActor(routing: akka.routing.Routing.PF[Any,akka.actor.ActorRef], msgTransformer: Any => Any)akka.actor.ActorRef` -`method ensuring(cond: Boolean)akka.routing.Routing.type` -`method ensuring(cond: Boolean, msg: => Any)akka.routing.Routing.type` -`method ensuring(cond: akka.routing.Routing.type => Boolean)akka.routing.Routing.type` -`method ensuring(cond: akka.routing.Routing.type => Boolean, msg: => Any)akka.routing.Routing.type` -`method eq(x$1: AnyRef)Boolean` -`method equals(x$1: Any)Boolean` -`method filter[A, B](filter: akka.routing.Routing.PF[A,Unit], filtered: akka.routing.Routing.PF[A,B])akka.routing.Routing.PF[A,B]` -`method finalize()Unit` -`method formatted(fmtstr: String)String` -`method hashCode()Int` -`method intercept[A, B](interceptor: A => Unit, interceptee: akka.routing.Routing.PF[A,B])akka.routing.Routing.PF[A,B]` -`method isInstanceOf[T0]=> Boolean` -`method loadBalancerActor(actors: => akka.routing.InfiniteIterator[akka.actor.ActorRef])akka.actor.ActorRef` -`method loggerActor(actorToLog: akka.actor.ActorRef, logger: Any => Unit)akka.actor.ActorRef` -`method ne(x$1: AnyRef)Boolean` -`method notify()Unit` -`method notifyAll()Unit` -`method synchronized[T0](x$1: T0)T0` -`method toString()String` -`method wait()Unit` -`method wait(x$1: Long)Unit` -`method wait(x$1: Long, x$2: Int)Unit` -`method x=> akka.routing.Routing.type` -`method →[B](y: B)(akka.routing.Routing.type, B)` -`trait RoutingMessageakka.routing.Routing.RoutingMessage` -`type PFakka.routing.Routing.PF` -`value __leftOfArrowakka.routing.Routing.type` -`value __resultOfEnsuringakka.routing.Routing.type` -`value selfAny` -================================================================================ - -askTypeCompletion at pi.scala(55,73) -================================================================================ -[response] aksTypeCompletion at (55,73) -retrieved 131 members -`method !!![T](message: Any, timeout: Long)(implicit sender: Option[akka.actor.ActorRef])akka.dispatch.Future[T]` -`method !!(message: Any, timeout: Long)(implicit sender: Option[akka.actor.ActorRef])Option[Any]` -`method !(message: Any)(implicit sender: Option[akka.actor.ActorRef])Unit` -`method !=(x$1: Any)Boolean` -`method !=(x$1: AnyRef)Boolean` -`method ##()Int` -`method +(other: String)String` -`method ->[B](y: B)(akka.actor.ActorRef, B)` -`method ==(x$1: Any)Boolean` -`method ==(x$1: AnyRef)Boolean` -`method actor=> akka.actor.Actor` -`method actorClass=> Class[_ <: akka.actor.Actor]` -`method actorClassName=> String` -`method actorInstance=> java.util.concurrent.atomic.AtomicReference[akka.actor.Actor]` -`method asInstanceOf[T0]=> T0` -`method channel=> akka.actor.Channel[Any]` -`method clone()Object` -`method compareTo(other: akka.actor.ActorRef)Int` -`method dispatcher=> akka.dispatch.MessageDispatcher` -`method dispatcher_=(md: akka.dispatch.MessageDispatcher)Unit` -`method ensuring(cond: Boolean)akka.actor.ActorRef` -`method ensuring(cond: Boolean, msg: => Any)akka.actor.ActorRef` -`method ensuring(cond: akka.actor.ActorRef => Boolean)akka.actor.ActorRef` -`method ensuring(cond: akka.actor.ActorRef => Boolean, msg: => Any)akka.actor.ActorRef` -`method eq(x$1: AnyRef)Boolean` -`method equals(that: Any)Boolean` -`method exit()Unit` -`method finalize()Unit` -`method formatted(fmtstr: String)String` -`method forward(message: Any)(implicit sender: Some[akka.actor.ActorRef])Any` -`method forward(message: AnyRef, sender: akka.actor.ActorRef)Unit` -`method getActorClass()Class[_ <: akka.actor.Actor]` -`method getActorClassName()String` -`method getChannel=> akka.actor.Channel[Any]` -`method getDispatcher()akka.dispatch.MessageDispatcher` -`method getFaultHandler()akka.config.Supervision.FaultHandlingStrategy` -`method getHomeAddress()java.net.InetSocketAddress` -`method getId()String` -`method getLifeCycle()akka.config.Supervision.LifeCycle` -`method getLinkedActors()java.util.Map[akka.actor.Uuid,akka.actor.ActorRef]` -`method getMailboxSize()Int` -`method getReceiveTimeout()Option[Long]` -`method getSender()Option[akka.actor.ActorRef]` -`method getSenderFuture()Option[akka.dispatch.CompletableFuture[Any]]` -`method getSupervisor()akka.actor.ActorRef` -`method getTimeout()Long` -`method getUuid()akka.actor.Uuid` -`method handleTrapExit(dead: akka.actor.ActorRef, reason: Throwable)Unit` -`method hashCode()Int` -`method homeAddress=> Option[java.net.InetSocketAddress]` -`method id=> String` -`method id_=(id: String)Unit` -`method invoke(messageHandle: akka.dispatch.MessageInvocation)Unit` -`method isBeingRestarted=> Boolean` -`method isDefinedAt(message: Any)Boolean` -`method isInstanceOf[T0]=> Boolean` -`method isRunning=> Boolean` -`method isShutdown=> Boolean` -`method isUnstarted=> Boolean` -`method link(actorRef: akka.actor.ActorRef)Unit` -`method linkedActors=> java.util.Map[akka.actor.Uuid,akka.actor.ActorRef]` -`method mailbox=> AnyRef` -`method mailboxSize=> Int` -`method mailbox_=(value: AnyRef)AnyRef` -`method ne(x$1: AnyRef)Boolean` -`method notify()Unit` -`method notifyAll()Unit` -`method postMessageToMailbox(message: Any, senderOption: Option[akka.actor.ActorRef])Unit` -`method postMessageToMailboxAndCreateFutureResultWithTimeout[T](message: Any, timeout: Long, senderOption: Option[akka.actor.ActorRef], senderFuture: Option[akka.dispatch.CompletableFuture[T]])akka.dispatch.CompletableFuture[T]` -`method registerSupervisorAsRemoteActor=> Option[akka.actor.Uuid]` -`method reply(message: Any)Unit` -`method replySafe(message: AnyRef)Boolean` -`method replyUnsafe(message: AnyRef)Unit` -`method reply_?(message: Any)Boolean` -`method restart(reason: Throwable, maxNrOfRetries: Option[Int], withinTimeRange: Option[Int])Unit` -`method restartLinkedActors(reason: Throwable, maxNrOfRetries: Option[Int], withinTimeRange: Option[Int])Unit` -`method sendOneWay(message: AnyRef)Unit` -`method sendOneWay(message: AnyRef, sender: akka.actor.ActorRef)Unit` -`method sendRequestReply(message: AnyRef)AnyRef` -`method sendRequestReply(message: AnyRef, sender: akka.actor.ActorRef)AnyRef` -`method sendRequestReply(message: AnyRef, timeout: Long, sender: akka.actor.ActorRef)AnyRef` -`method sendRequestReplyFuture[T <: AnyRef](message: AnyRef)akka.dispatch.Future[T]` -`method sendRequestReplyFuture[T <: AnyRef](message: AnyRef, sender: akka.actor.ActorRef)akka.dispatch.Future[T]` -`method sendRequestReplyFuture[T <: AnyRef](message: AnyRef, timeout: Long, sender: akka.actor.ActorRef)akka.dispatch.Future[T]` -`method sender=> Option[akka.actor.ActorRef]` -`method senderFuture()Option[akka.dispatch.CompletableFuture[Any]]` -`method setDispatcher(dispatcher: akka.dispatch.MessageDispatcher)Unit` -`method setFaultHandler(handler: akka.config.Supervision.FaultHandlingStrategy)Unit` -`method setId(x$1: String)Unit` -`method setLifeCycle(lifeCycle: akka.config.Supervision.LifeCycle)Unit` -`method setReceiveTimeout(timeout: Long)Unit` -`method setTimeout(x$1: Long)Unit` -`method spawn(clazz: Class[_ <: akka.actor.Actor])akka.actor.ActorRef` -`method spawnLink(clazz: Class[_ <: akka.actor.Actor])akka.actor.ActorRef` -`method spawnLinkRemote(clazz: Class[_ <: akka.actor.Actor], hostname: String, port: Int, timeout: Long)akka.actor.ActorRef` -`method spawnLinkRemote[T <: akka.actor.Actor](hostname: String, port: Int, timeout: Long)(implicit evidence$4: Manifest[T])akka.actor.ActorRef` -`method spawnLink[T <: akka.actor.Actor](implicit evidence$3: Manifest[T])akka.actor.ActorRef` -`method spawnRemote(clazz: Class[_ <: akka.actor.Actor], hostname: String, port: Int, timeout: Long)akka.actor.ActorRef` -`method spawnRemote[T <: akka.actor.Actor](hostname: String, port: Int, timeout: Long)(implicit evidence$2: Manifest[T])akka.actor.ActorRef` -`method spawn[T <: akka.actor.Actor](implicit evidence$1: Manifest[T])akka.actor.ActorRef` -`method start()akka.actor.ActorRef` -`method startLink(actorRef: akka.actor.ActorRef)Unit` -`method stop()Unit` -`method supervisor=> Option[akka.actor.ActorRef]` -`method supervisor_=(sup: Option[akka.actor.ActorRef])Unit` -`method synchronized[T0](x$1: T0)T0` -`method toString()String` -`method unlink(actorRef: akka.actor.ActorRef)Unit` -`method uuid=> akka.actor.Uuid` -`method uuid_=(uid: akka.actor.Uuid)Unit` -`method wait()Unit` -`method wait(x$1: Long)Unit` -`method wait(x$1: Long, x$2: Int)Unit` -`method x=> akka.actor.ActorRef` -`method →[B](y: B)(akka.actor.ActorRef, B)` -`value __leftOfArrowakka.actor.ActorRef` -`value __resultOfEnsuringakka.actor.ActorRef` -`value selfAny` -`variable _statusakka.actor.ActorRefInternals.StatusType` -`variable _uuidakka.actor.Uuid` -`variable currentMessageakka.dispatch.MessageInvocation` -`variable faultHandlerakka.config.Supervision.FaultHandlingStrategy` -`variable hotswapscala.collection.immutable.Stack[PartialFunction[Any,Unit]]` -`variable idString` -`variable lifeCycleakka.config.Supervision.LifeCycle` -`variable receiveTimeoutOption[Long]` -`variable timeoutLong` -================================================================================ - -askTypeCompletion at pi.scala(65,15) -================================================================================ -[response] aksTypeCompletion at (65,15) -retrieved 131 members -`method !!![T](message: Any, timeout: Long)(implicit sender: Option[akka.actor.ActorRef])akka.dispatch.Future[T]` -`method !!(message: Any, timeout: Long)(implicit sender: Option[akka.actor.ActorRef])Option[Any]` -`method !(message: Any)(implicit sender: Option[akka.actor.ActorRef])Unit` -`method !=(x$1: Any)Boolean` -`method !=(x$1: AnyRef)Boolean` -`method ##()Int` -`method +(other: String)String` -`method ->[B](y: B)(akka.actor.ActorRef, B)` -`method ==(x$1: Any)Boolean` -`method ==(x$1: AnyRef)Boolean` -`method actor=> akka.actor.Actor` -`method actorClass=> Class[_ <: akka.actor.Actor]` -`method actorClassName=> String` -`method actorInstance=> java.util.concurrent.atomic.AtomicReference[akka.actor.Actor]` -`method asInstanceOf[T0]=> T0` -`method channel=> akka.actor.Channel[Any]` -`method clone()Object` -`method compareTo(other: akka.actor.ActorRef)Int` -`method dispatcher=> akka.dispatch.MessageDispatcher` -`method dispatcher_=(md: akka.dispatch.MessageDispatcher)Unit` -`method ensuring(cond: Boolean)akka.actor.ActorRef` -`method ensuring(cond: Boolean, msg: => Any)akka.actor.ActorRef` -`method ensuring(cond: akka.actor.ActorRef => Boolean)akka.actor.ActorRef` -`method ensuring(cond: akka.actor.ActorRef => Boolean, msg: => Any)akka.actor.ActorRef` -`method eq(x$1: AnyRef)Boolean` -`method equals(that: Any)Boolean` -`method exit()Unit` -`method finalize()Unit` -`method formatted(fmtstr: String)String` -`method forward(message: Any)(implicit sender: Some[akka.actor.ActorRef])Any` -`method forward(message: AnyRef, sender: akka.actor.ActorRef)Unit` -`method getActorClass()Class[_ <: akka.actor.Actor]` -`method getActorClassName()String` -`method getChannel=> akka.actor.Channel[Any]` -`method getDispatcher()akka.dispatch.MessageDispatcher` -`method getFaultHandler()akka.config.Supervision.FaultHandlingStrategy` -`method getHomeAddress()java.net.InetSocketAddress` -`method getId()String` -`method getLifeCycle()akka.config.Supervision.LifeCycle` -`method getLinkedActors()java.util.Map[akka.actor.Uuid,akka.actor.ActorRef]` -`method getMailboxSize()Int` -`method getReceiveTimeout()Option[Long]` -`method getSender()Option[akka.actor.ActorRef]` -`method getSenderFuture()Option[akka.dispatch.CompletableFuture[Any]]` -`method getSupervisor()akka.actor.ActorRef` -`method getTimeout()Long` -`method getUuid()akka.actor.Uuid` -`method handleTrapExit(dead: akka.actor.ActorRef, reason: Throwable)Unit` -`method hashCode()Int` -`method homeAddress=> Option[java.net.InetSocketAddress]` -`method id=> String` -`method id_=(id: String)Unit` -`method invoke(messageHandle: akka.dispatch.MessageInvocation)Unit` -`method isBeingRestarted=> Boolean` -`method isDefinedAt(message: Any)Boolean` -`method isInstanceOf[T0]=> Boolean` -`method isRunning=> Boolean` -`method isShutdown=> Boolean` -`method isUnstarted=> Boolean` -`method link(actorRef: akka.actor.ActorRef)Unit` -`method linkedActors=> java.util.Map[akka.actor.Uuid,akka.actor.ActorRef]` -`method mailbox=> AnyRef` -`method mailboxSize=> Int` -`method mailbox_=(value: AnyRef)AnyRef` -`method ne(x$1: AnyRef)Boolean` -`method notify()Unit` -`method notifyAll()Unit` -`method postMessageToMailbox(message: Any, senderOption: Option[akka.actor.ActorRef])Unit` -`method postMessageToMailboxAndCreateFutureResultWithTimeout[T](message: Any, timeout: Long, senderOption: Option[akka.actor.ActorRef], senderFuture: Option[akka.dispatch.CompletableFuture[T]])akka.dispatch.CompletableFuture[T]` -`method registerSupervisorAsRemoteActor=> Option[akka.actor.Uuid]` -`method reply(message: Any)Unit` -`method replySafe(message: AnyRef)Boolean` -`method replyUnsafe(message: AnyRef)Unit` -`method reply_?(message: Any)Boolean` -`method restart(reason: Throwable, maxNrOfRetries: Option[Int], withinTimeRange: Option[Int])Unit` -`method restartLinkedActors(reason: Throwable, maxNrOfRetries: Option[Int], withinTimeRange: Option[Int])Unit` -`method sendOneWay(message: AnyRef)Unit` -`method sendOneWay(message: AnyRef, sender: akka.actor.ActorRef)Unit` -`method sendRequestReply(message: AnyRef)AnyRef` -`method sendRequestReply(message: AnyRef, sender: akka.actor.ActorRef)AnyRef` -`method sendRequestReply(message: AnyRef, timeout: Long, sender: akka.actor.ActorRef)AnyRef` -`method sendRequestReplyFuture[T <: AnyRef](message: AnyRef)akka.dispatch.Future[T]` -`method sendRequestReplyFuture[T <: AnyRef](message: AnyRef, sender: akka.actor.ActorRef)akka.dispatch.Future[T]` -`method sendRequestReplyFuture[T <: AnyRef](message: AnyRef, timeout: Long, sender: akka.actor.ActorRef)akka.dispatch.Future[T]` -`method sender=> Option[akka.actor.ActorRef]` -`method senderFuture()Option[akka.dispatch.CompletableFuture[Any]]` -`method setDispatcher(dispatcher: akka.dispatch.MessageDispatcher)Unit` -`method setFaultHandler(handler: akka.config.Supervision.FaultHandlingStrategy)Unit` -`method setId(x$1: String)Unit` -`method setLifeCycle(lifeCycle: akka.config.Supervision.LifeCycle)Unit` -`method setReceiveTimeout(timeout: Long)Unit` -`method setTimeout(x$1: Long)Unit` -`method spawn(clazz: Class[_ <: akka.actor.Actor])akka.actor.ActorRef` -`method spawnLink(clazz: Class[_ <: akka.actor.Actor])akka.actor.ActorRef` -`method spawnLinkRemote(clazz: Class[_ <: akka.actor.Actor], hostname: String, port: Int, timeout: Long)akka.actor.ActorRef` -`method spawnLinkRemote[T <: akka.actor.Actor](hostname: String, port: Int, timeout: Long)(implicit evidence$4: Manifest[T])akka.actor.ActorRef` -`method spawnLink[T <: akka.actor.Actor](implicit evidence$3: Manifest[T])akka.actor.ActorRef` -`method spawnRemote(clazz: Class[_ <: akka.actor.Actor], hostname: String, port: Int, timeout: Long)akka.actor.ActorRef` -`method spawnRemote[T <: akka.actor.Actor](hostname: String, port: Int, timeout: Long)(implicit evidence$2: Manifest[T])akka.actor.ActorRef` -`method spawn[T <: akka.actor.Actor](implicit evidence$1: Manifest[T])akka.actor.ActorRef` -`method start()akka.actor.ActorRef` -`method startLink(actorRef: akka.actor.ActorRef)Unit` -`method stop()Unit` -`method supervisor=> Option[akka.actor.ActorRef]` -`method supervisor_=(sup: Option[akka.actor.ActorRef])Unit` -`method synchronized[T0](x$1: T0)T0` -`method toString()String` -`method unlink(actorRef: akka.actor.ActorRef)Unit` -`method uuid=> akka.actor.Uuid` -`method uuid_=(uid: akka.actor.Uuid)Unit` -`method wait()Unit` -`method wait(x$1: Long)Unit` -`method wait(x$1: Long, x$2: Int)Unit` -`method x=> akka.actor.ActorRef` -`method →[B](y: B)(akka.actor.ActorRef, B)` -`value __leftOfArrowakka.actor.ActorRef` -`value __resultOfEnsuringakka.actor.ActorRef` -`value selfAny` -`variable _statusakka.actor.ActorRefInternals.StatusType` -`variable _uuidakka.actor.Uuid` -`variable currentMessageakka.dispatch.MessageInvocation` -`variable faultHandlerakka.config.Supervision.FaultHandlingStrategy` -`variable hotswapscala.collection.immutable.Stack[PartialFunction[Any,Unit]]` -`variable idString` -`variable lifeCycleakka.config.Supervision.LifeCycle` -`variable receiveTimeoutOption[Long]` -`variable timeoutLong` -================================================================================ - -askTypeCompletion at pi.scala(74,46) -================================================================================ -[response] aksTypeCompletion at (74,46) -retrieved 131 members -`method !!![T](message: Any, timeout: Long)(implicit sender: Option[akka.actor.ActorRef])akka.dispatch.Future[T]` -`method !!(message: Any, timeout: Long)(implicit sender: Option[akka.actor.ActorRef])Option[Any]` -`method !(message: Any)(implicit sender: Option[akka.actor.ActorRef])Unit` -`method !=(x$1: Any)Boolean` -`method !=(x$1: AnyRef)Boolean` -`method ##()Int` -`method +(other: String)String` -`method ->[B](y: B)(akka.actor.ScalaActorRef, B)` -`method ==(x$1: Any)Boolean` -`method ==(x$1: AnyRef)Boolean` -`method actor=> akka.actor.Actor` -`method actorClass=> Class[_ <: akka.actor.Actor]` -`method actorClassName=> String` -`method actorInstance=> java.util.concurrent.atomic.AtomicReference[akka.actor.Actor]` -`method asInstanceOf[T0]=> T0` -`method channel=> akka.actor.Channel[Any]` -`method clone()Object` -`method compareTo(other: akka.actor.ActorRef)Int` -`method dispatcher=> akka.dispatch.MessageDispatcher` -`method dispatcher_=(md: akka.dispatch.MessageDispatcher)Unit` -`method ensuring(cond: Boolean)akka.actor.ScalaActorRef` -`method ensuring(cond: Boolean, msg: => Any)akka.actor.ScalaActorRef` -`method ensuring(cond: akka.actor.ScalaActorRef => Boolean)akka.actor.ScalaActorRef` -`method ensuring(cond: akka.actor.ScalaActorRef => Boolean, msg: => Any)akka.actor.ScalaActorRef` -`method eq(x$1: AnyRef)Boolean` -`method equals(x$1: Any)Boolean` -`method exit()Unit` -`method finalize()Unit` -`method formatted(fmtstr: String)String` -`method forward(message: Any)(implicit sender: Some[akka.actor.ActorRef])Any` -`method forward(message: AnyRef, sender: akka.actor.ActorRef)Unit` -`method getActorClass()Class[_ <: akka.actor.Actor]` -`method getActorClassName()String` -`method getChannel=> akka.actor.Channel[Any]` -`method getDispatcher()akka.dispatch.MessageDispatcher` -`method getFaultHandler()akka.config.Supervision.FaultHandlingStrategy` -`method getHomeAddress()java.net.InetSocketAddress` -`method getId()String` -`method getLifeCycle()akka.config.Supervision.LifeCycle` -`method getLinkedActors()java.util.Map[akka.actor.Uuid,akka.actor.ActorRef]` -`method getMailboxSize()Int` -`method getReceiveTimeout()Option[Long]` -`method getSender()Option[akka.actor.ActorRef]` -`method getSenderFuture()Option[akka.dispatch.CompletableFuture[Any]]` -`method getSupervisor()akka.actor.ActorRef` -`method getTimeout()Long` -`method getUuid()akka.actor.Uuid` -`method handleTrapExit(dead: akka.actor.ActorRef, reason: Throwable)Unit` -`method hashCode()Int` -`method homeAddress=> Option[java.net.InetSocketAddress]` -`method id=> String` -`method id_=(id: String)Unit` -`method invoke(messageHandle: akka.dispatch.MessageInvocation)Unit` -`method isBeingRestarted=> Boolean` -`method isDefinedAt(message: Any)Boolean` -`method isInstanceOf[T0]=> Boolean` -`method isRunning=> Boolean` -`method isShutdown=> Boolean` -`method isUnstarted=> Boolean` -`method link(actorRef: akka.actor.ActorRef)Unit` -`method linkedActors=> java.util.Map[akka.actor.Uuid,akka.actor.ActorRef]` -`method mailbox=> AnyRef` -`method mailboxSize=> Int` -`method mailbox_=(value: AnyRef)AnyRef` -`method ne(x$1: AnyRef)Boolean` -`method notify()Unit` -`method notifyAll()Unit` -`method postMessageToMailbox(message: Any, senderOption: Option[akka.actor.ActorRef])Unit` -`method postMessageToMailboxAndCreateFutureResultWithTimeout[T](message: Any, timeout: Long, senderOption: Option[akka.actor.ActorRef], senderFuture: Option[akka.dispatch.CompletableFuture[T]])akka.dispatch.CompletableFuture[T]` -`method registerSupervisorAsRemoteActor=> Option[akka.actor.Uuid]` -`method reply(message: Any)Unit` -`method replySafe(message: AnyRef)Boolean` -`method replyUnsafe(message: AnyRef)Unit` -`method reply_?(message: Any)Boolean` -`method restart(reason: Throwable, maxNrOfRetries: Option[Int], withinTimeRange: Option[Int])Unit` -`method restartLinkedActors(reason: Throwable, maxNrOfRetries: Option[Int], withinTimeRange: Option[Int])Unit` -`method sendOneWay(message: AnyRef)Unit` -`method sendOneWay(message: AnyRef, sender: akka.actor.ActorRef)Unit` -`method sendRequestReply(message: AnyRef)AnyRef` -`method sendRequestReply(message: AnyRef, sender: akka.actor.ActorRef)AnyRef` -`method sendRequestReply(message: AnyRef, timeout: Long, sender: akka.actor.ActorRef)AnyRef` -`method sendRequestReplyFuture[T <: AnyRef](message: AnyRef)akka.dispatch.Future[T]` -`method sendRequestReplyFuture[T <: AnyRef](message: AnyRef, sender: akka.actor.ActorRef)akka.dispatch.Future[T]` -`method sendRequestReplyFuture[T <: AnyRef](message: AnyRef, timeout: Long, sender: akka.actor.ActorRef)akka.dispatch.Future[T]` -`method sender=> Option[akka.actor.ActorRef]` -`method senderFuture()Option[akka.dispatch.CompletableFuture[Any]]` -`method setDispatcher(dispatcher: akka.dispatch.MessageDispatcher)Unit` -`method setFaultHandler(x$1: akka.config.Supervision.FaultHandlingStrategy)Unit` -`method setId(x$1: String)Unit` -`method setLifeCycle(x$1: akka.config.Supervision.LifeCycle)Unit` -`method setReceiveTimeout(timeout: Long)Unit` -`method setTimeout(x$1: Long)Unit` -`method spawn(clazz: Class[_ <: akka.actor.Actor])akka.actor.ActorRef` -`method spawnLink(clazz: Class[_ <: akka.actor.Actor])akka.actor.ActorRef` -`method spawnLinkRemote(clazz: Class[_ <: akka.actor.Actor], hostname: String, port: Int, timeout: Long)akka.actor.ActorRef` -`method spawnLinkRemote[T <: akka.actor.Actor](hostname: String, port: Int, timeout: Long)(implicit evidence$4: Manifest[T])akka.actor.ActorRef` -`method spawnLink[T <: akka.actor.Actor](implicit evidence$3: Manifest[T])akka.actor.ActorRef` -`method spawnRemote(clazz: Class[_ <: akka.actor.Actor], hostname: String, port: Int, timeout: Long)akka.actor.ActorRef` -`method spawnRemote[T <: akka.actor.Actor](hostname: String, port: Int, timeout: Long)(implicit evidence$2: Manifest[T])akka.actor.ActorRef` -`method spawn[T <: akka.actor.Actor](implicit evidence$1: Manifest[T])akka.actor.ActorRef` -`method start()akka.actor.ActorRef` -`method startLink(actorRef: akka.actor.ActorRef)Unit` -`method stop()Unit` -`method supervisor=> Option[akka.actor.ActorRef]` -`method supervisor_=(sup: Option[akka.actor.ActorRef])Unit` -`method synchronized[T0](x$1: T0)T0` -`method toString()String` -`method unlink(actorRef: akka.actor.ActorRef)Unit` -`method uuid=> akka.actor.Uuid` -`method uuid_=(uid: akka.actor.Uuid)Unit` -`method wait()Unit` -`method wait(x$1: Long)Unit` -`method wait(x$1: Long, x$2: Int)Unit` -`method x=> akka.actor.ScalaActorRef` -`method →[B](y: B)(akka.actor.ScalaActorRef, B)` -`value __leftOfArrowakka.actor.ScalaActorRef` -`value __resultOfEnsuringakka.actor.ScalaActorRef` -`value selfAny` -`variable _statusakka.actor.ActorRefInternals.StatusType` -`variable _uuidakka.actor.Uuid` -`variable currentMessageakka.dispatch.MessageInvocation` -`variable faultHandlerakka.config.Supervision.FaultHandlingStrategy` -`variable hotswapscala.collection.immutable.Stack[PartialFunction[Any,Unit]]` -`variable idString` -`variable lifeCycleakka.config.Supervision.LifeCycle` -`variable receiveTimeoutOption[Long]` -`variable timeoutLong` -================================================================================ - -askType at pi.scala(34,16) -================================================================================ -[response] askTypeAt at (34,16) -def receive: PartialFunction[Any,Unit] = ((x0$3: Any) => x0$3 match { - case (start: Int, nrOfElements: Int)Pi.Work((start @ _), (nrOfElements @ _)) => Worker.this.self.reply(Pi.this.Result.apply(Worker.this.calculatePiFor(start, nrOfElements))) -}) -================================================================================ - -askHyperlinkPos for `calculate` at (11,11) pi.scala -================================================================================ -[response] found askHyperlinkPos for `calculate` at (93,7) pi.scala -================================================================================ - -askHyperlinkPos for `PiMessage` at (17,41) pi.scala -================================================================================ -[response] found askHyperlinkPos for `PiMessage` at (16,16) pi.scala -================================================================================ - -askHyperlinkPos for `Actor` at (24,28) pi.scala -================================================================================ -[response] found askHyperlinkPos for `Actor` at (289,7) Actor.scala -================================================================================ - -askHyperlinkPos for `reply` at (36,18) pi.scala -================================================================================ -[response] found askHyperlinkPos for `reply` at (1382,7) ActorRef.scala -================================================================================ - -askHyperlinkPos for `nrOfResults` at (73,19) pi.scala -================================================================================ -[response] found askHyperlinkPos for `nrOfResults` at (48,9) pi.scala -================================================================================ - -askHyperlinkPos for `latch` at (86,11) pi.scala -================================================================================ -[response] found askHyperlinkPos for `latch` at (44,61) pi.scala -================================================================================ diff --git a/test/files/presentation/akka.flags b/test/files/presentation/akka.flags deleted file mode 100644 index 56d026a62d..0000000000 --- a/test/files/presentation/akka.flags +++ /dev/null @@ -1,18 +0,0 @@ -# This file contains command line options that are passed to the presentation compiler -# Lines starting with # are stripped, and you can split arguments on several lines. - -# The -bootclasspath option is treated specially by the test framework: if it's not specified -# in this file, the presentation compiler will pick up the scala-library/compiler that's on the -# java classpath used to run this test (usually build/pack) - -# Any option can be passed this way, like presentation debug -# -Ypresentation-debug -Ypresentation-verbose - -# the classpath is relative to the current working directory. That means it depends where you're -# running partest from. Run it from the root scala checkout for these files to resolve correctly -# (by default when running 'ant test', or 'test/partest'). Paths use Unix separators, the test -# framework translates them to the platform dependent representation. -# -bootclasspath lib/scala-compiler.jar:lib/scala-library.jar:lib/fjbg.jar - -# the following line would test using the quick compiler -# -bootclasspath build/quick/classes/compiler:build/quick/classes/library:lib/fjbg.jar diff --git a/test/files/presentation/akka/Runner.scala b/test/files/presentation/akka/Runner.scala deleted file mode 100644 index 14a6aa8350..0000000000 --- a/test/files/presentation/akka/Runner.scala +++ /dev/null @@ -1,3 +0,0 @@ -import scala.tools.nsc.interactive.tests.InteractiveTest - -object Test extends InteractiveTest diff --git a/test/files/presentation/akka/src/akka/AkkaException.scala b/test/files/presentation/akka/src/akka/AkkaException.scala deleted file mode 100644 index 155a7a16b5..0000000000 --- a/test/files/presentation/akka/src/akka/AkkaException.scala +++ /dev/null @@ -1,40 +0,0 @@ -/** - * Copyright (C) 2009-2011 Scalable Solutions AB - */ - -package akka - -import akka.actor.newUuid -import java.net.{ InetAddress, UnknownHostException } - -/** - * Akka base Exception. Each Exception gets: - *

        - *
      • a uuid for tracking purposes
      • - *
      • toString that includes exception name, message, uuid, and the stacktrace
      • - *
      - * - * @author Jonas Bonér - */ -class AkkaException(message: String = "", cause: Throwable = null) extends RuntimeException(message, cause) with Serializable { - val uuid = "%s_%s".format(AkkaException.hostname, newUuid) - - override lazy val toString = - "%s: %s\n[%s]\n%s".format(getClass.getName, message, uuid, stackTraceToString) - - def stackTraceToString = { - val trace = getStackTrace - val sb = new StringBuffer - for (i ← 0 until trace.length) - sb.append("\tat %s\n" format trace(i)) - sb.toString - } -} - -object AkkaException { - val hostname = try { - InetAddress.getLocalHost.getHostName - } catch { - case e: UnknownHostException => "unknown" - } -} diff --git a/test/files/presentation/akka/src/akka/actor/Actor.scala b/test/files/presentation/akka/src/akka/actor/Actor.scala deleted file mode 100644 index b955c4c38b..0000000000 --- a/test/files/presentation/akka/src/akka/actor/Actor.scala +++ /dev/null @@ -1,503 +0,0 @@ -/** Copyright (C) 2009-2011 Scalable Solutions AB - */ - -package akka.actor - -import akka.dispatch._ -import akka.config.Config._ -import akka.util.Helpers.{ narrow, narrowSilently } -import akka.util.ListenerManagement -import akka.AkkaException - -import scala.beans.BeanProperty -import akka.util.{ ReflectiveAccess, Duration } -import akka.remoteinterface.RemoteSupport -import akka.japi.{ Creator, Procedure } -import java.lang.reflect.InvocationTargetException - -/** Life-cycle messages for the Actors - */ -sealed trait LifeCycleMessage extends Serializable - -/* Marker trait to show which Messages are automatically handled by Akka */ -sealed trait AutoReceivedMessage { self: LifeCycleMessage => } - -case class HotSwap(code: ActorRef => Actor.Receive, discardOld: Boolean = true) - extends AutoReceivedMessage with LifeCycleMessage { - - /** Java API - */ - def this(code: akka.japi.Function[ActorRef, Procedure[Any]], discardOld: Boolean) = - this((self: ActorRef) => { - val behavior = code(self) - val result: Actor.Receive = { case msg => behavior(msg) } - result - }, discardOld) - - /** Java API with default non-stacking behavior - */ - def this(code: akka.japi.Function[ActorRef, Procedure[Any]]) = this(code, true) -} - -case object RevertHotSwap extends AutoReceivedMessage with LifeCycleMessage - -case class Restart(reason: Throwable) extends AutoReceivedMessage with LifeCycleMessage - -case class Exit(dead: ActorRef, killer: Throwable) extends AutoReceivedMessage with LifeCycleMessage - -case class Link(child: ActorRef) extends AutoReceivedMessage with LifeCycleMessage - -case class Unlink(child: ActorRef) extends AutoReceivedMessage with LifeCycleMessage - -case class UnlinkAndStop(child: ActorRef) extends AutoReceivedMessage with LifeCycleMessage - -case object PoisonPill extends AutoReceivedMessage with LifeCycleMessage - -case object Kill extends AutoReceivedMessage with LifeCycleMessage - -case object ReceiveTimeout extends LifeCycleMessage - -case class MaximumNumberOfRestartsWithinTimeRangeReached( - @BeanProperty val victim: ActorRef, - @BeanProperty val maxNrOfRetries: Option[Int], - @BeanProperty val withinTimeRange: Option[Int], - @BeanProperty val lastExceptionCausingRestart: Throwable) extends LifeCycleMessage - -// Exceptions for Actors -class ActorStartException private[akka] (message: String, cause: Throwable = null) extends AkkaException(message, cause) -class IllegalActorStateException private[akka] (message: String, cause: Throwable = null) extends AkkaException(message, cause) -class ActorKilledException private[akka] (message: String, cause: Throwable = null) extends AkkaException(message, cause) -class ActorInitializationException private[akka] (message: String, cause: Throwable = null) extends AkkaException(message, cause) -class ActorTimeoutException private[akka] (message: String, cause: Throwable = null) extends AkkaException(message, cause) -class InvalidMessageException private[akka] (message: String, cause: Throwable = null) extends AkkaException(message, cause) - -/** This message is thrown by default when an Actors behavior doesn't match a message - */ -case class UnhandledMessageException(msg: Any, ref: ActorRef) extends Exception { - override def getMessage() = "Actor %s does not handle [%s]".format(ref, msg) - override def fillInStackTrace() = this //Don't waste cycles generating stack trace -} - -/** Actor factory module with factory methods for creating various kinds of Actors. - * - * @author Jonas Bonér - */ -object Actor extends ListenerManagement { - - /** Add shutdown cleanups - */ - private[akka] lazy val shutdownHook = { - val hook = new Runnable { - override def run { - // Clear Thread.subclassAudits - val tf = classOf[java.lang.Thread].getDeclaredField("subclassAudits") - tf.setAccessible(true) - val subclassAudits = tf.get(null).asInstanceOf[java.util.Map[_, _]] - subclassAudits synchronized { subclassAudits.clear } - } - } - Runtime.getRuntime.addShutdownHook(new Thread(hook)) - hook - } - - val registry = new ActorRegistry - - lazy val remote: RemoteSupport = { - ReflectiveAccess - .Remote - .defaultRemoteSupport - .map(_()) - .getOrElse(throw new UnsupportedOperationException("You need to have akka-remote.jar on classpath")) - } - - private[akka] val TIMEOUT = Duration(config.getInt("akka.actor.timeout", 5), TIME_UNIT).toMillis - private[akka] val SERIALIZE_MESSAGES = config.getBool("akka.actor.serialize-messages", false) - - /** A Receive is a convenience type that defines actor message behavior currently modeled as - * a PartialFunction[Any, Unit]. - */ - type Receive = PartialFunction[Any, Unit] - - private[actor] val actorRefInCreation = new ThreadLocal[Option[ActorRef]] { - override def initialValue = None - } - - /** Creates an ActorRef out of the Actor with type T. - *
      -   *   import Actor._
      -   *   val actor = actorOf[MyActor]
      -   *   actor.start()
      -   *   actor ! message
      -   *   actor.stop()
      -   *  
      - * You can create and start the actor in one statement like this: - *
      -   *   val actor = actorOf[MyActor].start()
      -   *  
      - */ - def actorOf[T <: Actor: Manifest]: ActorRef = actorOf(manifest[T].erasure.asInstanceOf[Class[_ <: Actor]]) - - /** Creates an ActorRef out of the Actor of the specified Class. - *
      -   *   import Actor._
      -   *   val actor = actorOf(classOf[MyActor])
      -   *   actor.start()
      -   *   actor ! message
      -   *   actor.stop()
      -   *  
      - * You can create and start the actor in one statement like this: - *
      -   *   val actor = actorOf(classOf[MyActor]).start()
      -   *  
      - */ - def actorOf(clazz: Class[_ <: Actor]): ActorRef = new LocalActorRef(() => { - import ReflectiveAccess.{ createInstance, noParams, noArgs } - createInstance[Actor](clazz.asInstanceOf[Class[_]], noParams, noArgs) match { - case Right(actor) => actor - case Left(exception) => - val cause = exception match { - case i: InvocationTargetException => i.getTargetException - case _ => exception - } - - throw new ActorInitializationException( - "Could not instantiate Actor of " + clazz + - "\nMake sure Actor is NOT defined inside a class/trait," + - "\nif so put it outside the class/trait, f.e. in a companion object," + - "\nOR try to change: 'actorOf[MyActor]' to 'actorOf(new MyActor)'.", cause) - } - - }, None) - - /** Creates an ActorRef out of the Actor. Allows you to pass in a factory function - * that creates the Actor. Please note that this function can be invoked multiple - * times if for example the Actor is supervised and needs to be restarted. - *

      - * This function should NOT be used for remote actors. - *

      -   *   import Actor._
      -   *   val actor = actorOf(new MyActor)
      -   *   actor.start()
      -   *   actor ! message
      -   *   actor.stop()
      -   *  
      - * You can create and start the actor in one statement like this: - *
      -   *   val actor = actorOf(new MyActor).start()
      -   *  
      - */ - def actorOf(factory: => Actor): ActorRef = new LocalActorRef(() => factory, None) - - /** Creates an ActorRef out of the Actor. Allows you to pass in a factory (Creator) - * that creates the Actor. Please note that this function can be invoked multiple - * times if for example the Actor is supervised and needs to be restarted. - *

      - * This function should NOT be used for remote actors. - * JAVA API - */ - def actorOf(creator: Creator[Actor]): ActorRef = new LocalActorRef(() => creator.create, None) - - /** Use to spawn out a block of code in an event-driven actor. Will shut actor down when - * the block has been executed. - *

      - * NOTE: If used from within an Actor then has to be qualified with 'Actor.spawn' since - * there is a method 'spawn[ActorType]' in the Actor trait already. - * Example: - *

      -   *  import Actor.{spawn}
      -   *
      -   *  spawn  {
      -   *   ... // do stuff
      -   *  }
      -   *  
      - */ - def spawn(body: => Unit)(implicit dispatcher: MessageDispatcher = Dispatchers.defaultGlobalDispatcher): Unit = { - case object Spawn - actorOf(new Actor() { - self.dispatcher = dispatcher - def receive = { - case Spawn => try { body } finally { self.stop() } - } - }).start() ! Spawn - } - - /** Implicitly converts the given Option[Any] to a AnyOptionAsTypedOption which offers the method as[T] - * to convert an Option[Any] to an Option[T]. - */ - implicit def toAnyOptionAsTypedOption(anyOption: Option[Any]) = new AnyOptionAsTypedOption(anyOption) - - /** Implicitly converts the given Future[_] to a AnyOptionAsTypedOption which offers the method as[T] - * to convert an Option[Any] to an Option[T]. - * This means that the following code is equivalent: - * (actor !! "foo").as[Int] (Deprecated) - * and - * (actor !!! "foo").as[Int] (Recommended) - */ - implicit def futureToAnyOptionAsTypedOption(anyFuture: Future[_]) = new AnyOptionAsTypedOption({ - try { anyFuture.await } catch { case t: FutureTimeoutException => } - anyFuture.resultOrException - }) -} - -/** Actor base trait that should be extended by or mixed to create an Actor with the semantics of the 'Actor Model': - * http://en.wikipedia.org/wiki/Actor_model - *

      - * An actor has a well-defined (non-cyclic) life-cycle. - *

      - *  => NEW (newly created actor) - can't receive messages (yet)
      - *     => STARTED (when 'start' is invoked) - can receive messages
      - *         => SHUT DOWN (when 'exit' is invoked) - can't do anything
      - *  
      - * - *

      - * The Actor's API is available in the 'self' member variable. - * - *

      - * Here you find functions like: - * - !, !!, !!! and forward - * - link, unlink, startLink, spawnLink etc - * - makeRemote etc. - * - start, stop - * - etc. - * - *

      - * Here you also find fields like - * - dispatcher = ... - * - id = ... - * - lifeCycle = ... - * - faultHandler = ... - * - trapExit = ... - * - etc. - * - *

      - * This means that to use them you have to prefix them with 'self', like this: self ! Message - * - * However, for convenience you can import these functions and fields like below, which will allow you do - * drop the 'self' prefix: - *

      - *  class MyActor extends Actor  {
      - *   import self._
      - *   id = ...
      - *   dispatcher = ...
      - *   spawnLink[OtherActor]
      - *   ...
      - *  }
      - *  
      - * - * @author Jonas Bonér - */ -trait Actor { - - /** Type alias because traits cannot have companion objects. - */ - type Receive = Actor.Receive - - /* - * Some[ActorRef] representation of the 'self' ActorRef reference. - *

      - * Mainly for internal use, functions as the implicit sender references when invoking - * the 'forward' function. - */ - @transient - implicit val someSelf: Some[ActorRef] = { - val optRef = Actor.actorRefInCreation.get - if (optRef.isEmpty) throw new ActorInitializationException( - "ActorRef for instance of actor [" + getClass.getName + "] is not in scope." + - "\n\tYou can not create an instance of an actor explicitly using 'new MyActor'." + - "\n\tYou have to use one of the factory methods in the 'Actor' object to create a new actor." + - "\n\tEither use:" + - "\n\t\t'val actor = Actor.actorOf[MyActor]', or" + - "\n\t\t'val actor = Actor.actorOf(new MyActor(..))'") - Actor.actorRefInCreation.set(None) - optRef.asInstanceOf[Some[ActorRef]].get.id = getClass.getName //FIXME: Is this needed? - optRef.asInstanceOf[Some[ActorRef]] - } - - /* - * Option[ActorRef] representation of the 'self' ActorRef reference. - *

      - * Mainly for internal use, functions as the implicit sender references when invoking - * one of the message send functions ('!', '!!' and '!!!'). - */ - implicit def optionSelf: Option[ActorRef] = someSelf - - /** The 'self' field holds the ActorRef for this actor. - *

      - * Can be used to send messages to itself: - *

      -   *  self ! message
      -   *  
      - * Here you also find most of the Actor API. - *

      - * For example fields like: - *

      -   *  self.dispatcher = ...
      -   *  self.trapExit = ...
      -   *  self.faultHandler = ...
      -   *  self.lifeCycle = ...
      -   *  self.sender
      -   *  
      - *

      - * Here you also find methods like: - *

      -   *  self.reply(..)
      -   *  self.link(..)
      -   *  self.unlink(..)
      -   *  self.start(..)
      -   *  self.stop(..)
      -   *  
      - */ - @transient - val self: ScalaActorRef = someSelf.get - - /** User overridable callback/setting. - *

      - * Partial function implementing the actor logic. - * To be implemented by concrete actor class. - *

      - * Example code: - *

      -   *   def receive = {
      -   *     case Ping =>
      -   *       println("got a 'Ping' message")
      -   *       self.reply("pong")
      -   *
      -   *     case OneWay =>
      -   *       println("got a 'OneWay' message")
      -   *
      -   *     case unknown =>
      -   *       println("unknown message: " + unknown)
      -   *  }
      -   *  
      - */ - protected def receive: Receive - - /** User overridable callback. - *

      - * Is called when an Actor is started by invoking 'actor.start()'. - */ - def preStart() {} - - /** User overridable callback. - *

      - * Is called when 'actor.stop()' is invoked. - */ - def postStop() {} - - /** User overridable callback. - *

      - * Is called on a crashed Actor right BEFORE it is restarted to allow clean up of resources before Actor is terminated. - */ - def preRestart(reason: Throwable) {} - - /** User overridable callback. - *

      - * Is called right AFTER restart on the newly created Actor to allow reinitialization after an Actor crash. - */ - def postRestart(reason: Throwable) {} - - /** User overridable callback. - *

      - * Is called when a message isn't handled by the current behavior of the actor - * by default it throws an UnhandledMessageException - */ - def unhandled(msg: Any) { - throw new UnhandledMessageException(msg, self) - } - - /** Is the actor able to handle the message passed in as arguments? - */ - def isDefinedAt(message: Any): Boolean = { - val behaviorStack = self.hotswap - message match { //Same logic as apply(msg) but without the unhandled catch-all - case l: AutoReceivedMessage => true - case msg if behaviorStack.nonEmpty && - behaviorStack.head.isDefinedAt(msg) => true - case msg if behaviorStack.isEmpty && - processingBehavior.isDefinedAt(msg) => true - case _ => false - } - } - - /** Changes the Actor's behavior to become the new 'Receive' (PartialFunction[Any, Unit]) handler. - * Puts the behavior on top of the hotswap stack. - * If "discardOld" is true, an unbecome will be issued prior to pushing the new behavior to the stack - */ - def become(behavior: Receive, discardOld: Boolean = true) { - if (discardOld) unbecome() - self.hotswap = self.hotswap.push(behavior) - } - - /** Reverts the Actor behavior to the previous one in the hotswap stack. - */ - def unbecome(): Unit = { - val h = self.hotswap - if (h.nonEmpty) self.hotswap = h.pop - } - - // ========================================= - // ==== INTERNAL IMPLEMENTATION DETAILS ==== - // ========================================= - - private[akka] final def apply(msg: Any) = { - if (msg.isInstanceOf[AnyRef] && (msg.asInstanceOf[AnyRef] eq null)) - throw new InvalidMessageException("Message from [" + self.sender + "] to [" + self.toString + "] is null") - val behaviorStack = self.hotswap - msg match { - case l: AutoReceivedMessage => autoReceiveMessage(l) - case msg if behaviorStack.nonEmpty && - behaviorStack.head.isDefinedAt(msg) => behaviorStack.head.apply(msg) - case msg if behaviorStack.isEmpty && - processingBehavior.isDefinedAt(msg) => processingBehavior.apply(msg) - case unknown => unhandled(unknown) //This is the only line that differs from processingbehavior - } - } - - private final def autoReceiveMessage(msg: AutoReceivedMessage): Unit = msg match { - case HotSwap(code, discardOld) => become(code(self), discardOld) - case RevertHotSwap => unbecome() - case Exit(dead, reason) => self.handleTrapExit(dead, reason) - case Link(child) => self.link(child) - case Unlink(child) => self.unlink(child) - case UnlinkAndStop(child) => self.unlink(child); child.stop() - case Restart(reason) => throw reason - case Kill => throw new ActorKilledException("Kill") - case PoisonPill => - val f = self.senderFuture - self.stop() - if (f.isDefined) f.get.completeWithException(new ActorKilledException("PoisonPill")) - } - - private lazy val processingBehavior = receive //ProcessingBehavior is the original behavior -} - -private[actor] class AnyOptionAsTypedOption(anyOption: Option[Any]) { - - /** Convenience helper to cast the given Option of Any to an Option of the given type. Will throw a ClassCastException - * if the actual type is not assignable from the given one. - */ - def as[T]: Option[T] = narrow[T](anyOption) - - /** Convenience helper to cast the given Option of Any to an Option of the given type. Will swallow a possible - * ClassCastException and return None in that case. - */ - def asSilently[T: Manifest]: Option[T] = narrowSilently[T](anyOption) -} - -/** Marker interface for proxyable actors (such as typed actor). - * - * @author Jonas Bonér - */ -trait Proxyable { - private[actor] def swapProxiedActor(newInstance: Actor) -} - -/** Represents the different Actor types. - * - * @author Jonas Bonér - */ -sealed trait ActorType -object ActorType { - case object ScalaActor extends ActorType - case object TypedActor extends ActorType -} diff --git a/test/files/presentation/akka/src/akka/actor/ActorRef.scala b/test/files/presentation/akka/src/akka/actor/ActorRef.scala deleted file mode 100644 index 07fa358744..0000000000 --- a/test/files/presentation/akka/src/akka/actor/ActorRef.scala +++ /dev/null @@ -1,1433 +0,0 @@ -/** - * Copyright (C) 2009-2011 Scalable Solutions AB - */ - -package akka.actor - -import akka.event.EventHandler -import akka.dispatch._ -import akka.config.Supervision._ -import akka.util._ -import ReflectiveAccess._ - -import java.net.InetSocketAddress -import java.util.concurrent.atomic.AtomicReference -import java.util.concurrent.{ ScheduledFuture, ConcurrentHashMap, TimeUnit } -import java.util.{ Map => JMap } - -import scala.beans.BeanProperty -import scala.collection.immutable.Stack -import scala.annotation.tailrec - -private[akka] object ActorRefInternals { - - /** - * LifeCycles for ActorRefs. - */ - private[akka] sealed trait StatusType - object UNSTARTED extends StatusType - object RUNNING extends StatusType - object BEING_RESTARTED extends StatusType - object SHUTDOWN extends StatusType -} - -/** - * Abstraction for unification of sender and senderFuture for later reply. - * Can be stored away and used at a later point in time. - */ -abstract class Channel[T] { - - /** - * Scala API.

      - * Sends the specified message to the channel. - */ - def !(msg: T): Unit - - /** - * Java API.

      - * Sends the specified message to the channel. - */ - def sendOneWay(msg: T): Unit = this.!(msg) -} - -/** - * ActorRef is an immutable and serializable handle to an Actor. - *

      - * Create an ActorRef for an Actor by using the factory method on the Actor object. - *

      - * Here is an example on how to create an actor with a default constructor. - *

      - *   import Actor._
      - *
      - *   val actor = actorOf[MyActor]
      - *   actor.start()
      - *   actor ! message
      - *   actor.stop()
      - * 
      - * - * You can also create and start actors like this: - *
      - *   val actor = actorOf[MyActor].start()
      - * 
      - * - * Here is an example on how to create an actor with a non-default constructor. - *
      - *   import Actor._
      - *
      - *   val actor = actorOf(new MyActor(...))
      - *   actor.start()
      - *   actor ! message
      - *   actor.stop()
      - * 
      - * - * @author Jonas Bonér - */ -trait ActorRef extends ActorRefShared with java.lang.Comparable[ActorRef] { scalaRef: ScalaActorRef => - // Only mutable for RemoteServer in order to maintain identity across nodes - @volatile - protected[akka] var _uuid = newUuid - @volatile - protected[this] var _status: ActorRefInternals.StatusType = ActorRefInternals.UNSTARTED - - /** - * User overridable callback/setting. - *

      - * Identifier for actor, does not have to be a unique one. Default is the 'uuid'. - *

      - * This field is used for logging, AspectRegistry.actorsFor(id), identifier for remote - * actor in RemoteServer etc.But also as the identifier for persistence, which means - * that you can use a custom name to be able to retrieve the "correct" persisted state - * upon restart, remote restart etc. - */ - @BeanProperty - @volatile - var id: String = _uuid.toString - - /** - * User overridable callback/setting. - *

      - * Defines the default timeout for '!!' and '!!!' invocations, - * e.g. the timeout for the future returned by the call to '!!' and '!!!'. - */ - @deprecated("Will be replaced by implicit-scoped timeout on all methods that needs it, will default to timeout specified in config", "1.1") - @BeanProperty - @volatile - var timeout: Long = Actor.TIMEOUT - - /** - * User overridable callback/setting. - *

      - * Defines the default timeout for an initial receive invocation. - * When specified, the receive function should be able to handle a 'ReceiveTimeout' message. - */ - @volatile - var receiveTimeout: Option[Long] = None - - /** - * Akka Java API.

      - * Defines the default timeout for an initial receive invocation. - * When specified, the receive function should be able to handle a 'ReceiveTimeout' message. - */ - def setReceiveTimeout(timeout: Long) = this.receiveTimeout = Some(timeout) - def getReceiveTimeout(): Option[Long] = receiveTimeout - - /** - * Akka Java API.

      - * A faultHandler defines what should be done when a linked actor signals an error. - *

      - * Can be one of: - *

      -   * getContext().setFaultHandler(new AllForOneStrategy(new Class[]{Throwable.class},maxNrOfRetries, withinTimeRange));
      -   * 
      - * Or: - *
      -   * getContext().setFaultHandler(new OneForOneStrategy(new Class[]{Throwable.class},maxNrOfRetries, withinTimeRange));
      -   * 
      - */ - def setFaultHandler(handler: FaultHandlingStrategy) - def getFaultHandler(): FaultHandlingStrategy - - /** - * Akka Java API.

      - * A lifeCycle defines whether the actor will be stopped on error (Temporary) or if it can be restarted (Permanent) - *

      - * Can be one of: - * - * import static akka.config.Supervision.*; - *

      -   * getContext().setLifeCycle(permanent());
      -   * 
      - * Or: - *
      -   * getContext().setLifeCycle(temporary());
      -   * 
      - */ - def setLifeCycle(lifeCycle: LifeCycle): Unit - def getLifeCycle(): LifeCycle - - /** - * Akka Java API.

      - * The default dispatcher is the Dispatchers.globalExecutorBasedEventDrivenDispatcher. - * This means that all actors will share the same event-driven executor based dispatcher. - *

      - * You can override it so it fits the specific use-case that the actor is used for. - * See the akka.dispatch.Dispatchers class for the different - * 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. - */ - def setDispatcher(dispatcher: MessageDispatcher) = this.dispatcher = dispatcher - def getDispatcher(): MessageDispatcher = dispatcher - - /** - * Returns on which node this actor lives if None it lives in the local ActorRegistry - */ - @deprecated("Remoting will become fully transparent in the future", "1.1") - def homeAddress: Option[InetSocketAddress] - - /** - * Java API.

      - */ - @deprecated("Remoting will become fully transparent in the future", "1.1") - def getHomeAddress(): InetSocketAddress = homeAddress getOrElse null - - /** - * Holds the hot swapped partial function. - */ - @volatile - protected[akka] var hotswap = Stack[PartialFunction[Any, Unit]]() - - /** - * This is a reference to the message currently being processed by the actor - */ - @volatile - protected[akka] var currentMessage: MessageInvocation = null - - /** - * Comparison only takes uuid into account. - */ - def compareTo(other: ActorRef) = this.uuid compareTo other.uuid - - /** - * Returns the uuid for the actor. - */ - def getUuid() = _uuid - def uuid = _uuid - - /** - * Akka Java API.

      - * The reference sender Actor of the last received message. - * Is defined if the message was sent from another Actor, else None. - */ - def getSender(): Option[ActorRef] = sender - - /** - * Akka Java API.

      - * The reference sender future of the last received message. - * Is defined if the message was sent with sent with '!!' or '!!!', else None. - */ - def getSenderFuture(): Option[CompletableFuture[Any]] = senderFuture - - /** - * Is the actor being restarted? - */ - def isBeingRestarted: Boolean = _status == ActorRefInternals.BEING_RESTARTED - - /** - * Is the actor running? - */ - def isRunning: Boolean = _status match { - case ActorRefInternals.BEING_RESTARTED | ActorRefInternals.RUNNING => true - case _ => false - } - - /** - * Is the actor shut down? - */ - def isShutdown: Boolean = _status == ActorRefInternals.SHUTDOWN - - /** - * Is the actor ever started? - */ - def isUnstarted: Boolean = _status == ActorRefInternals.UNSTARTED - - /** - * Is the actor able to handle the message passed in as arguments? - */ - @deprecated("Will be removed without replacement, it's just not reliable in the face of `become` and `unbecome`", "1.1") - def isDefinedAt(message: Any): Boolean = actor.isDefinedAt(message) - - /** - * Only for internal use. UUID is effectively final. - */ - protected[akka] def uuid_=(uid: Uuid) = _uuid = uid - - /** - * Akka Java API.

      - * Sends a one-way asynchronous message. E.g. fire-and-forget semantics. - *

      - *

      -   * actor.sendOneWay(message);
      -   * 
      - *

      - */ - def sendOneWay(message: AnyRef): Unit = sendOneWay(message, null) - - /** - * Akka Java API.

      - * Sends a one-way asynchronous message. E.g. fire-and-forget semantics. - *

      - * Allows you to pass along the sender of the message. - *

      - *

      -   * actor.sendOneWay(message, context);
      -   * 
      - *

      - */ - def sendOneWay(message: AnyRef, sender: ActorRef): Unit = this.!(message)(Option(sender)) - - /** - * Akka Java API.

      - * @see sendRequestReply(message: AnyRef, timeout: Long, sender: ActorRef) - * Uses the default timeout of the Actor (setTimeout()) and omits the sender reference - */ - def sendRequestReply(message: AnyRef): AnyRef = sendRequestReply(message, timeout, null) - - /** - * Akka Java API.

      - * @see sendRequestReply(message: AnyRef, timeout: Long, sender: ActorRef) - * Uses the default timeout of the Actor (setTimeout()) - */ - def sendRequestReply(message: AnyRef, sender: ActorRef): AnyRef = sendRequestReply(message, timeout, sender) - - /** - * Akka Java API.

      - * Sends a message asynchronously and waits on a future for a reply message under the hood. - *

      - * It waits on the reply either until it receives it or until the timeout expires - * (which will throw an ActorTimeoutException). E.g. send-and-receive-eventually semantics. - *

      - * NOTE: - * Use this method with care. In most cases it is better to use 'sendOneWay' together with 'getContext().getSender()' to - * implement request/response message exchanges. - *

      - * If you are sending messages using sendRequestReply then you have to use getContext().reply(..) - * to send a reply message to the original sender. If not then the sender will block until the timeout expires. - */ - def sendRequestReply(message: AnyRef, timeout: Long, sender: ActorRef): AnyRef = { - !!(message, timeout)(Option(sender)).getOrElse(throw new ActorTimeoutException( - "Message [" + message + - "]\n\tsent to [" + actorClassName + - "]\n\tfrom [" + (if (sender ne null) sender.actorClassName else "nowhere") + - "]\n\twith timeout [" + timeout + - "]\n\ttimed out.")) - .asInstanceOf[AnyRef] - } - - /** - * Akka Java API.

      - * @see sendRequestReplyFuture(message: AnyRef, sender: ActorRef): Future[_] - * Uses the Actors default timeout (setTimeout()) and omits the sender - */ - def sendRequestReplyFuture[T <: AnyRef](message: AnyRef): Future[T] = sendRequestReplyFuture(message, timeout, null).asInstanceOf[Future[T]] - - /** - * Akka Java API.

      - * @see sendRequestReplyFuture(message: AnyRef, sender: ActorRef): Future[_] - * Uses the Actors default timeout (setTimeout()) - */ - def sendRequestReplyFuture[T <: AnyRef](message: AnyRef, sender: ActorRef): Future[T] = sendRequestReplyFuture(message, timeout, sender).asInstanceOf[Future[T]] - - /** - * Akka Java API.

      - * Sends a message asynchronously returns a future holding the eventual reply message. - *

      - * NOTE: - * Use this method with care. In most cases it is better to use 'sendOneWay' together with the 'getContext().getSender()' to - * implement request/response message exchanges. - *

      - * If you are sending messages using sendRequestReplyFuture then you have to use getContext().reply(..) - * to send a reply message to the original sender. If not then the sender will block until the timeout expires. - */ - def sendRequestReplyFuture[T <: AnyRef](message: AnyRef, timeout: Long, sender: ActorRef): Future[T] = !!!(message, timeout)(Option(sender)).asInstanceOf[Future[T]] - - /** - * Akka Java API.

      - * Forwards the message specified to this actor and preserves the original sender of the message - */ - def forward(message: AnyRef, sender: ActorRef): Unit = - if (sender eq null) throw new IllegalArgumentException("The 'sender' argument to 'forward' can't be null") - else forward(message)(Some(sender)) - - /** - * Akka Java API.

      - * Use getContext().replyUnsafe(..) to reply with a message to the original sender of the message currently - * being processed. - *

      - * Throws an IllegalStateException if unable to determine what to reply to. - */ - def replyUnsafe(message: AnyRef) = reply(message) - - /** - * Akka Java API.

      - * Use getContext().replySafe(..) to reply with a message to the original sender of the message currently - * being processed. - *

      - * Returns true if reply was sent, and false if unable to determine what to reply to. - */ - def replySafe(message: AnyRef): Boolean = reply_?(message) - - /** - * Returns the class for the Actor instance that is managed by the ActorRef. - */ - @deprecated("Will be removed without replacement, doesn't make any sense to have in the face of `become` and `unbecome`", "1.1") - def actorClass: Class[_ <: Actor] - - /** - * Akka Java API.

      - * Returns the class for the Actor instance that is managed by the ActorRef. - */ - @deprecated("Will be removed without replacement, doesn't make any sense to have in the face of `become` and `unbecome`", "1.1") - def getActorClass(): Class[_ <: Actor] = actorClass - - /** - * Returns the class name for the Actor instance that is managed by the ActorRef. - */ - @deprecated("Will be removed without replacement, doesn't make any sense to have in the face of `become` and `unbecome`", "1.1") - def actorClassName: String - - /** - * Akka Java API.

      - * Returns the class name for the Actor instance that is managed by the ActorRef. - */ - @deprecated("Will be removed without replacement, doesn't make any sense to have in the face of `become` and `unbecome`", "1.1") - def getActorClassName(): String = actorClassName - - /** - * Sets the dispatcher for this actor. Needs to be invoked before the actor is started. - */ - def dispatcher_=(md: MessageDispatcher): Unit - - /** - * Get the dispatcher for this actor. - */ - def dispatcher: MessageDispatcher - - /** - * Starts up the actor and its message queue. - */ - def start(): ActorRef - - /** - * Shuts down the actor its dispatcher and message queue. - * Alias for 'stop'. - */ - def exit() = stop() - - /** - * Shuts down the actor its dispatcher and message queue. - */ - def stop(): Unit - - /** - * Links an other actor to this actor. Links are unidirectional and means that a the linking actor will - * receive a notification if the linked actor has crashed. - *

      - * If the 'trapExit' member field of the 'faultHandler' has been set to at contain at least one exception class then it will - * 'trap' these exceptions and automatically restart the linked actors according to the restart strategy - * defined by the 'faultHandler'. - */ - def link(actorRef: ActorRef): Unit - - /** - * Unlink the actor. - */ - def unlink(actorRef: ActorRef): Unit - - /** - * Atomically start and link an actor. - */ - def startLink(actorRef: ActorRef): Unit - - /** - * Atomically create (from actor class) and start an actor. - *

      - * To be invoked from within the actor itself. - */ - @deprecated("Will be removed after 1.1, use Actor.actorOf instead", "1.1") - def spawn(clazz: Class[_ <: Actor]): ActorRef - - /** - * Atomically create (from actor class), make it remote and start an actor. - *

      - * To be invoked from within the actor itself. - */ - @deprecated("Will be removed after 1.1, client managed actors will be removed", "1.1") - def spawnRemote(clazz: Class[_ <: Actor], hostname: String, port: Int, timeout: Long): ActorRef - - /** - * Atomically create (from actor class), link and start an actor. - *

      - * To be invoked from within the actor itself. - */ - @deprecated("Will be removed after 1.1, use use Actor.remote.actorOf instead and then link on success", "1.1") - def spawnLink(clazz: Class[_ <: Actor]): ActorRef - - /** - * Atomically create (from actor class), make it remote, link and start an actor. - *

      - * To be invoked from within the actor itself. - */ - @deprecated("Will be removed after 1.1, client managed actors will be removed", "1.1") - def spawnLinkRemote(clazz: Class[_ <: Actor], hostname: String, port: Int, timeout: Long): ActorRef - - /** - * Returns the mailbox size. - */ - def mailboxSize = dispatcher.mailboxSize(this) - - /** - * Akka Java API.

      - * Returns the mailbox size. - */ - def getMailboxSize(): Int = mailboxSize - - /** - * Returns the supervisor, if there is one. - */ - def supervisor: Option[ActorRef] - - /** - * Akka Java API.

      - * Returns the supervisor, if there is one. - */ - def getSupervisor(): ActorRef = supervisor getOrElse null - - /** - * Returns an unmodifiable Java Map containing the linked actors, - * please note that the backing map is thread-safe but not immutable - */ - def linkedActors: JMap[Uuid, ActorRef] - - /** - * Java API.

      - * Returns an unmodifiable Java Map containing the linked actors, - * please note that the backing map is thread-safe but not immutable - */ - def getLinkedActors(): JMap[Uuid, ActorRef] = linkedActors - - /** - * Abstraction for unification of sender and senderFuture for later reply - */ - def channel: Channel[Any] = { - if (senderFuture.isDefined) { - new Channel[Any] { - val future = senderFuture.get - def !(msg: Any) = future completeWithResult msg - } - } else if (sender.isDefined) { - val someSelf = Some(this) - new Channel[Any] { - val client = sender.get - def !(msg: Any) = client.!(msg)(someSelf) - } - } else throw new IllegalActorStateException("No channel available") - } - - /** - * Java API.

      - * Abstraction for unification of sender and senderFuture for later reply - */ - def getChannel: Channel[Any] = channel - - protected[akka] def invoke(messageHandle: MessageInvocation): Unit - - protected[akka] def postMessageToMailbox(message: Any, senderOption: Option[ActorRef]): Unit - - protected[akka] def postMessageToMailboxAndCreateFutureResultWithTimeout[T]( - message: Any, - timeout: Long, - senderOption: Option[ActorRef], - senderFuture: Option[CompletableFuture[T]]): CompletableFuture[T] - - protected[akka] def actorInstance: AtomicReference[Actor] - - protected[akka] def actor: Actor = actorInstance.get - - protected[akka] def supervisor_=(sup: Option[ActorRef]): Unit - - protected[akka] def mailbox: AnyRef - protected[akka] def mailbox_=(value: AnyRef): AnyRef - - protected[akka] def handleTrapExit(dead: ActorRef, reason: Throwable): Unit - - protected[akka] def restart(reason: Throwable, maxNrOfRetries: Option[Int], withinTimeRange: Option[Int]): Unit - - protected[akka] def restartLinkedActors(reason: Throwable, maxNrOfRetries: Option[Int], withinTimeRange: Option[Int]): Unit - - protected[akka] def registerSupervisorAsRemoteActor: Option[Uuid] - - override def hashCode: Int = HashCode.hash(HashCode.SEED, uuid) - - override def equals(that: Any): Boolean = { - that.isInstanceOf[ActorRef] && - that.asInstanceOf[ActorRef].uuid == uuid - } - - override def toString = "Actor[" + id + ":" + uuid + "]" -} - -/** - * Local (serializable) ActorRef that is used when referencing the Actor on its "home" node. - * - * @author Jonas Bonér - */ -class LocalActorRef private[akka] ( - private[this] val actorFactory: () => Actor, - val homeAddress: Option[InetSocketAddress], - val clientManaged: Boolean = false) - extends ActorRef with ScalaActorRef { - protected[akka] val guard = new ReentrantGuard - - @volatile - protected[akka] var _futureTimeout: Option[ScheduledFuture[AnyRef]] = None - @volatile - private[akka] lazy val _linkedActors = new ConcurrentHashMap[Uuid, ActorRef] - @volatile - private[akka] var _supervisor: Option[ActorRef] = None - @volatile - private var maxNrOfRetriesCount: Int = 0 - @volatile - private var restartsWithinTimeRangeTimestamp: Long = 0L - @volatile - private var _mailbox: AnyRef = _ - @volatile - private[akka] var _dispatcher: MessageDispatcher = Dispatchers.defaultGlobalDispatcher - - protected[akka] val actorInstance = guard.withGuard { new AtomicReference[Actor](newActor) } - - //If it was started inside "newActor", initialize it - if (isRunning) initializeActorInstance - - // used only for deserialization - private[akka] def this( - __uuid: Uuid, - __id: String, - __timeout: Long, - __receiveTimeout: Option[Long], - __lifeCycle: LifeCycle, - __supervisor: Option[ActorRef], - __hotswap: Stack[PartialFunction[Any, Unit]], - __factory: () => Actor, - __homeAddress: Option[InetSocketAddress]) = { - this(__factory, __homeAddress) - _uuid = __uuid - id = __id - timeout = __timeout - receiveTimeout = __receiveTimeout - lifeCycle = __lifeCycle - _supervisor = __supervisor - hotswap = __hotswap - setActorSelfFields(actor, this) - start - } - - /** - * Returns whether this actor ref is client-managed remote or not - */ - private[akka] final def isClientManaged_? = clientManaged && homeAddress.isDefined && isRemotingEnabled - - // ========= PUBLIC FUNCTIONS ========= - - /** - * Returns the class for the Actor instance that is managed by the ActorRef. - */ - @deprecated("Will be removed without replacement, doesn't make any sense to have in the face of `become` and `unbecome`", "1.1") - def actorClass: Class[_ <: Actor] = actor.getClass.asInstanceOf[Class[_ <: Actor]] - - /** - * Returns the class name for the Actor instance that is managed by the ActorRef. - */ - @deprecated("Will be removed without replacement, doesn't make any sense to have in the face of `become` and `unbecome`", "1.1") - def actorClassName: String = actorClass.getName - - /** - * Sets the dispatcher for this actor. Needs to be invoked before the actor is started. - */ - def dispatcher_=(md: MessageDispatcher): Unit = guard.withGuard { - if (!isBeingRestarted) { - if (!isRunning) _dispatcher = md - else throw new ActorInitializationException( - "Can not swap dispatcher for " + toString + " after it has been started") - } - } - - /** - * Get the dispatcher for this actor. - */ - def dispatcher: MessageDispatcher = _dispatcher - - /** - * Starts up the actor and its message queue. - */ - def start(): ActorRef = guard.withGuard { - if (isShutdown) throw new ActorStartException( - "Can't restart an actor that has been shut down with 'stop' or 'exit'") - if (!isRunning) { - dispatcher.attach(this) - - _status = ActorRefInternals.RUNNING - - // If we are not currently creating this ActorRef instance - if ((actorInstance ne null) && (actorInstance.get ne null)) - initializeActorInstance - - if (isClientManaged_?) - Actor.remote.registerClientManagedActor(homeAddress.get.getAddress.getHostAddress, homeAddress.get.getPort, uuid) - - checkReceiveTimeout //Schedule the initial Receive timeout - } - this - } - - /** - * Shuts down the actor its dispatcher and message queue. - */ - def stop() = guard.withGuard { - if (isRunning) { - receiveTimeout = None - cancelReceiveTimeout - dispatcher.detach(this) - _status = ActorRefInternals.SHUTDOWN - try { - actor.postStop - } finally { - currentMessage = null - Actor.registry.unregister(this) - if (isRemotingEnabled) { - if (isClientManaged_?) - Actor.remote.unregisterClientManagedActor(homeAddress.get.getAddress.getHostAddress, homeAddress.get.getPort, uuid) - Actor.remote.unregister(this) - } - setActorSelfFields(actorInstance.get, null) - } - } //else if (isBeingRestarted) throw new ActorKilledException("Actor [" + toString + "] is being restarted.") - } - - /** - * Links an other actor to this actor. Links are unidirectional and means that a the linking actor will - * receive a notification if the linked actor has crashed. - *

      - * If the 'trapExit' member field of the 'faultHandler' has been set to at contain at least one exception class then it will - * 'trap' these exceptions and automatically restart the linked actors according to the restart strategy - * defined by the 'faultHandler'. - *

      - * To be invoked from within the actor itself. - */ - def link(actorRef: ActorRef): Unit = guard.withGuard { - val actorRefSupervisor = actorRef.supervisor - val hasSupervisorAlready = actorRefSupervisor.isDefined - if (hasSupervisorAlready && actorRefSupervisor.get.uuid == uuid) return // we already supervise this guy - else if (hasSupervisorAlready) throw new IllegalActorStateException( - "Actor can only have one supervisor [" + actorRef + "], e.g. link(actor) fails") - else { - _linkedActors.put(actorRef.uuid, actorRef) - actorRef.supervisor = Some(this) - } - } - - /** - * Unlink the actor. - *

      - * To be invoked from within the actor itself. - */ - def unlink(actorRef: ActorRef) = guard.withGuard { - if (_linkedActors.remove(actorRef.uuid) eq null) - throw new IllegalActorStateException("Actor [" + actorRef + "] is not a linked actor, can't unlink") - - actorRef.supervisor = None - } - - /** - * Atomically start and link an actor. - *

      - * To be invoked from within the actor itself. - */ - def startLink(actorRef: ActorRef): Unit = guard.withGuard { - link(actorRef) - actorRef.start() - } - - /** - * Atomically create (from actor class) and start an actor. - *

      - * To be invoked from within the actor itself. - */ - def spawn(clazz: Class[_ <: Actor]): ActorRef = - Actor.actorOf(clazz).start() - - /** - * Atomically create (from actor class), start and make an actor remote. - *

      - * To be invoked from within the actor itself. - */ - def spawnRemote(clazz: Class[_ <: Actor], hostname: String, port: Int, timeout: Long = Actor.TIMEOUT): ActorRef = { - ensureRemotingEnabled - val ref = Actor.remote.actorOf(clazz, hostname, port) - ref.timeout = timeout - ref.start() - } - - /** - * Atomically create (from actor class), start and link an actor. - *

      - * To be invoked from within the actor itself. - */ - def spawnLink(clazz: Class[_ <: Actor]): ActorRef = { - val actor = spawn(clazz) - link(actor) - actor.start() - actor - } - - /** - * Atomically create (from actor class), start, link and make an actor remote. - *

      - * To be invoked from within the actor itself. - */ - def spawnLinkRemote(clazz: Class[_ <: Actor], hostname: String, port: Int, timeout: Long = Actor.TIMEOUT): ActorRef = { - ensureRemotingEnabled - val actor = Actor.remote.actorOf(clazz, hostname, port) - actor.timeout = timeout - link(actor) - actor.start() - actor - } - - /** - * Returns the mailbox. - */ - def mailbox: AnyRef = _mailbox - - protected[akka] def mailbox_=(value: AnyRef): AnyRef = { _mailbox = value; value } - - /** - * Returns the supervisor, if there is one. - */ - def supervisor: Option[ActorRef] = _supervisor - - // ========= AKKA PROTECTED FUNCTIONS ========= - - protected[akka] def supervisor_=(sup: Option[ActorRef]): Unit = _supervisor = sup - - protected[akka] def postMessageToMailbox(message: Any, senderOption: Option[ActorRef]): Unit = - if (isClientManaged_?) { - Actor.remote.send[Any]( - message, senderOption, None, homeAddress.get, timeout, true, this, None, ActorType.ScalaActor, None) - } else - dispatcher dispatchMessage new MessageInvocation(this, message, senderOption, None) - - protected[akka] def postMessageToMailboxAndCreateFutureResultWithTimeout[T]( - message: Any, - timeout: Long, - senderOption: Option[ActorRef], - senderFuture: Option[CompletableFuture[T]]): CompletableFuture[T] = { - if (isClientManaged_?) { - val future = Actor.remote.send[T]( - message, senderOption, senderFuture, homeAddress.get, timeout, false, this, None, ActorType.ScalaActor, None) - if (future.isDefined) future.get - else throw new IllegalActorStateException("Expected a future from remote call to actor " + toString) - } else { - val future = if (senderFuture.isDefined) senderFuture else Some(new DefaultCompletableFuture[T](timeout)) - dispatcher dispatchMessage new MessageInvocation( - this, message, senderOption, future.asInstanceOf[Some[CompletableFuture[Any]]]) - future.get - } - } - - /** - * Callback for the dispatcher. This is the single entry point to the user Actor implementation. - */ - protected[akka] def invoke(messageHandle: MessageInvocation): Unit = { - guard.lock.lock - try { - if (!isShutdown) { - currentMessage = messageHandle - try { - try { - cancelReceiveTimeout // FIXME: leave this here? - actor(messageHandle.message) - currentMessage = null // reset current message after successful invocation - } catch { - case e: InterruptedException => - currentMessage = null // received message while actor is shutting down, ignore - case e => - handleExceptionInDispatch(e, messageHandle.message) - } - finally { - checkReceiveTimeout // Reschedule receive timeout - } - } catch { - case e => - EventHandler.error(e, this, messageHandle.message.toString) - throw e - } - } - } finally { guard.lock.unlock } - } - - protected[akka] def handleTrapExit(dead: ActorRef, reason: Throwable) { - faultHandler match { - case AllForOneStrategy(trapExit, maxRetries, within) if trapExit.exists(_.isAssignableFrom(reason.getClass)) => - restartLinkedActors(reason, maxRetries, within) - - case OneForOneStrategy(trapExit, maxRetries, within) if trapExit.exists(_.isAssignableFrom(reason.getClass)) => - dead.restart(reason, maxRetries, within) - - case _ => - if (_supervisor.isDefined) notifySupervisorWithMessage(Exit(this, reason)) - else dead.stop() - } - } - - private def requestRestartPermission(maxNrOfRetries: Option[Int], withinTimeRange: Option[Int]): Boolean = { - val denied = if (maxNrOfRetries.isEmpty && withinTimeRange.isEmpty) { //Immortal - false - } else if (withinTimeRange.isEmpty) { // restrict number of restarts - maxNrOfRetriesCount += 1 //Increment number of retries - maxNrOfRetriesCount > maxNrOfRetries.get - } else { // cannot restart more than N within M timerange - maxNrOfRetriesCount += 1 //Increment number of retries - val windowStart = restartsWithinTimeRangeTimestamp - val now = System.currentTimeMillis - val retries = maxNrOfRetriesCount - //We are within the time window if it isn't the first restart, or if the window hasn't closed - val insideWindow = if (windowStart == 0) false - else (now - windowStart) <= withinTimeRange.get - - //The actor is dead if it dies X times within the window of restart - val unrestartable = insideWindow && retries > maxNrOfRetries.getOrElse(1) - - if (windowStart == 0 || !insideWindow) //(Re-)set the start of the window - restartsWithinTimeRangeTimestamp = now - - if (windowStart != 0 && !insideWindow) //Reset number of restarts if window has expired - maxNrOfRetriesCount = 1 - - unrestartable - } - - denied == false //If we weren't denied, we have a go - } - - protected[akka] def restart(reason: Throwable, maxNrOfRetries: Option[Int], withinTimeRange: Option[Int]) { - def performRestart() { - val failedActor = actorInstance.get - - failedActor match { - case p: Proxyable => - failedActor.preRestart(reason) - failedActor.postRestart(reason) - case _ => - failedActor.preRestart(reason) - val freshActor = newActor - setActorSelfFields(failedActor, null) // Only null out the references if we could instantiate the new actor - actorInstance.set(freshActor) // Assign it here so if preStart fails, we can null out the sef-refs next call - freshActor.preStart - freshActor.postRestart(reason) - } - } - - def tooManyRestarts() { - _supervisor.foreach { sup => - // can supervisor handle the notification? - val notification = MaximumNumberOfRestartsWithinTimeRangeReached(this, maxNrOfRetries, withinTimeRange, reason) - if (sup.isDefinedAt(notification)) notifySupervisorWithMessage(notification) - } - stop - } - - @tailrec - def attemptRestart() { - val success = if (requestRestartPermission(maxNrOfRetries, withinTimeRange)) { - guard.withGuard[Boolean] { - _status = ActorRefInternals.BEING_RESTARTED - - lifeCycle match { - case Temporary => - shutDownTemporaryActor(this) - true - - case _ => // either permanent or none where default is permanent - val success = try { - performRestart() - true - } catch { - case e => - EventHandler.error(e, this, "Exception in restart of Actor [%s]".format(toString)) - false // an error or exception here should trigger a retry - } - finally { - currentMessage = null - } - if (success) { - _status = ActorRefInternals.RUNNING - dispatcher.resume(this) - restartLinkedActors(reason, maxNrOfRetries, withinTimeRange) - } - success - } - } - } else { - tooManyRestarts() - true // done - } - - if (success) () // alles gut - else attemptRestart() - } - - attemptRestart() // recur - } - - protected[akka] def restartLinkedActors(reason: Throwable, maxNrOfRetries: Option[Int], withinTimeRange: Option[Int]) = { - val i = _linkedActors.values.iterator - while (i.hasNext) { - val actorRef = i.next - actorRef.lifeCycle match { - // either permanent or none where default is permanent - case Temporary => shutDownTemporaryActor(actorRef) - case _ => actorRef.restart(reason, maxNrOfRetries, withinTimeRange) - } - } - } - - protected[akka] def registerSupervisorAsRemoteActor: Option[Uuid] = guard.withGuard { - ensureRemotingEnabled - if (_supervisor.isDefined) { - if (homeAddress.isDefined) Actor.remote.registerSupervisorForActor(this) - Some(_supervisor.get.uuid) - } else None - } - - def linkedActors: JMap[Uuid, ActorRef] = java.util.Collections.unmodifiableMap(_linkedActors) - - // ========= PRIVATE FUNCTIONS ========= - - private[this] def newActor: Actor = { - try { - Actor.actorRefInCreation.set(Some(this)) - val a = actorFactory() - if (a eq null) throw new ActorInitializationException("Actor instance passed to ActorRef can not be 'null'") - a - } finally { - Actor.actorRefInCreation.set(None) - } - } - - private def shutDownTemporaryActor(temporaryActor: ActorRef) { - temporaryActor.stop() - _linkedActors.remove(temporaryActor.uuid) // remove the temporary actor - // if last temporary actor is gone, then unlink me from supervisor - if (_linkedActors.isEmpty) notifySupervisorWithMessage(UnlinkAndStop(this)) - true - } - - private def handleExceptionInDispatch(reason: Throwable, message: Any) = { - EventHandler.error(reason, this, message.toString) - - //Prevent any further messages to be processed until the actor has been restarted - dispatcher.suspend(this) - - senderFuture.foreach(_.completeWithException(reason)) - - if (supervisor.isDefined) notifySupervisorWithMessage(Exit(this, reason)) - else { - lifeCycle match { - case Temporary => shutDownTemporaryActor(this) - case _ => dispatcher.resume(this) //Resume processing for this actor - } - } - } - - private def notifySupervisorWithMessage(notification: LifeCycleMessage) = { - // FIXME to fix supervisor restart of remote actor for oneway calls, inject a supervisor proxy that can send notification back to client - _supervisor.foreach { sup => - if (sup.isShutdown) { // if supervisor is shut down, game over for all linked actors - //Scoped stop all linked actors, to avoid leaking the 'i' val - { - val i = _linkedActors.values.iterator - while (i.hasNext) { - i.next.stop() - i.remove - } - } - //Stop the actor itself - stop - } else sup ! notification // else notify supervisor - } - } - - private def setActorSelfFields(actor: Actor, value: ActorRef) { - - @tailrec - def lookupAndSetSelfFields(clazz: Class[_], actor: Actor, value: ActorRef): Boolean = { - val success = try { - val selfField = clazz.getDeclaredField("self") - val someSelfField = clazz.getDeclaredField("someSelf") - selfField.setAccessible(true) - someSelfField.setAccessible(true) - selfField.set(actor, value) - someSelfField.set(actor, if (value ne null) Some(value) else null) - true - } catch { - case e: NoSuchFieldException => false - } - - if (success) true - else { - val parent = clazz.getSuperclass - if (parent eq null) - throw new IllegalActorStateException(toString + " is not an Actor since it have not mixed in the 'Actor' trait") - lookupAndSetSelfFields(parent, actor, value) - } - } - - lookupAndSetSelfFields(actor.getClass, actor, value) - } - - private def initializeActorInstance = { - actor.preStart // run actor preStart - Actor.registry.register(this) - } - - protected[akka] def checkReceiveTimeout = { - cancelReceiveTimeout - if (receiveTimeout.isDefined && dispatcher.mailboxSize(this) <= 0) { //Only reschedule if desired and there are currently no more messages to be processed - _futureTimeout = Some(Scheduler.scheduleOnce(this, ReceiveTimeout, receiveTimeout.get, TimeUnit.MILLISECONDS)) - } - } - - protected[akka] def cancelReceiveTimeout = { - if (_futureTimeout.isDefined) { - _futureTimeout.get.cancel(true) - _futureTimeout = None - } - } -} - -/** - * System messages for RemoteActorRef. - * - * @author Jonas Bonér - */ -object RemoteActorSystemMessage { - val Stop = "RemoteActorRef:stop".intern -} - -/** - * Remote ActorRef that is used when referencing the Actor on a different node than its "home" node. - * This reference is network-aware (remembers its origin) and immutable. - * - * @author Jonas Bonér - */ -private[akka] case class RemoteActorRef private[akka] ( - classOrServiceName: String, - val actorClassName: String, - val hostname: String, - val port: Int, - _timeout: Long, - loader: Option[ClassLoader], - val actorType: ActorType = ActorType.ScalaActor) - extends ActorRef with ScalaActorRef { - - ensureRemotingEnabled - - val homeAddress = Some(new InetSocketAddress(hostname, port)) - - //protected def clientManaged = classOrServiceName.isEmpty //If no class or service name, it's client managed - id = classOrServiceName - //id = classOrServiceName.getOrElse("uuid:" + uuid) //If we're a server-managed we want to have classOrServiceName as id, or else, we're a client-managed and we want to have our uuid as id - - timeout = _timeout - - start - - def postMessageToMailbox(message: Any, senderOption: Option[ActorRef]): Unit = - Actor.remote.send[Any](message, senderOption, None, homeAddress.get, timeout, true, this, None, actorType, loader) - - def postMessageToMailboxAndCreateFutureResultWithTimeout[T]( - message: Any, - timeout: Long, - senderOption: Option[ActorRef], - senderFuture: Option[CompletableFuture[T]]): CompletableFuture[T] = { - val future = Actor.remote.send[T]( - message, senderOption, senderFuture, - homeAddress.get, timeout, - false, this, None, - actorType, loader) - if (future.isDefined) future.get - else throw new IllegalActorStateException("Expected a future from remote call to actor " + toString) - } - - def start: ActorRef = synchronized { - _status = ActorRefInternals.RUNNING - this - } - - def stop: Unit = synchronized { - if (_status == ActorRefInternals.RUNNING) { - _status = ActorRefInternals.SHUTDOWN - postMessageToMailbox(RemoteActorSystemMessage.Stop, None) - } - } - - protected[akka] def registerSupervisorAsRemoteActor: Option[Uuid] = None - - // ==== NOT SUPPORTED ==== - @deprecated("Will be removed without replacement, doesn't make any sense to have in the face of `become` and `unbecome`", "1.1") - def actorClass: Class[_ <: Actor] = unsupported - def dispatcher_=(md: MessageDispatcher): Unit = unsupported - def dispatcher: MessageDispatcher = unsupported - def link(actorRef: ActorRef): Unit = unsupported - def unlink(actorRef: ActorRef): Unit = unsupported - def startLink(actorRef: ActorRef): Unit = unsupported - def spawn(clazz: Class[_ <: Actor]): ActorRef = unsupported - def spawnRemote(clazz: Class[_ <: Actor], hostname: String, port: Int, timeout: Long): ActorRef = unsupported - def spawnLink(clazz: Class[_ <: Actor]): ActorRef = unsupported - def spawnLinkRemote(clazz: Class[_ <: Actor], hostname: String, port: Int, timeout: Long): ActorRef = unsupported - def supervisor: Option[ActorRef] = unsupported - def linkedActors: JMap[Uuid, ActorRef] = unsupported - protected[akka] def mailbox: AnyRef = unsupported - protected[akka] def mailbox_=(value: AnyRef): AnyRef = unsupported - protected[akka] def handleTrapExit(dead: ActorRef, reason: Throwable): Unit = unsupported - protected[akka] def restart(reason: Throwable, maxNrOfRetries: Option[Int], withinTimeRange: Option[Int]): Unit = unsupported - protected[akka] def restartLinkedActors(reason: Throwable, maxNrOfRetries: Option[Int], withinTimeRange: Option[Int]): Unit = unsupported - protected[akka] def invoke(messageHandle: MessageInvocation): Unit = unsupported - protected[akka] def supervisor_=(sup: Option[ActorRef]): Unit = unsupported - protected[akka] def actorInstance: AtomicReference[Actor] = unsupported - private def unsupported = throw new UnsupportedOperationException("Not supported for RemoteActorRef") -} - -/** - * This trait represents the common (external) methods for all ActorRefs - * Needed because implicit conversions aren't applied when instance imports are used - * - * i.e. - * var self: ScalaActorRef = ... - * import self._ - * //can't call ActorRef methods here unless they are declared in a common - * //superclass, which ActorRefShared is. - */ -trait ActorRefShared { - /** - * Returns the uuid for the actor. - */ - def uuid: Uuid -} - -/** - * This trait represents the Scala Actor API - * There are implicit conversions in ../actor/Implicits.scala - * from ActorRef -> ScalaActorRef and back - */ -trait ScalaActorRef extends ActorRefShared { ref: ActorRef => - - /** - * Identifier for actor, does not have to be a unique one. Default is the 'uuid'. - *

      - * This field is used for logging, AspectRegistry.actorsFor(id), identifier for remote - * actor in RemoteServer etc.But also as the identifier for persistence, which means - * that you can use a custom name to be able to retrieve the "correct" persisted state - * upon restart, remote restart etc. - */ - def id: String - - def id_=(id: String): Unit - - /** - * User overridable callback/setting. - *

      - * Defines the life-cycle for a supervised actor. - */ - @volatile - @BeanProperty - var lifeCycle: LifeCycle = UndefinedLifeCycle - - /** - * User overridable callback/setting. - *

      - * Don't forget to supply a List of exception types to intercept (trapExit) - *

      - * Can be one of: - *

      -   *  faultHandler = AllForOneStrategy(trapExit = List(classOf[Exception]), maxNrOfRetries, withinTimeRange)
      -   * 
      - * Or: - *
      -   *  faultHandler = OneForOneStrategy(trapExit = List(classOf[Exception]), maxNrOfRetries, withinTimeRange)
      -   * 
      - */ - @volatile - @BeanProperty - var faultHandler: FaultHandlingStrategy = NoFaultHandlingStrategy - - /** - * The reference sender Actor of the last received message. - * Is defined if the message was sent from another Actor, else None. - */ - def sender: Option[ActorRef] = { - val msg = currentMessage - if (msg eq null) None - else msg.sender - } - - /** - * The reference sender future of the last received message. - * Is defined if the message was sent with sent with '!!' or '!!!', else None. - */ - def senderFuture(): Option[CompletableFuture[Any]] = { - val msg = currentMessage - if (msg eq null) None - else msg.senderFuture - } - - /** - * Sends a one-way asynchronous message. E.g. fire-and-forget semantics. - *

      - * - * 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, - * if invoked from within an Actor. If not then no sender is available. - *

      -   *   actor ! message
      -   * 
      - *

      - */ - def !(message: Any)(implicit sender: Option[ActorRef] = None): Unit = { - if (isRunning) postMessageToMailbox(message, sender) - else throw new ActorInitializationException( - "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. - *

      - * It waits on the reply either until it receives it (in the form of Some(replyMessage)) - * or until the timeout expires (which will return None). E.g. send-and-receive-eventually semantics. - *

      - * NOTE: - * Use this method with care. In most cases it is better to use '!' together with the 'sender' member field to - * implement request/response message exchanges. - * If you are sending messages using !! then you have to use self.reply(..) - * to send a reply message to the original sender. If not then the sender will block until the timeout expires. - */ - def !!(message: Any, timeout: Long = this.timeout)(implicit sender: Option[ActorRef] = None): Option[Any] = { - if (isRunning) { - val future = postMessageToMailboxAndCreateFutureResultWithTimeout[Any](message, timeout, sender, None) - val isMessageJoinPoint = if (isTypedActorEnabled) TypedActorModule.resolveFutureIfMessageIsJoinPoint(message, future) - else false - try { - future.await - } catch { - case e: FutureTimeoutException => - if (isMessageJoinPoint) { - EventHandler.error(e, this, e.getMessage) - throw e - } else None - } - future.resultOrException - } else throw new ActorInitializationException( - "Actor has not been started, you need to invoke 'actor.start()' before using it") - } - - /** - * Sends a message asynchronously returns a future holding the eventual reply message. - *

      - * NOTE: - * Use this method with care. In most cases it is better to use '!' together with the 'sender' member field to - * implement request/response message exchanges. - * If you are sending messages using !!! then you have to use self.reply(..) - * to send a reply message to the original sender. If not then the sender will block until the timeout expires. - */ - def !!![T](message: Any, timeout: Long = this.timeout)(implicit sender: Option[ActorRef] = None): Future[T] = { - if (isRunning) postMessageToMailboxAndCreateFutureResultWithTimeout[T](message, timeout, sender, None) - else throw new ActorInitializationException( - "Actor has not been started, you need to invoke 'actor.start()' before using it") - } - - /** - * Forwards the message and passes the original sender actor as the sender. - *

      - * Works with '!', '!!' and '!!!'. - */ - def forward(message: Any)(implicit sender: Some[ActorRef]) = { - if (isRunning) { - if (sender.get.senderFuture.isDefined) - postMessageToMailboxAndCreateFutureResultWithTimeout(message, timeout, sender.get.sender, sender.get.senderFuture) - else - postMessageToMailbox(message, sender.get.sender) - } else throw new ActorInitializationException("Actor has not been started, you need to invoke 'actor.start()' before using it") - } - - /** - * Use self.reply(..) to reply with a message to the original sender of the message currently - * being processed. - *

      - * Throws an IllegalStateException if unable to determine what to reply to. - */ - def reply(message: Any) = if (!reply_?(message)) throw new IllegalActorStateException( - "\n\tNo sender in scope, can't reply. " + - "\n\tYou have probably: " + - "\n\t\t1. Sent a message to an Actor from an instance that is NOT an Actor." + - "\n\t\t2. Invoked a method on an TypedActor from an instance NOT an TypedActor." + - "\n\tElse you might want to use 'reply_?' which returns Boolean(true) if succes and Boolean(false) if no sender in scope") - - /** - * Use reply_?(..) to reply with a message to the original sender of the message currently - * being processed. - *

      - * Returns true if reply was sent, and false if unable to determine what to reply to. - */ - def reply_?(message: Any): Boolean = { - if (senderFuture.isDefined) { - senderFuture.get completeWithResult message - true - } else if (sender.isDefined) { - //TODO: optimize away this allocation, perhaps by having implicit self: Option[ActorRef] in signature - sender.get.!(message)(Some(this)) - true - } else false - } - - /** - * Atomically create (from actor class) and start an actor. - */ - def spawn[T <: Actor: Manifest]: ActorRef = - spawn(manifest[T].erasure.asInstanceOf[Class[_ <: Actor]]) - - /** - * Atomically create (from actor class), start and make an actor remote. - */ - def spawnRemote[T <: Actor: Manifest](hostname: String, port: Int, timeout: Long): ActorRef = { - ensureRemotingEnabled - spawnRemote(manifest[T].erasure.asInstanceOf[Class[_ <: Actor]], hostname, port, timeout) - } - - /** - * Atomically create (from actor class), start and link an actor. - */ - def spawnLink[T <: Actor: Manifest]: ActorRef = - spawnLink(manifest[T].erasure.asInstanceOf[Class[_ <: Actor]]) - - /** - * Atomically create (from actor class), start, link and make an actor remote. - */ - def spawnLinkRemote[T <: Actor: Manifest](hostname: String, port: Int, timeout: Long): ActorRef = { - ensureRemotingEnabled - spawnLinkRemote(manifest[T].erasure.asInstanceOf[Class[_ <: Actor]], hostname, port, timeout) - } -} diff --git a/test/files/presentation/akka/src/akka/actor/ActorRegistry.scala b/test/files/presentation/akka/src/akka/actor/ActorRegistry.scala deleted file mode 100644 index df335dc8b4..0000000000 --- a/test/files/presentation/akka/src/akka/actor/ActorRegistry.scala +++ /dev/null @@ -1,389 +0,0 @@ -/** - * Copyright (C) 2009-2011 Scalable Solutions AB - */ - -package akka.actor - -import scala.collection.mutable.{ ListBuffer, Map } -import scala.reflect.Manifest - -import java.util.concurrent.{ ConcurrentSkipListSet, ConcurrentHashMap } -import java.util.{ Set => JSet } - -import annotation.tailrec -import akka.util.ReflectiveAccess._ -import akka.util.{ ReflectiveAccess, ReadWriteGuard, ListenerManagement } - -/** - * Base trait for ActorRegistry events, allows listen to when an actor is added and removed from the ActorRegistry. - * - * @author Jonas Bonér - */ -sealed trait ActorRegistryEvent -case class ActorRegistered(actor: ActorRef) extends ActorRegistryEvent -case class ActorUnregistered(actor: ActorRef) extends ActorRegistryEvent - -/** - * Registry holding all Actor instances in the whole system. - * Mapped by: - *

        - *
      • the Actor's UUID
      • - *
      • the Actor's id field (which can be set by user-code)
      • - *
      • the Actor's class
      • - *
      • all Actors that are subtypes of a specific type
      • - *
          - * - * @author Jonas Bonér - */ - -final class ActorRegistry private[actor] () extends ListenerManagement { - - private val actorsByUUID = new ConcurrentHashMap[Uuid, ActorRef] - private val actorsById = new Index[String, ActorRef] - private val guard = new ReadWriteGuard - - /** - * Returns all actors in the system. - */ - def actors: Array[ActorRef] = filter(_ => true) - - /** - * Returns the number of actors in the system. - */ - def size: Int = actorsByUUID.size - - /** - * Invokes a function for all actors. - */ - def foreach(f: (ActorRef) => Unit) = { - val elements = actorsByUUID.elements - while (elements.hasMoreElements) f(elements.nextElement) - } - - /** - * Invokes the function on all known actors until it returns Some - * Returns None if the function never returns Some - */ - def find[T](f: PartialFunction[ActorRef, T]): Option[T] = { - val elements = actorsByUUID.elements - while (elements.hasMoreElements) { - val element = elements.nextElement - if (f isDefinedAt element) return Some(f(element)) - } - None - } - - /** - * Finds all actors that are subtypes of the class passed in as the Manifest argument and supporting passed message. - */ - def actorsFor[T <: Actor](message: Any)(implicit manifest: Manifest[T]): Array[ActorRef] = - filter(a => manifest.erasure.isAssignableFrom(a.actor.getClass) && a.isDefinedAt(message)) - - /** - * Finds all actors that satisfy a predicate. - */ - def filter(p: ActorRef => Boolean): Array[ActorRef] = { - val all = new ListBuffer[ActorRef] - val elements = actorsByUUID.elements - while (elements.hasMoreElements) { - val actorId = elements.nextElement - if (p(actorId)) all += actorId - } - all.toArray - } - - /** - * Finds all actors that are subtypes of the class passed in as the Manifest argument. - */ - def actorsFor[T <: Actor](implicit manifest: Manifest[T]): Array[ActorRef] = - actorsFor[T](manifest.erasure.asInstanceOf[Class[T]]) - - /** - * Finds any actor that matches T. Very expensive, traverses ALL alive actors. - */ - def actorFor[T <: Actor](implicit manifest: Manifest[T]): Option[ActorRef] = - find({ case a: ActorRef if manifest.erasure.isAssignableFrom(a.actor.getClass) => a }) - - /** - * Finds all actors of type or sub-type specified by the class passed in as the Class argument. - */ - def actorsFor[T <: Actor](clazz: Class[T]): Array[ActorRef] = - filter(a => clazz.isAssignableFrom(a.actor.getClass)) - - /** - * Finds all actors that has a specific id. - */ - def actorsFor(id: String): Array[ActorRef] = actorsById values id - - /** - * Finds the actor that has a specific UUID. - */ - def actorFor(uuid: Uuid): Option[ActorRef] = Option(actorsByUUID get uuid) - - /** - * Returns all typed actors in the system. - */ - def typedActors: Array[AnyRef] = filterTypedActors(_ => true) - - /** - * Invokes a function for all typed actors. - */ - def foreachTypedActor(f: (AnyRef) => Unit) = { - TypedActorModule.ensureEnabled - val elements = actorsByUUID.elements - while (elements.hasMoreElements) { - val proxy = typedActorFor(elements.nextElement) - if (proxy.isDefined) f(proxy.get) - } - } - - /** - * Invokes the function on all known typed actors until it returns Some - * Returns None if the function never returns Some - */ - def findTypedActor[T](f: PartialFunction[AnyRef, T]): Option[T] = { - TypedActorModule.ensureEnabled - val elements = actorsByUUID.elements - while (elements.hasMoreElements) { - val proxy = typedActorFor(elements.nextElement) - if (proxy.isDefined && (f isDefinedAt proxy)) return Some(f(proxy)) - } - None - } - - /** - * Finds all typed actors that satisfy a predicate. - */ - def filterTypedActors(p: AnyRef => Boolean): Array[AnyRef] = { - TypedActorModule.ensureEnabled - val all = new ListBuffer[AnyRef] - val elements = actorsByUUID.elements - while (elements.hasMoreElements) { - val proxy = typedActorFor(elements.nextElement) - if (proxy.isDefined && p(proxy.get)) all += proxy.get - } - all.toArray - } - - /** - * Finds all typed actors that are subtypes of the class passed in as the Manifest argument. - */ - def typedActorsFor[T <: AnyRef](implicit manifest: Manifest[T]): Array[AnyRef] = { - TypedActorModule.ensureEnabled - typedActorsFor[T](manifest.erasure.asInstanceOf[Class[T]]) - } - - /** - * Finds any typed actor that matches T. - */ - def typedActorFor[T <: AnyRef](implicit manifest: Manifest[T]): Option[AnyRef] = { - TypedActorModule.ensureEnabled - def predicate(proxy: AnyRef): Boolean = { - val actorRef = TypedActorModule.typedActorObjectInstance.get.actorFor(proxy) - actorRef.isDefined && manifest.erasure.isAssignableFrom(actorRef.get.actor.getClass) - } - findTypedActor({ case a: Some[AnyRef] if predicate(a.get) => a }) - } - - /** - * Finds all typed actors of type or sub-type specified by the class passed in as the Class argument. - */ - def typedActorsFor[T <: AnyRef](clazz: Class[T]): Array[AnyRef] = { - TypedActorModule.ensureEnabled - def predicate(proxy: AnyRef): Boolean = { - val actorRef = TypedActorModule.typedActorObjectInstance.get.actorFor(proxy) - actorRef.isDefined && clazz.isAssignableFrom(actorRef.get.actor.getClass) - } - filterTypedActors(predicate) - } - - /** - * Finds all typed actors that have a specific id. - */ - def typedActorsFor(id: String): Array[AnyRef] = { - TypedActorModule.ensureEnabled - val actorRefs = actorsById values id - actorRefs.flatMap(typedActorFor(_)) - } - - /** - * Finds the typed actor that has a specific UUID. - */ - def typedActorFor(uuid: Uuid): Option[AnyRef] = { - TypedActorModule.ensureEnabled - val actorRef = actorsByUUID get uuid - if (actorRef eq null) None - else typedActorFor(actorRef) - } - - /** - * Get the typed actor proxy for a given typed actor ref. - */ - private def typedActorFor(actorRef: ActorRef): Option[AnyRef] = { - TypedActorModule.typedActorObjectInstance.get.proxyFor(actorRef) - } - - /** - * Registers an actor in the ActorRegistry. - */ - private[akka] def register(actor: ActorRef) { - val id = actor.id - val uuid = actor.uuid - - actorsById.put(id, actor) - actorsByUUID.put(uuid, actor) - - // notify listeners - notifyListeners(ActorRegistered(actor)) - } - - /** - * Unregisters an actor in the ActorRegistry. - */ - private[akka] def unregister(actor: ActorRef) { - val id = actor.id - val uuid = actor.uuid - - actorsByUUID remove uuid - actorsById.remove(id, actor) - - // notify listeners - notifyListeners(ActorUnregistered(actor)) - } - - /** - * Shuts down and unregisters all actors in the system. - */ - def shutdownAll() { - if (TypedActorModule.isEnabled) { - val elements = actorsByUUID.elements - while (elements.hasMoreElements) { - val actorRef = elements.nextElement - val proxy = typedActorFor(actorRef) - if (proxy.isDefined) TypedActorModule.typedActorObjectInstance.get.stop(proxy.get) - else actorRef.stop() - } - } else foreach(_.stop()) - if (Remote.isEnabled) { - Actor.remote.clear //TODO: REVISIT: Should this be here? - } - actorsByUUID.clear - actorsById.clear - } -} - -/** - * An implementation of a ConcurrentMultiMap - * Adds/remove is serialized over the specified key - * Reads are fully concurrent <-- el-cheapo - * - * @author Viktor Klang - */ -class Index[K <: AnyRef, V <: AnyRef: Manifest] { - private val Naught = Array[V]() //Nil for Arrays - private val container = new ConcurrentHashMap[K, JSet[V]] - private val emptySet = new ConcurrentSkipListSet[V] - - /** - * Associates the value of type V with the key of type K - * @return true if the value didn't exist for the key previously, and false otherwise - */ - def put(key: K, value: V): Boolean = { - //Tailrecursive spin-locking put - @tailrec - def spinPut(k: K, v: V): Boolean = { - var retry = false - var added = false - val set = container get k - - if (set ne null) { - set.synchronized { - if (set.isEmpty) retry = true //IF the set is empty then it has been removed, so signal retry - else { //Else add the value to the set and signal that retry is not needed - added = set add v - retry = false - } - } - } else { - val newSet = new ConcurrentSkipListSet[V] - newSet add v - - // Parry for two simultaneous putIfAbsent(id,newSet) - val oldSet = container.putIfAbsent(k, newSet) - if (oldSet ne null) { - oldSet.synchronized { - if (oldSet.isEmpty) retry = true //IF the set is empty then it has been removed, so signal retry - else { //Else try to add the value to the set and signal that retry is not needed - added = oldSet add v - retry = false - } - } - } else added = true - } - - if (retry) spinPut(k, v) - else added - } - - spinPut(key, value) - } - - /** - * @return a _new_ array of all existing values for the given key at the time of the call - */ - def values(key: K): Array[V] = { - val set: JSet[V] = container get key - val result = if (set ne null) set toArray Naught else Naught - result.asInstanceOf[Array[V]] - } - - /** - * @return Some(value) for the first matching value where the supplied function returns true for the given key, - * if no matches it returns None - */ - def findValue(key: K)(f: (V) => Boolean): Option[V] = { - import scala.collection.JavaConversions._ - val set = container get key - if (set ne null) set.iterator.find(f) - else None - } - - /** - * Applies the supplied function to all keys and their values - */ - def foreach(fun: (K, V) => Unit) { - import scala.collection.JavaConversions._ - container.entrySet foreach { (e) => - e.getValue.foreach(fun(e.getKey, _)) - } - } - - /** - * Disassociates the value of type V from the key of type K - * @return true if the value was disassociated from the key and false if it wasn't previously associated with the key - */ - def remove(key: K, value: V): Boolean = { - val set = container get key - - if (set ne null) { - set.synchronized { - if (set.remove(value)) { //If we can remove the value - if (set.isEmpty) //and the set becomes empty - container.remove(key, emptySet) //We try to remove the key if it's mapped to an empty set - - true //Remove succeeded - } else false //Remove failed - } - } else false //Remove failed - } - - /** - * @return true if the underlying containers is empty, may report false negatives when the last remove is underway - */ - def isEmpty: Boolean = container.isEmpty - - /** - * Removes all keys and all values - */ - def clear = foreach { case (k, v) => remove(k, v) } -} diff --git a/test/files/presentation/akka/src/akka/actor/Actors.java b/test/files/presentation/akka/src/akka/actor/Actors.java deleted file mode 100644 index a5ec9f37dc..0000000000 --- a/test/files/presentation/akka/src/akka/actor/Actors.java +++ /dev/null @@ -1,108 +0,0 @@ -package akka.actor; - -import akka.japi.Creator; -import akka.remoteinterface.RemoteSupport; - -/** - * JAVA API for - * - creating actors, - * - creating remote actors, - * - locating actors - */ -public class Actors { - /** - * - * @return The actor registry - */ - public static ActorRegistry registry() { - return Actor$.MODULE$.registry(); - } - - /** - * - * @return - * @throws UnsupportedOperationException If remoting isn't configured - * @throws ModuleNotAvailableException If the class for the remote support cannot be loaded - */ - public static RemoteSupport remote() { - return Actor$.MODULE$.remote(); - } - - /** - * NOTE: Use this convenience method with care, do NOT make it possible to get a reference to the - * UntypedActor instance directly, but only through its 'ActorRef' wrapper reference. - *

          - * Creates an ActorRef out of the Actor. Allows you to pass in the instance for the UntypedActor. - * Only use this method when you need to pass in constructor arguments into the 'UntypedActor'. - *

          - * You use it by implementing the UntypedActorFactory interface. - * Example in Java: - *

          -   *   ActorRef actor = Actors.actorOf(new UntypedActorFactory() {
          -   *     public UntypedActor create() {
          -   *       return new MyUntypedActor("service:name", 5);
          -   *     }
          -   *   });
          -   *   actor.start();
          -   *   actor.sendOneWay(message, context);
          -   *   actor.stop();
          -   * 
          - */ - public static ActorRef actorOf(final Creator factory) { - return Actor$.MODULE$.actorOf(factory); - } - - /** - * Creates an ActorRef out of the Actor type represented by the class provided. - * Example in Java: - *
          -   *   ActorRef actor = Actors.actorOf(MyUntypedActor.class);
          -   *   actor.start();
          -   *   actor.sendOneWay(message, context);
          -   *   actor.stop();
          -   * 
          - * You can create and start the actor in one statement like this: - *
          -   *   val actor = Actors.actorOf(MyActor.class).start();
          -   * 
          - */ - public static ActorRef actorOf(final Class type) { - return Actor$.MODULE$.actorOf(type); - } - - /** - * The message that is sent when an Actor gets a receive timeout. - *
          -     *  if( message == receiveTimeout() ) {
          -     *    //Timed out
          -     *  }
          -     * 
          - * @return the single instance of ReceiveTimeout - */ - public final static ReceiveTimeout$ receiveTimeout() { - return ReceiveTimeout$.MODULE$; - } - - /** - * The message that when sent to an Actor kills it by throwing an exception. - *
          -     *  actor.sendOneWay(kill());
          -     * 
          - * @return the single instance of Kill - */ - public final static Kill$ kill() { - return Kill$.MODULE$; - } - - - /** - * The message that when sent to an Actor shuts it down by calling 'stop'. - *
          -     *  actor.sendOneWay(poisonPill());
          -     * 
          - * @return the single instance of PoisonPill - */ - public final static PoisonPill$ poisonPill() { - return PoisonPill$.MODULE$; - } -} diff --git a/test/files/presentation/akka/src/akka/actor/BootableActorLoaderService.scala b/test/files/presentation/akka/src/akka/actor/BootableActorLoaderService.scala deleted file mode 100644 index a54fca9ac7..0000000000 --- a/test/files/presentation/akka/src/akka/actor/BootableActorLoaderService.scala +++ /dev/null @@ -1,60 +0,0 @@ -/** - * Copyright (C) 2009-2011 Scalable Solutions AB - */ - -package akka.actor - -import java.io.File -import java.net.{ URL, URLClassLoader } -import java.util.jar.JarFile - -import akka.util.{ Bootable } -import akka.config.Config._ - -/** - * Handles all modules in the deploy directory (load and unload) - */ -trait BootableActorLoaderService extends Bootable { - - val BOOT_CLASSES = config.getList("akka.boot") - lazy val applicationLoader: Option[ClassLoader] = createApplicationClassLoader - - protected def createApplicationClassLoader: Option[ClassLoader] = Some({ - if (HOME.isDefined) { - val DEPLOY = HOME.get + "/deploy" - val DEPLOY_DIR = new File(DEPLOY) - if (!DEPLOY_DIR.exists) { - System.exit(-1) - } - val filesToDeploy = DEPLOY_DIR.listFiles.toArray.toList - .asInstanceOf[List[File]].filter(_.getName.endsWith(".jar")) - var dependencyJars: List[URL] = Nil - filesToDeploy.map { file => - val jarFile = new JarFile(file) - val en = jarFile.entries - while (en.hasMoreElements) { - val name = en.nextElement.getName - if (name.endsWith(".jar")) dependencyJars ::= new File( - String.format("jar:file:%s!/%s", jarFile.getName, name)).toURI.toURL - } - } - val toDeploy = filesToDeploy.map(_.toURI.toURL) - val allJars = toDeploy ::: dependencyJars - - new URLClassLoader(allJars.toArray, Thread.currentThread.getContextClassLoader) - } else Thread.currentThread.getContextClassLoader - }) - - abstract override def onLoad = { - super.onLoad - - for (loader ← applicationLoader; clazz ← BOOT_CLASSES) { - loader.loadClass(clazz).newInstance - } - } - - abstract override def onUnload = { - super.onUnload - Actor.registry.shutdownAll() - } -} diff --git a/test/files/presentation/akka/src/akka/actor/FSM.scala b/test/files/presentation/akka/src/akka/actor/FSM.scala deleted file mode 100644 index d9cd9a9ca2..0000000000 --- a/test/files/presentation/akka/src/akka/actor/FSM.scala +++ /dev/null @@ -1,527 +0,0 @@ -/** - * Copyright (C) 2009-2011 Scalable Solutions AB - */ -package akka.actor - -import akka.util._ -import akka.event.EventHandler - -import scala.collection.mutable -import java.util.concurrent.ScheduledFuture - -object FSM { - - object NullFunction extends PartialFunction[Any, Nothing] { - def isDefinedAt(o: Any) = false - def apply(o: Any) = sys.error("undefined") - } - - case class CurrentState[S](fsmRef: ActorRef, state: S) - case class Transition[S](fsmRef: ActorRef, from: S, to: S) - case class SubscribeTransitionCallBack(actorRef: ActorRef) - case class UnsubscribeTransitionCallBack(actorRef: ActorRef) - - sealed trait Reason - case object Normal extends Reason - case object Shutdown extends Reason - case class Failure(cause: Any) extends Reason - - case object StateTimeout - case class TimeoutMarker(generation: Long) - - case class Timer(name: String, msg: AnyRef, repeat: Boolean, generation: Int) { - private var ref: Option[ScheduledFuture[AnyRef]] = _ - - def schedule(actor: ActorRef, timeout: Duration) { - if (repeat) { - ref = Some(Scheduler.schedule(actor, this, timeout.length, timeout.length, timeout.unit)) - } else { - ref = Some(Scheduler.scheduleOnce(actor, this, timeout.length, timeout.unit)) - } - } - - def cancel { - if (ref.isDefined) { - ref.get.cancel(true) - ref = None - } - } - } - - /* - * This extractor is just convenience for matching a (S, S) pair, including a - * reminder what the new state is. - */ - object -> { - def unapply[S](in: (S, S)) = Some(in) - } - - /* - * With these implicits in scope, you can write "5 seconds" anywhere a - * Duration or Option[Duration] is expected. This is conveniently true - * for derived classes. - */ - implicit def d2od(d: Duration): Option[Duration] = Some(d) -} - -/** - * Finite State Machine actor trait. Use as follows: - * - *
          - *   object A {
          - *     trait State
          - *     case class One extends State
          - *     case class Two extends State
          - *
          - *     case class Data(i : Int)
          - *   }
          - *
          - *   class A extends Actor with FSM[A.State, A.Data] {
          - *     import A._
          - *
          - *     startWith(One, Data(42))
          - *     when(One) {
          - *         case Event(SomeMsg, Data(x)) => ...
          - *         case Ev(SomeMsg) => ... // convenience when data not needed
          - *     }
          - *     when(Two, stateTimeout = 5 seconds) { ... }
          - *     initialize
          - *   }
          - * 
          - * - * Within the partial function the following values are returned for effecting - * state transitions: - * - * - stay for staying in the same state - * - stay using Data(...) for staying in the same state, but with - * different data - * - stay forMax 5.millis for staying with a state timeout; can be - * combined with using - * - goto(...) for changing into a different state; also supports - * using and forMax - * - stop for terminating this FSM actor - * - * Each of the above also supports the method replying(AnyRef) for - * sending a reply before changing state. - * - * While changing state, custom handlers may be invoked which are registered - * using onTransition. This is meant to enable concentrating - * different concerns in different places; you may choose to use - * when for describing the properties of a state, including of - * course initiating transitions, but you can describe the transitions using - * onTransition to avoid having to duplicate that code among - * multiple paths which lead to a transition: - * - *
          - * onTransition {
          - *   case Active -> _ => cancelTimer("activeTimer")
          - * }
          - * 
          - * - * Multiple such blocks are supported and all of them will be called, not only - * the first matching one. - * - * Another feature is that other actors may subscribe for transition events by - * sending a SubscribeTransitionCallback message to this actor; - * use UnsubscribeTransitionCallback before stopping the other - * actor. - * - * State timeouts set an upper bound to the time which may pass before another - * message is received in the current state. If no external message is - * available, then upon expiry of the timeout a StateTimeout message is sent. - * Note that this message will only be received in the state for which the - * timeout was set and that any message received will cancel the timeout - * (possibly to be started again by the next transition). - * - * Another feature is the ability to install and cancel single-shot as well as - * repeated timers which arrange for the sending of a user-specified message: - * - *
          - *   setTimer("tock", TockMsg, 1 second, true) // repeating
          - *   setTimer("lifetime", TerminateMsg, 1 hour, false) // single-shot
          - *   cancelTimer("tock")
          - *   timerActive_? ("tock")
          - * 
          - */ -trait FSM[S, D] extends ListenerManagement { - this: Actor => - - import FSM._ - - type StateFunction = scala.PartialFunction[Event[D], State] - type Timeout = Option[Duration] - type TransitionHandler = PartialFunction[(S, S), Unit] - - /** - * **************************************** - * DSL - * **************************************** - */ - - /** - * Insert a new StateFunction at the end of the processing chain for the - * given state. If the stateTimeout parameter is set, entering this state - * without a differing explicit timeout setting will trigger a StateTimeout - * event; the same is true when using #stay. - * - * @param stateName designator for the state - * @param stateTimeout default state timeout for this state - * @param stateFunction partial function describing response to input - */ - protected final def when(stateName: S, stateTimeout: Timeout = None)(stateFunction: StateFunction) = { - register(stateName, stateFunction, stateTimeout) - } - - /** - * Set initial state. Call this method from the constructor before the #initialize method. - * - * @param stateName initial state designator - * @param stateData initial state data - * @param timeout state timeout for the initial state, overriding the default timeout for that state - */ - protected final def startWith(stateName: S, - stateData: D, - timeout: Timeout = None) = { - currentState = State(stateName, stateData, timeout) - } - - /** - * Produce transition to other state. Return this from a state function in - * order to effect the transition. - * - * @param nextStateName state designator for the next state - * @return state transition descriptor - */ - protected final def goto(nextStateName: S): State = { - State(nextStateName, currentState.stateData) - } - - /** - * Produce "empty" transition descriptor. Return this from a state function - * when no state change is to be effected. - * - * @return descriptor for staying in current state - */ - protected final def stay(): State = { - // cannot directly use currentState because of the timeout field - goto(currentState.stateName) - } - - /** - * Produce change descriptor to stop this FSM actor with reason "Normal". - */ - protected final def stop(): State = { - stop(Normal) - } - - /** - * Produce change descriptor to stop this FSM actor including specified reason. - */ - protected final def stop(reason: Reason): State = { - stop(reason, currentState.stateData) - } - - /** - * Produce change descriptor to stop this FSM actor including specified reason. - */ - protected final def stop(reason: Reason, stateData: D): State = { - stay using stateData withStopReason (reason) - } - - /** - * Schedule named timer to deliver message after given delay, possibly repeating. - * @param name identifier to be used with cancelTimer() - * @param msg message to be delivered - * @param timeout delay of first message delivery and between subsequent messages - * @param repeat send once if false, scheduleAtFixedRate if true - * @return current state descriptor - */ - protected final def setTimer(name: String, msg: AnyRef, timeout: Duration, repeat: Boolean): State = { - if (timers contains name) { - timers(name).cancel - } - val timer = Timer(name, msg, repeat, timerGen.next) - timer.schedule(self, timeout) - timers(name) = timer - stay - } - - /** - * Cancel named timer, ensuring that the message is not subsequently delivered (no race). - * @param name of the timer to cancel - */ - protected final def cancelTimer(name: String) = { - if (timers contains name) { - timers(name).cancel - timers -= name - } - } - - /** - * Inquire whether the named timer is still active. Returns true unless the - * timer does not exist, has previously been canceled or if it was a - * single-shot timer whose message was already received. - */ - protected final def timerActive_?(name: String) = timers contains name - - /** - * Set state timeout explicitly. This method can safely be used from within a - * state handler. - */ - protected final def setStateTimeout(state: S, timeout: Timeout) { - stateTimeouts(state) = timeout - } - - /** - * Set handler which is called upon each state transition, i.e. not when - * staying in the same state. This may use the pair extractor defined in the - * FSM companion object like so: - * - *
          -   * onTransition {
          -   *   case Old -> New => doSomething
          -   * }
          -   * 
          - * - * It is also possible to supply a 2-ary function object: - * - *
          -   * onTransition(handler _)
          -   *
          -   * private def handler(from: S, to: S) { ... }
          -   * 
          - * - * The underscore is unfortunately necessary to enable the nicer syntax shown - * above (it uses the implicit conversion total2pf under the hood). - * - * Multiple handlers may be installed, and every one of them will be - * called, not only the first one matching. - */ - protected final def onTransition(transitionHandler: TransitionHandler) { - transitionEvent :+= transitionHandler - } - - /** - * Convenience wrapper for using a total function instead of a partial - * function literal. To be used with onTransition. - */ - implicit protected final def total2pf(transitionHandler: (S, S) => Unit) = - new PartialFunction[(S, S), Unit] { - def isDefinedAt(in: (S, S)) = true - def apply(in: (S, S)) { transitionHandler(in._1, in._2) } - } - - /** - * Set handler which is called upon termination of this FSM actor. - */ - protected final def onTermination(terminationHandler: PartialFunction[StopEvent[S, D], Unit]) = { - terminateEvent = terminationHandler - } - - /** - * Set handler which is called upon reception of unhandled messages. - */ - protected final def whenUnhandled(stateFunction: StateFunction) = { - handleEvent = stateFunction orElse handleEventDefault - } - - /** - * Verify existence of initial state and setup timers. This should be the - * last call within the constructor. - */ - def initialize { - makeTransition(currentState) - } - - /** - * **************************************************************** - * PRIVATE IMPLEMENTATION DETAILS - * **************************************************************** - */ - - /* - * FSM State data and current timeout handling - */ - private var currentState: State = _ - private var timeoutFuture: Option[ScheduledFuture[AnyRef]] = None - private var generation: Long = 0L - - /* - * Timer handling - */ - private val timers = mutable.Map[String, Timer]() - private val timerGen = Iterator from 0 - - /* - * State definitions - */ - private val stateFunctions = mutable.Map[S, StateFunction]() - private val stateTimeouts = mutable.Map[S, Timeout]() - - private def register(name: S, function: StateFunction, timeout: Timeout) { - if (stateFunctions contains name) { - stateFunctions(name) = stateFunctions(name) orElse function - stateTimeouts(name) = timeout orElse stateTimeouts(name) - } else { - stateFunctions(name) = function - stateTimeouts(name) = timeout - } - } - - /* - * unhandled event handler - */ - private val handleEventDefault: StateFunction = { - case Event(value, stateData) => - stay - } - private var handleEvent: StateFunction = handleEventDefault - - /* - * termination handling - */ - private var terminateEvent: PartialFunction[StopEvent[S, D], Unit] = { - case StopEvent(Failure(cause), _, _) => - case StopEvent(reason, _, _) => - } - - /* - * transition handling - */ - private var transitionEvent: List[TransitionHandler] = Nil - private def handleTransition(prev: S, next: S) { - val tuple = (prev, next) - for (te ← transitionEvent) { if (te.isDefinedAt(tuple)) te(tuple) } - } - - // ListenerManagement shall not start() or stop() listener actors - override protected val manageLifeCycleOfListeners = false - - /** - * ******************************************* - * Main actor receive() method - * ******************************************* - */ - override final protected def receive: Receive = { - case TimeoutMarker(gen) => - if (generation == gen) { - processEvent(StateTimeout) - } - case t@Timer(name, msg, repeat, generation) => - if ((timers contains name) && (timers(name).generation == generation)) { - processEvent(msg) - if (!repeat) { - timers -= name - } - } - case SubscribeTransitionCallBack(actorRef) => - addListener(actorRef) - // send current state back as reference point - try { - actorRef ! CurrentState(self, currentState.stateName) - } catch { - case e: ActorInitializationException => - EventHandler.warning(this, "trying to register not running listener") - } - case UnsubscribeTransitionCallBack(actorRef) => - removeListener(actorRef) - case value => { - if (timeoutFuture.isDefined) { - timeoutFuture.get.cancel(true) - timeoutFuture = None - } - generation += 1 - processEvent(value) - } - } - - private def processEvent(value: Any) = { - val event = Event(value, currentState.stateData) - val stateFunc = stateFunctions(currentState.stateName) - val nextState = if (stateFunc isDefinedAt event) { - stateFunc(event) - } else { - // handleEventDefault ensures that this is always defined - handleEvent(event) - } - nextState.stopReason match { - case Some(reason) => terminate(reason) - case None => makeTransition(nextState) - } - } - - private def makeTransition(nextState: State) = { - if (!stateFunctions.contains(nextState.stateName)) { - terminate(Failure("Next state %s does not exist".format(nextState.stateName))) - } else { - if (currentState.stateName != nextState.stateName) { - handleTransition(currentState.stateName, nextState.stateName) - notifyListeners(Transition(self, currentState.stateName, nextState.stateName)) - } - applyState(nextState) - } - } - - private def applyState(nextState: State) = { - currentState = nextState - val timeout = if (currentState.timeout.isDefined) currentState.timeout else stateTimeouts(currentState.stateName) - if (timeout.isDefined) { - val t = timeout.get - if (t.finite_? && t.length >= 0) { - timeoutFuture = Some(Scheduler.scheduleOnce(self, TimeoutMarker(generation), t.length, t.unit)) - } - } - } - - private def terminate(reason: Reason) = { - terminateEvent.apply(StopEvent(reason, currentState.stateName, currentState.stateData)) - self.stop() - } - - case class Event[D](event: Any, stateData: D) - object Ev { - def unapply[D](e: Event[D]): Option[Any] = Some(e.event) - } - - case class State(stateName: S, stateData: D, timeout: Timeout = None) { - - /** - * Modify state transition descriptor to include a state timeout for the - * next state. This timeout overrides any default timeout set for the next - * state. - */ - def forMax(timeout: Duration): State = { - copy(timeout = Some(timeout)) - } - - /** - * Send reply to sender of the current message, if available. - * - * @return this state transition descriptor - */ - def replying(replyValue: Any): State = { - self.sender match { - case Some(sender) => sender ! replyValue - case None => - } - this - } - - /** - * Modify state transition descriptor with new state data. The data will be - * set when transitioning to the new state. - */ - def using(nextStateDate: D): State = { - copy(stateData = nextStateDate) - } - - private[akka] var stopReason: Option[Reason] = None - - private[akka] def withStopReason(reason: Reason): State = { - stopReason = Some(reason) - this - } - } - - case class StopEvent[S, D](reason: Reason, currentState: S, stateData: D) -} diff --git a/test/files/presentation/akka/src/akka/actor/Scheduler.scala b/test/files/presentation/akka/src/akka/actor/Scheduler.scala deleted file mode 100644 index 128584f3c5..0000000000 --- a/test/files/presentation/akka/src/akka/actor/Scheduler.scala +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright 2007 WorldWide Conferencing, LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Rework of David Pollak's ActorPing class in the Lift Project - * which is licensed under the Apache 2 License. - */ -package akka.actor - -import scala.collection.JavaConversions - -import java.util.concurrent._ - -import akka.event.EventHandler -import akka.AkkaException - -object Scheduler { - import Actor._ - - case class SchedulerException(msg: String, e: Throwable) extends RuntimeException(msg, e) - - @volatile - private var service = Executors.newSingleThreadScheduledExecutor(SchedulerThreadFactory) - - /** - * Schedules to send the specified message to the receiver after initialDelay and then repeated after delay - */ - def schedule(receiver: ActorRef, message: AnyRef, initialDelay: Long, delay: Long, timeUnit: TimeUnit): ScheduledFuture[AnyRef] = { - try { - service.scheduleAtFixedRate( - new Runnable { def run = receiver ! message }, - initialDelay, delay, timeUnit).asInstanceOf[ScheduledFuture[AnyRef]] - } catch { - case e: Exception => - val error = SchedulerException(message + " could not be scheduled on " + receiver, e) - EventHandler.error(error, this, "%s @ %s".format(receiver, message)) - throw error - } - } - - /** - * Schedules to run specified function to the receiver after initialDelay and then repeated after delay, - * avoid blocking operations since this is executed in the schedulers thread - */ - def schedule(f: () => Unit, initialDelay: Long, delay: Long, timeUnit: TimeUnit): ScheduledFuture[AnyRef] = - schedule(new Runnable { def run = f() }, initialDelay, delay, timeUnit) - - /** - * Schedules to run specified runnable to the receiver after initialDelay and then repeated after delay, - * avoid blocking operations since this is executed in the schedulers thread - */ - def schedule(runnable: Runnable, initialDelay: Long, delay: Long, timeUnit: TimeUnit): ScheduledFuture[AnyRef] = { - try { - service.scheduleAtFixedRate(runnable, initialDelay, delay, timeUnit).asInstanceOf[ScheduledFuture[AnyRef]] - } catch { - case e: Exception => - val error = SchedulerException("Failed to schedule a Runnable", e) - EventHandler.error(error, this, error.getMessage) - throw error - } - } - - /** - * Schedules to send the specified message to the receiver after delay - */ - def scheduleOnce(receiver: ActorRef, message: AnyRef, delay: Long, timeUnit: TimeUnit): ScheduledFuture[AnyRef] = { - try { - service.schedule( - new Runnable { def run = receiver ! message }, - delay, timeUnit).asInstanceOf[ScheduledFuture[AnyRef]] - } catch { - case e: Exception => - val error = SchedulerException(message + " could not be scheduleOnce'd on " + receiver, e) - EventHandler.error(e, this, receiver + " @ " + message) - throw error - } - } - - /** - * Schedules a function to be run after delay, - * avoid blocking operations since the runnable is executed in the schedulers thread - */ - def scheduleOnce(f: () => Unit, delay: Long, timeUnit: TimeUnit): ScheduledFuture[AnyRef] = - scheduleOnce(new Runnable { def run = f() }, delay, timeUnit) - - /** - * Schedules a runnable to be run after delay, - * avoid blocking operations since the runnable is executed in the schedulers thread - */ - def scheduleOnce(runnable: Runnable, delay: Long, timeUnit: TimeUnit): ScheduledFuture[AnyRef] = { - try { - service.schedule(runnable, delay, timeUnit).asInstanceOf[ScheduledFuture[AnyRef]] - } catch { - case e: Exception => - val error = SchedulerException("Failed to scheduleOnce a Runnable", e) - EventHandler.error(e, this, error.getMessage) - throw error - } - } - - def shutdown() { - synchronized { - service.shutdown() - } - } - - def restart() { - synchronized { - shutdown() - service = Executors.newSingleThreadScheduledExecutor(SchedulerThreadFactory) - } - } -} - -private object SchedulerThreadFactory extends ThreadFactory { - private var count = 0 - val threadFactory = Executors.defaultThreadFactory() - - def newThread(r: Runnable): Thread = { - val thread = threadFactory.newThread(r) - thread.setName("akka:scheduler-" + count) - thread.setDaemon(true) - thread - } -} diff --git a/test/files/presentation/akka/src/akka/actor/Supervisor.scala b/test/files/presentation/akka/src/akka/actor/Supervisor.scala deleted file mode 100644 index 4a1309faef..0000000000 --- a/test/files/presentation/akka/src/akka/actor/Supervisor.scala +++ /dev/null @@ -1,176 +0,0 @@ -/** - * Copyright (C) 2009-2011 Scalable Solutions AB - */ - -package akka.actor - -import akka.AkkaException -import akka.util._ -import ReflectiveAccess._ -import Actor._ - -import java.util.concurrent.{ CopyOnWriteArrayList, ConcurrentHashMap } -import java.net.InetSocketAddress -import akka.config.Supervision._ - -class SupervisorException private[akka] (message: String, cause: Throwable = null) extends AkkaException(message, cause) - -/** - * Factory object for creating supervisors declarative. It creates instances of the 'Supervisor' class. - * These are not actors, if you need a supervisor that is an Actor then you have to use the 'SupervisorActor' - * factory object. - *

          - * - * Here is a sample on how to use it: - *

          - *  val supervisor = Supervisor(
          - *    SupervisorConfig(
          - *      RestartStrategy(OneForOne, 3, 10, List(classOf[Exception]),
          - *      Supervise(
          - *        myFirstActor,
          - *        Permanent) ::
          - *      Supervise(
          - *        mySecondActor,
          - *        Permanent) ::
          - *      Nil))
          - * 
          - * - * You dynamically link and unlink child children using the 'link' and 'unlink' methods. - *
          - * supervisor.link(child)
          - * supervisor.unlink(child)
          - * 
          - * - * @author Jonas Bonér - */ -object Supervisor { - def apply(config: SupervisorConfig): Supervisor = SupervisorFactory(config).newInstance.start -} - -/** - * Use this factory instead of the Supervisor factory object if you want to control - * instantiation and starting of the Supervisor, if not then it is easier and better - * to use the Supervisor factory object. - *

          - * Example usage: - *

          - *  val factory = SupervisorFactory(
          - *    SupervisorConfig(
          - *      RestartStrategy(OneForOne, 3, 10, List(classOf[Exception]),
          - *      Supervise(
          - *        myFirstActor,
          - *        Permanent) ::
          - *      Supervise(
          - *        mySecondActor,
          - *        Permanent) ::
          - *      Nil))
          - * 
          - * - * Then create a new Supervisor tree with the concrete Services we have defined. - * - *
          - * val supervisor = factory.newInstance
          - * supervisor.start // start up all managed servers
          - * 
          - * - * @author Jonas Bonér - */ -case class SupervisorFactory(val config: SupervisorConfig) { - - def newInstance: Supervisor = newInstanceFor(config) - - def newInstanceFor(config: SupervisorConfig): Supervisor = { - val supervisor = new Supervisor(config.restartStrategy, config.maxRestartsHandler) - supervisor.configure(config) - supervisor.start - supervisor - } -} - -/** - * NOTE: - *

          - * The supervisor class is only used for the configuration system when configuring supervisor - * hierarchies declaratively. Should not be used as part of the regular programming API. Instead - * wire the children together using 'link', 'spawnLink' etc. and set the 'trapExit' flag in the - * children that should trap error signals and trigger restart. - *

          - * See the ScalaDoc for the SupervisorFactory for an example on how to declaratively wire up children. - * - * @author Jonas Bonér - */ -sealed class Supervisor(handler: FaultHandlingStrategy, maxRestartsHandler: (ActorRef, MaximumNumberOfRestartsWithinTimeRangeReached) => Unit) { - import Supervisor._ - - private val _childActors = new ConcurrentHashMap[String, List[ActorRef]] - private val _childSupervisors = new CopyOnWriteArrayList[Supervisor] - - private[akka] val supervisor = actorOf(new SupervisorActor(handler, maxRestartsHandler)).start() - - def uuid = supervisor.uuid - - def start: Supervisor = { - this - } - - def shutdown(): Unit = supervisor.stop() - - def link(child: ActorRef) = supervisor.link(child) - - def unlink(child: ActorRef) = supervisor.unlink(child) - - def children: List[ActorRef] = - _childActors.values.toArray.toList.asInstanceOf[List[List[ActorRef]]].flatten - - def childSupervisors: List[Supervisor] = - _childActors.values.toArray.toList.asInstanceOf[List[Supervisor]] - - def configure(config: SupervisorConfig): Unit = config match { - case SupervisorConfig(_, servers, _) => - - servers.map(server => - server match { - case Supervise(actorRef, lifeCycle, registerAsRemoteService) => - actorRef.start() - val className = actorRef.actor.getClass.getName - val currentActors = { - val list = _childActors.get(className) - if (list eq null) List[ActorRef]() - else list - } - _childActors.put(className, actorRef :: currentActors) - actorRef.lifeCycle = lifeCycle - supervisor.link(actorRef) - if (registerAsRemoteService) - Actor.remote.register(actorRef) - case supervisorConfig@SupervisorConfig(_, _, _) => // recursive supervisor configuration - val childSupervisor = Supervisor(supervisorConfig) - supervisor.link(childSupervisor.supervisor) - _childSupervisors.add(childSupervisor) - }) - } -} - -/** - * For internal use only. - * - * @author Jonas Bonér - */ -final class SupervisorActor private[akka] (handler: FaultHandlingStrategy, maxRestartsHandler: (ActorRef, MaximumNumberOfRestartsWithinTimeRangeReached) => Unit) extends Actor { - self.faultHandler = handler - - override def postStop(): Unit = { - val i = self.linkedActors.values.iterator - while (i.hasNext) { - val ref = i.next - ref.stop() - self.unlink(ref) - } - } - - def receive = { - case max@MaximumNumberOfRestartsWithinTimeRangeReached(_, _, _, _) => maxRestartsHandler(self, max) - case unknown => throw new SupervisorException( - "SupervisorActor can not respond to messages.\n\tUnknown message [" + unknown + "]") - } -} diff --git a/test/files/presentation/akka/src/akka/actor/UntypedActor.scala b/test/files/presentation/akka/src/akka/actor/UntypedActor.scala deleted file mode 100644 index cbc43f22f8..0000000000 --- a/test/files/presentation/akka/src/akka/actor/UntypedActor.scala +++ /dev/null @@ -1,134 +0,0 @@ -/** - * Copyright (C) 2009-2011 Scalable Solutions AB - */ - -package akka.actor - -import akka.japi.{ Creator, Procedure } - -/** - * Subclass this abstract class to create a MDB-style untyped actor. - *

          - * This class is meant to be used from Java. - *

          - * Here is an example on how to create and use an UntypedActor: - *

          - *  public class SampleUntypedActor extends UntypedActor {
          - *    public void onReceive(Object message) throws Exception {
          - *      if (message instanceof String) {
          - *        String msg = (String)message;
          - *
          - *        if (msg.equals("UseReply")) {
          - *          // Reply to original sender of message using the 'replyUnsafe' method
          - *          getContext().replyUnsafe(msg + ":" + getContext().getUuid());
          - *
          - *        } else if (msg.equals("UseSender") && getContext().getSender().isDefined()) {
          - *          // Reply to original sender of message using the sender reference
          - *          // also passing along my own reference (the context)
          - *          getContext().getSender().get().sendOneWay(msg, context);
          - *
          - *        } else if (msg.equals("UseSenderFuture") && getContext().getSenderFuture().isDefined()) {
          - *          // Reply to original sender of message using the sender future reference
          - *          getContext().getSenderFuture().get().completeWithResult(msg);
          - *
          - *        } else if (msg.equals("SendToSelf")) {
          - *          // Send message to the actor itself recursively
          - *          getContext().sendOneWay(msg)
          - *
          - *        } else if (msg.equals("ForwardMessage")) {
          - *          // Retrieve an actor from the ActorRegistry by ID and get an ActorRef back
          - *          ActorRef actorRef = Actor.registry.actorsFor("some-actor-id").head();
          - *
          - *        } else throw new IllegalArgumentException("Unknown message: " + message);
          - *      } else throw new IllegalArgumentException("Unknown message: " + message);
          - *    }
          - *
          - *    public static void main(String[] args) {
          - *      ActorRef actor = Actors.actorOf(SampleUntypedActor.class);
          - *      actor.start();
          - *      actor.sendOneWay("SendToSelf");
          - *      actor.stop();
          - *    }
          - *  }
          - * 
          - * - * @author Jonas Bonér - */ -abstract class UntypedActor extends Actor { - - /** - * To be implemented by concrete UntypedActor. Defines the message handler. - */ - @throws(classOf[Exception]) - def onReceive(message: Any): Unit - - /** - * Returns the 'self' reference with the API. - */ - def getContext(): ActorRef = self - - /** - * Returns the 'self' reference with the API. - */ - def context(): ActorRef = self - - /** - * Java API for become - */ - def become(behavior: Procedure[Any]): Unit = become(behavior, false) - - /* - * Java API for become with optional discardOld - */ - def become(behavior: Procedure[Any], discardOld: Boolean): Unit = - super.become({ case msg => behavior.apply(msg) }, discardOld) - - /** - * User overridable callback. - *

          - * Is called when an Actor is started by invoking 'actor.start()'. - */ - override def preStart() {} - - /** - * User overridable callback. - *

          - * Is called when 'actor.stop()' is invoked. - */ - override def postStop() {} - - /** - * User overridable callback. - *

          - * Is called on a crashed Actor right BEFORE it is restarted to allow clean up of resources before Actor is terminated. - */ - override def preRestart(reason: Throwable) {} - - /** - * User overridable callback. - *

          - * Is called right AFTER restart on the newly created Actor to allow reinitialization after an Actor crash. - */ - override def postRestart(reason: Throwable) {} - - /** - * User overridable callback. - *

          - * Is called when a message isn't handled by the current behavior of the actor - * by default it throws an UnhandledMessageException - */ - override def unhandled(msg: Any) { - throw new UnhandledMessageException(msg, self) - } - - final protected def receive = { - case msg => onReceive(msg) - } -} - -/** - * Factory closure for an UntypedActor, to be used with 'Actors.actorOf(factory)'. - * - * @author Jonas Bonér - */ -trait UntypedActorFactory extends Creator[Actor] diff --git a/test/files/presentation/akka/src/akka/actor/package.scala b/test/files/presentation/akka/src/akka/actor/package.scala deleted file mode 100644 index fbeeed49cb..0000000000 --- a/test/files/presentation/akka/src/akka/actor/package.scala +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Copyright (C) 2009-2011 Scalable Solutions AB - */ - -package akka - -import actor.{ ScalaActorRef, ActorRef } - -package object actor { - implicit def actorRef2Scala(ref: ActorRef): ScalaActorRef = - ref.asInstanceOf[ScalaActorRef] - - implicit def scala2ActorRef(ref: ScalaActorRef): ActorRef = - ref.asInstanceOf[ActorRef] - - type Uuid = com.eaio.uuid.UUID - - def newUuid(): Uuid = new Uuid() - - def uuidFrom(time: Long, clockSeqAndNode: Long): Uuid = new Uuid(time, clockSeqAndNode) - - def uuidFrom(uuid: String): Uuid = new Uuid(uuid) -} diff --git a/test/files/presentation/akka/src/akka/config/Config.scala b/test/files/presentation/akka/src/akka/config/Config.scala deleted file mode 100644 index 6578c66f77..0000000000 --- a/test/files/presentation/akka/src/akka/config/Config.scala +++ /dev/null @@ -1,93 +0,0 @@ -/** - * Copyright (C) 2009-2011 Scalable Solutions AB - */ - -package akka.config - -import akka.AkkaException - -class ConfigurationException(message: String, cause: Throwable = null) extends AkkaException(message, cause) -class ModuleNotAvailableException(message: String, cause: Throwable = null) extends AkkaException(message, cause) - -/** - * Loads up the configuration (from the akka.conf file). - * - * @author Jonas Bonér - */ -object Config { - val VERSION = "1.1.3" - - val HOME = { - val envHome = System.getenv("AKKA_HOME") match { - case null | "" | "." => None - case value => Some(value) - } - - val systemHome = System.getProperty("akka.home") match { - case null | "" => None - case value => Some(value) - } - - envHome orElse systemHome - } - - val config: Configuration = try { - val confName = { - val envConf = System.getenv("AKKA_MODE") match { - case null | "" => None - case value => Some(value) - } - - val systemConf = System.getProperty("akka.mode") match { - case null | "" => None - case value => Some(value) - } - - (envConf orElse systemConf).map("akka." + _ + ".conf").getOrElse("akka.conf") - } - - val newInstance = - if (System.getProperty("akka.config", "") != "") { - val configFile = System.getProperty("akka.config", "") - println("Loading config from -Dakka.config=" + configFile) - Configuration.fromFile(configFile) - } else if (getClass.getClassLoader.getResource(confName) ne null) { - println("Loading config [" + confName + "] from the application classpath.") - Configuration.fromResource(confName, getClass.getClassLoader) - } else if (HOME.isDefined) { - val configFile = HOME.get + "/config/" + confName - println("AKKA_HOME is defined as [" + HOME.get + "], loading config from [" + configFile + "].") - Configuration.fromFile(configFile) - } else { - println( - "\nCan't load '" + confName + "'." + - "\nOne of the three ways of locating the '" + confName + "' file needs to be defined:" + - "\n\t1. Define the '-Dakka.config=...' system property option." + - "\n\t2. Put the '" + confName + "' file on the classpath." + - "\n\t3. Define 'AKKA_HOME' environment variable pointing to the root of the Akka distribution." + - "\nI have no way of finding the '" + confName + "' configuration file." + - "\nUsing default values everywhere.") - Configuration.fromString("akka {}") // default empty config - } - - val configVersion = newInstance.getString("akka.version", VERSION) - if (configVersion != VERSION) - throw new ConfigurationException( - "Akka JAR version [" + VERSION + "] is different than the provided config version [" + configVersion + "]") - - newInstance - } catch { - case e => - System.err.println("Couldn't parse config, fatal error.") - e.printStackTrace(System.err) - System.exit(-1) - throw e - } - - val CONFIG_VERSION = config.getString("akka.version", VERSION) - - val TIME_UNIT = config.getString("akka.time-unit", "seconds") - - val startTime = System.currentTimeMillis - def uptime = (System.currentTimeMillis - startTime) / 1000 -} diff --git a/test/files/presentation/akka/src/akka/config/ConfigParser.scala b/test/files/presentation/akka/src/akka/config/ConfigParser.scala deleted file mode 100644 index 73fac5e31b..0000000000 --- a/test/files/presentation/akka/src/akka/config/ConfigParser.scala +++ /dev/null @@ -1,74 +0,0 @@ -/** - * Copyright (C) 2009-2011 Scalable Solutions AB - * - * Based on Configgy by Robey Pointer. - * Copyright 2009 Robey Pointer - * http://www.apache.org/licenses/LICENSE-2.0 - */ - -package akka.config - -import scala.collection.mutable -import scala.util.parsing.combinator._ - -class ConfigParser(var prefix: String = "", map: mutable.Map[String, Any] = mutable.Map.empty[String, Any], importer: Importer) extends RegexParsers { - val sections = mutable.Stack[String]() - - def createPrefix = { - prefix = if (sections.isEmpty) "" else sections.toList.reverse.mkString("", ".", ".") - } - - override val whiteSpace = """(\s+|#[^\n]*\n)+""".r - - // tokens - - val numberToken: Parser[String] = """-?\d+(\.\d+)?""".r - val stringToken: Parser[String] = ("\"" + """([^\\\"]|\\[^ux]|\\\n|\\u[0-9a-fA-F]{4}|\\x[0-9a-fA-F]{2})*""" + "\"").r - val booleanToken: Parser[String] = "(true|on|false|off)".r - val identToken: Parser[String] = """([\da-zA-Z_][-\w]*)(\.[a-zA-Z_][-\w]*)*""".r - val assignToken: Parser[String] = "=".r - val sectionToken: Parser[String] = """[a-zA-Z][-\w]*""".r - - // values - - def value: Parser[Any] = number | string | list | boolean - def number = numberToken - def string = stringToken ^^ { s => s.substring(1, s.length - 1) } - def list = "[" ~> repsep(string | numberToken, opt(",")) <~ (opt(",") ~ "]") - def boolean = booleanToken - - // parser - - def root = rep(includeFile | assignment | sectionOpen | sectionClose) - - def includeFile = "include" ~> string ^^ { - case filename: String => - new ConfigParser(prefix, map, importer) parse importer.importFile(filename) - } - - def assignment = identToken ~ assignToken ~ value ^^ { - case k ~ a ~ v => map(prefix + k) = v - } - - def sectionOpen = sectionToken <~ "{" ^^ { name => - sections push name - createPrefix - } - - def sectionClose = "}" ^^ { _ => - if (sections.isEmpty) { - failure("dangling close tag") - } else { - sections.pop - createPrefix - } - } - - def parse(in: String): Map[String, Any] = { - parseAll(root, in) match { - case Success(result, _) => map.toMap - case x@Failure(msg, _) => throw new ConfigurationException(x.toString) - case x@Error(msg, _) => throw new ConfigurationException(x.toString) - } - } -} diff --git a/test/files/presentation/akka/src/akka/config/Configuration.scala b/test/files/presentation/akka/src/akka/config/Configuration.scala deleted file mode 100644 index 81c32fce90..0000000000 --- a/test/files/presentation/akka/src/akka/config/Configuration.scala +++ /dev/null @@ -1,166 +0,0 @@ -/** - * Copyright (C) 2009-2011 Scalable Solutions AB - * - * Based on Configgy by Robey Pointer. - * Copyright 2009 Robey Pointer - * http://www.apache.org/licenses/LICENSE-2.0 - */ - -package akka.config - -import java.io.File - -object Configuration { - val DefaultPath = new File(".").getCanonicalPath - val DefaultImporter = new FilesystemImporter(DefaultPath) - - def load(data: String, importer: Importer = DefaultImporter): Configuration = { - val parser = new ConfigParser(importer = importer) - new Configuration(parser parse data) - } - - def fromFile(filename: String, importer: Importer): Configuration = { - load(importer.importFile(filename), importer) - } - - def fromFile(path: String, filename: String): Configuration = { - val importer = new FilesystemImporter(path) - fromFile(filename, importer) - } - - def fromFile(filename: String): Configuration = { - val n = filename.lastIndexOf('/') - if (n < 0) { - fromFile(DefaultPath, filename) - } else { - fromFile(filename.substring(0, n), filename.substring(n + 1)) - } - } - - def fromResource(filename: String): Configuration = { - fromResource(filename, ClassLoader.getSystemClassLoader) - } - - def fromResource(filename: String, classLoader: ClassLoader): Configuration = { - val importer = new ResourceImporter(classLoader) - fromFile(filename, importer) - } - - def fromMap(map: Map[String, Any]) = { - new Configuration(map) - } - - def fromString(data: String): Configuration = { - load(data) - } -} - -class Configuration(val map: Map[String, Any]) { - private val trueValues = Set("true", "on") - private val falseValues = Set("false", "off") - - def contains(key: String): Boolean = map contains key - - def keys: Iterable[String] = map.keys - - def getAny(key: String): Option[Any] = { - try { - Some(map(key)) - } catch { - case _ => None - } - } - - def getAny(key: String, defaultValue: Any): Any = getAny(key).getOrElse(defaultValue) - - def getSeqAny(key: String): Seq[Any] = { - try { - map(key).asInstanceOf[Seq[Any]] - } catch { - case _ => Seq.empty[Any] - } - } - - def getString(key: String): Option[String] = map.get(key).map(_.toString) - - def getString(key: String, defaultValue: String): String = getString(key).getOrElse(defaultValue) - - def getList(key: String): Seq[String] = { - try { - map(key).asInstanceOf[Seq[String]] - } catch { - case _ => Seq.empty[String] - } - } - - def getInt(key: String): Option[Int] = { - try { - Some(map(key).toString.toInt) - } catch { - case _ => None - } - } - - def getInt(key: String, defaultValue: Int): Int = getInt(key).getOrElse(defaultValue) - - def getLong(key: String): Option[Long] = { - try { - Some(map(key).toString.toLong) - } catch { - case _ => None - } - } - - def getLong(key: String, defaultValue: Long): Long = getLong(key).getOrElse(defaultValue) - - def getFloat(key: String): Option[Float] = { - try { - Some(map(key).toString.toFloat) - } catch { - case _ => None - } - } - - def getFloat(key: String, defaultValue: Float): Float = getFloat(key).getOrElse(defaultValue) - - def getDouble(key: String): Option[Double] = { - try { - Some(map(key).toString.toDouble) - } catch { - case _ => None - } - } - - def getDouble(key: String, defaultValue: Double): Double = getDouble(key).getOrElse(defaultValue) - - def getBoolean(key: String): Option[Boolean] = { - getString(key) flatMap { s => - val isTrue = trueValues.contains(s) - if (!isTrue && !falseValues.contains(s)) None - else Some(isTrue) - } - } - - def getBoolean(key: String, defaultValue: Boolean): Boolean = getBool(key).getOrElse(defaultValue) - - def getBool(key: String): Option[Boolean] = getBoolean(key) - - def getBool(key: String, defaultValue: Boolean): Boolean = getBoolean(key, defaultValue) - - def apply(key: String): String = getString(key) match { - case None => throw new ConfigurationException("undefined config: " + key) - case Some(v) => v - } - - def apply(key: String, defaultValue: String) = getString(key, defaultValue) - def apply(key: String, defaultValue: Int) = getInt(key, defaultValue) - def apply(key: String, defaultValue: Long) = getLong(key, defaultValue) - def apply(key: String, defaultValue: Boolean) = getBool(key, defaultValue) - - def getSection(name: String): Option[Configuration] = { - val l = name.length + 1 - val m = map.collect { case (k, v) if k.startsWith(name) => (k.substring(l), v) } - if (m.isEmpty) None - else Some(new Configuration(m)) - } -} diff --git a/test/files/presentation/akka/src/akka/config/Configurator.scala b/test/files/presentation/akka/src/akka/config/Configurator.scala deleted file mode 100644 index 2818339b0f..0000000000 --- a/test/files/presentation/akka/src/akka/config/Configurator.scala +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Copyright (C) 2009-2011 Scalable Solutions AB - */ - -package akka.config - -import akka.config.Supervision.{ SuperviseTypedActor, FaultHandlingStrategy } - -private[akka] trait TypedActorConfiguratorBase { - def getExternalDependency[T](clazz: Class[T]): T - - def configure(restartStrategy: FaultHandlingStrategy, components: List[SuperviseTypedActor]): TypedActorConfiguratorBase - - def inject: TypedActorConfiguratorBase - - def supervise: TypedActorConfiguratorBase - - def reset - - def stop -} diff --git a/test/files/presentation/akka/src/akka/config/Importer.scala b/test/files/presentation/akka/src/akka/config/Importer.scala deleted file mode 100644 index eebda1d4fe..0000000000 --- a/test/files/presentation/akka/src/akka/config/Importer.scala +++ /dev/null @@ -1,64 +0,0 @@ -/** - * Copyright (C) 2009-2011 Scalable Solutions AB - * - * Based on Configgy by Robey Pointer. - * Copyright 2009 Robey Pointer - * http://www.apache.org/licenses/LICENSE-2.0 - */ - -package akka.config - -import java.io.{ BufferedReader, File, FileInputStream, InputStream, InputStreamReader } - -/** - * An interface for finding config files and reading them into strings for - * parsing. This is used to handle `include` directives in config files. - */ -trait Importer { - - def importFile(filename: String): String - - private val BUFFER_SIZE = 8192 - - protected def streamToString(in: InputStream): String = { - try { - val reader = new BufferedReader(new InputStreamReader(in, "UTF-8")) - val buffer = new Array[Char](BUFFER_SIZE) - val sb = new StringBuilder - var n = 0 - while (n >= 0) { - n = reader.read(buffer, 0, buffer.length) - if (n >= 0) { - sb.appendAll(buffer, 0, n) - } - } - in.close() - sb.toString - } catch { - case x => throw new ConfigurationException(x.toString) - } - } -} - -/** - * An Importer that looks for imported config files in the filesystem. - * This is the default importer. - */ -class FilesystemImporter(val baseDir: String) extends Importer { - def importFile(filename: String): String = { - val f = new File(filename) - val file = if (f.isAbsolute) f else new File(baseDir, filename) - streamToString(new FileInputStream(file)) - } -} - -/** - * An Importer that looks for imported config files in the java resources - * of the system class loader (usually the jar used to launch this app). - */ -class ResourceImporter(classLoader: ClassLoader) extends Importer { - def importFile(filename: String): String = { - val stream = classLoader.getResourceAsStream(filename) - streamToString(stream) - } -} diff --git a/test/files/presentation/akka/src/akka/config/SupervisionConfig.scala b/test/files/presentation/akka/src/akka/config/SupervisionConfig.scala deleted file mode 100644 index 40f61f615f..0000000000 --- a/test/files/presentation/akka/src/akka/config/SupervisionConfig.scala +++ /dev/null @@ -1,134 +0,0 @@ -/** - * Copyright (C) 2009-2011 Scalable Solutions AB - */ - -package akka.config - -import akka.dispatch.MessageDispatcher -import akka.actor.{ MaximumNumberOfRestartsWithinTimeRangeReached, ActorRef } -import akka.japi.{ Procedure2, Procedure } - -case class RemoteAddress(val hostname: String, val port: Int) - -/** - * Configuration classes - not to be used as messages. - * - * @author Jonas Bonér - */ -object Supervision { - sealed abstract class ConfigElement - - abstract class Server extends ConfigElement - sealed abstract class LifeCycle extends ConfigElement - sealed abstract class FaultHandlingStrategy(val trapExit: List[Class[_ <: Throwable]]) extends ConfigElement - - case class SupervisorConfig(restartStrategy: FaultHandlingStrategy, worker: List[Server], maxRestartsHandler: (ActorRef, MaximumNumberOfRestartsWithinTimeRangeReached) => Unit = { (aRef, max) => () }) extends Server { - //Java API - def this(restartStrategy: FaultHandlingStrategy, worker: Array[Server]) = this(restartStrategy, worker.toList) - def this(restartStrategy: FaultHandlingStrategy, worker: Array[Server], restartHandler: Procedure2[ActorRef, MaximumNumberOfRestartsWithinTimeRangeReached]) = this(restartStrategy, worker.toList, { (aRef, max) => restartHandler.apply(aRef, max) }) - } - - class Supervise(val actorRef: ActorRef, val lifeCycle: LifeCycle, val registerAsRemoteService: Boolean = false) extends Server { - //Java API - def this(actorRef: ActorRef, lifeCycle: LifeCycle) = - this(actorRef, lifeCycle, false) - } - - object Supervise { - def apply(actorRef: ActorRef, lifeCycle: LifeCycle, registerAsRemoteService: Boolean = false) = new Supervise(actorRef, lifeCycle, registerAsRemoteService) - def apply(actorRef: ActorRef, lifeCycle: LifeCycle) = new Supervise(actorRef, lifeCycle, false) - def unapply(supervise: Supervise) = Some((supervise.actorRef, supervise.lifeCycle, supervise.registerAsRemoteService)) - } - - object AllForOneStrategy { - def apply(trapExit: List[Class[_ <: Throwable]], maxNrOfRetries: Int, withinTimeRange: Int): AllForOneStrategy = - new AllForOneStrategy(trapExit, - if (maxNrOfRetries < 0) None else Some(maxNrOfRetries), if (withinTimeRange < 0) None else Some(withinTimeRange)) - } - - case class AllForOneStrategy(override val trapExit: List[Class[_ <: Throwable]], - maxNrOfRetries: Option[Int] = None, - withinTimeRange: Option[Int] = None) extends FaultHandlingStrategy(trapExit) { - def this(trapExit: List[Class[_ <: Throwable]], maxNrOfRetries: Int, withinTimeRange: Int) = - this(trapExit, - if (maxNrOfRetries < 0) None else Some(maxNrOfRetries), if (withinTimeRange < 0) None else Some(withinTimeRange)) - - def this(trapExit: Array[Class[_ <: Throwable]], maxNrOfRetries: Int, withinTimeRange: Int) = - this(trapExit.toList, - if (maxNrOfRetries < 0) None else Some(maxNrOfRetries), if (withinTimeRange < 0) None else Some(withinTimeRange)) - - def this(trapExit: java.util.List[Class[_ <: Throwable]], maxNrOfRetries: Int, withinTimeRange: Int) = - this(trapExit.toArray.toList.asInstanceOf[List[Class[_ <: Throwable]]], - if (maxNrOfRetries < 0) None else Some(maxNrOfRetries), if (withinTimeRange < 0) None else Some(withinTimeRange)) - } - - object OneForOneStrategy { - def apply(trapExit: List[Class[_ <: Throwable]], maxNrOfRetries: Int, withinTimeRange: Int): OneForOneStrategy = - new OneForOneStrategy(trapExit, - if (maxNrOfRetries < 0) None else Some(maxNrOfRetries), if (withinTimeRange < 0) None else Some(withinTimeRange)) - } - - case class OneForOneStrategy(override val trapExit: List[Class[_ <: Throwable]], - maxNrOfRetries: Option[Int] = None, - withinTimeRange: Option[Int] = None) extends FaultHandlingStrategy(trapExit) { - def this(trapExit: List[Class[_ <: Throwable]], maxNrOfRetries: Int, withinTimeRange: Int) = - this(trapExit, - if (maxNrOfRetries < 0) None else Some(maxNrOfRetries), if (withinTimeRange < 0) None else Some(withinTimeRange)) - - def this(trapExit: Array[Class[_ <: Throwable]], maxNrOfRetries: Int, withinTimeRange: Int) = - this(trapExit.toList, - if (maxNrOfRetries < 0) None else Some(maxNrOfRetries), if (withinTimeRange < 0) None else Some(withinTimeRange)) - - def this(trapExit: java.util.List[Class[_ <: Throwable]], maxNrOfRetries: Int, withinTimeRange: Int) = - this(trapExit.toArray.toList.asInstanceOf[List[Class[_ <: Throwable]]], - if (maxNrOfRetries < 0) None else Some(maxNrOfRetries), if (withinTimeRange < 0) None else Some(withinTimeRange)) - } - - case object NoFaultHandlingStrategy extends FaultHandlingStrategy(Nil) - - //Scala API - case object Permanent extends LifeCycle - case object Temporary extends LifeCycle - case object UndefinedLifeCycle extends LifeCycle - - //Java API (& Scala if you fancy) - def permanent(): LifeCycle = Permanent - def temporary(): LifeCycle = Temporary - def undefinedLifeCycle(): LifeCycle = UndefinedLifeCycle - - //Java API - def noFaultHandlingStrategy = NoFaultHandlingStrategy - - case class SuperviseTypedActor(_intf: Class[_], - val target: Class[_], - val lifeCycle: LifeCycle, - val timeout: Long, - _dispatcher: MessageDispatcher, // optional - _remoteAddress: RemoteAddress // optional - ) extends Server { - val intf: Option[Class[_]] = Option(_intf) - val dispatcher: Option[MessageDispatcher] = Option(_dispatcher) - val remoteAddress: Option[RemoteAddress] = Option(_remoteAddress) - - def this(target: Class[_], lifeCycle: LifeCycle, timeout: Long) = - this(null: Class[_], target, lifeCycle, timeout, null: MessageDispatcher, null: RemoteAddress) - - def this(intf: Class[_], target: Class[_], lifeCycle: LifeCycle, timeout: Long) = - this(intf, target, lifeCycle, timeout, null: MessageDispatcher, null: RemoteAddress) - - def this(intf: Class[_], target: Class[_], lifeCycle: LifeCycle, timeout: Long, dispatcher: MessageDispatcher) = - this(intf, target, lifeCycle, timeout, dispatcher, null: RemoteAddress) - - def this(target: Class[_], lifeCycle: LifeCycle, timeout: Long, dispatcher: MessageDispatcher) = - this(null: Class[_], target, lifeCycle, timeout, dispatcher, null: RemoteAddress) - - def this(intf: Class[_], target: Class[_], lifeCycle: LifeCycle, timeout: Long, remoteAddress: RemoteAddress) = - this(intf, target, lifeCycle, timeout, null: MessageDispatcher, remoteAddress) - - def this(target: Class[_], lifeCycle: LifeCycle, timeout: Long, remoteAddress: RemoteAddress) = - this(null: Class[_], target, lifeCycle, timeout, null: MessageDispatcher, remoteAddress) - - def this(target: Class[_], lifeCycle: LifeCycle, timeout: Long, dispatcher: MessageDispatcher, remoteAddress: RemoteAddress) = - this(null: Class[_], target, lifeCycle, timeout, dispatcher, remoteAddress) - } -} diff --git a/test/files/presentation/akka/src/akka/dataflow/DataFlow.scala b/test/files/presentation/akka/src/akka/dataflow/DataFlow.scala deleted file mode 100644 index bca7936116..0000000000 --- a/test/files/presentation/akka/src/akka/dataflow/DataFlow.scala +++ /dev/null @@ -1,165 +0,0 @@ -/** - * Copyright (C) 2009-2011 Scalable Solutions AB - */ - -package akka.dataflow - -import java.util.concurrent.atomic.AtomicReference -import java.util.concurrent.{ ConcurrentLinkedQueue, LinkedBlockingQueue } - -import akka.event.EventHandler -import akka.actor.{ Actor, ActorRef } -import akka.actor.Actor._ -import akka.dispatch.CompletableFuture -import akka.AkkaException -import akka.japi.{ Function, Effect } - -/** - * Implements Oz-style dataflow (single assignment) variables. - * - * @author Jonas Bonér - */ -object DataFlow { - object Start - object Exit - - class DataFlowVariableException(message: String, cause: Throwable = null) extends AkkaException(message, cause) - - /** - * Executes the supplied thunk in another thread. - */ - def thread(body: => Unit): Unit = spawn(body) - - /** - * JavaAPI. - * Executes the supplied Effect in another thread. - */ - def thread(body: Effect): Unit = spawn(body.apply) - - /** - * Executes the supplied function in another thread. - */ - def thread[A <: AnyRef, R <: AnyRef](body: A => R) = - actorOf(new ReactiveEventBasedThread(body)).start() - - /** - * JavaAPI. - * Executes the supplied Function in another thread. - */ - def thread[A <: AnyRef, R <: AnyRef](body: Function[A, R]) = - actorOf(new ReactiveEventBasedThread(body.apply)).start() - - private class ReactiveEventBasedThread[A <: AnyRef, T <: AnyRef](body: A => T) - extends Actor { - def receive = { - case Exit => self.stop() - case message => self.reply(body(message.asInstanceOf[A])) - } - } - - private object DataFlowVariable { - private sealed abstract class DataFlowVariableMessage - private case class Set[T <: Any](value: T) extends DataFlowVariableMessage - private object Get extends DataFlowVariableMessage - } - - /** - * @author Jonas Bonér - */ - @deprecated("Superceeded by Future and CompletableFuture as of 1.1", "1.1") - sealed class DataFlowVariable[T <: Any](timeoutMs: Long) { - import DataFlowVariable._ - - def this() = this(1000 * 60) - - private val value = new AtomicReference[Option[T]](None) - private val blockedReaders = new ConcurrentLinkedQueue[ActorRef] - - private class In[T <: Any](dataFlow: DataFlowVariable[T]) extends Actor { - self.timeout = timeoutMs - def receive = { - case s@Set(v) => - if (dataFlow.value.compareAndSet(None, Some(v.asInstanceOf[T]))) { - while (dataFlow.blockedReaders.peek ne null) - dataFlow.blockedReaders.poll ! s - } else throw new DataFlowVariableException( - "Attempt to change data flow variable (from [" + dataFlow.value.get + "] to [" + v + "])") - case Exit => self.stop() - } - } - - private class Out[T <: Any](dataFlow: DataFlowVariable[T]) extends Actor { - self.timeout = timeoutMs - private var readerFuture: Option[CompletableFuture[Any]] = None - def receive = { - case Get => dataFlow.value.get match { - case Some(value) => self reply value - case None => readerFuture = self.senderFuture - } - case Set(v: T) => readerFuture.map(_ completeWithResult v) - case Exit => self.stop() - } - } - - private[this] val in = actorOf(new In(this)).start() - - /** - * Sets the value of this variable (if unset) with the value of the supplied variable. - */ - def <<(ref: DataFlowVariable[T]) { - if (this.value.get.isEmpty) in ! Set(ref()) - else throw new DataFlowVariableException( - "Attempt to change data flow variable (from [" + this.value.get + "] to [" + ref() + "])") - } - - /** - * JavaAPI. - * Sets the value of this variable (if unset) with the value of the supplied variable. - */ - def set(ref: DataFlowVariable[T]) { this << ref } - - /** - * Sets the value of this variable (if unset). - */ - def <<(value: T) { - if (this.value.get.isEmpty) in ! Set(value) - else throw new DataFlowVariableException( - "Attempt to change data flow variable (from [" + this.value.get + "] to [" + value + "])") - } - - /** - * JavaAPI. - * Sets the value of this variable (if unset) with the value of the supplied variable. - */ - def set(value: T) { this << value } - - /** - * Retrieves the value of variable, throws a DataFlowVariableException if it times out. - */ - def get(): T = this() - - /** - * Retrieves the value of variable, throws a DataFlowVariableException if it times out. - */ - def apply(): T = { - value.get getOrElse { - val out = actorOf(new Out(this)).start() - - val result = try { - blockedReaders offer out - (out !! Get).as[T] - } catch { - case e: Exception => - EventHandler.error(e, this, e.getMessage) - out ! Exit - throw e - } - - result.getOrElse(throw new DataFlowVariableException( - "Timed out (after " + timeoutMs + " milliseconds) while waiting for result")) - } - } - - def shutdown() { in ! Exit } - } -} diff --git a/test/files/presentation/akka/src/akka/dispatch/Dispatchers.scala b/test/files/presentation/akka/src/akka/dispatch/Dispatchers.scala deleted file mode 100644 index 7dd1bf6218..0000000000 --- a/test/files/presentation/akka/src/akka/dispatch/Dispatchers.scala +++ /dev/null @@ -1,227 +0,0 @@ -/** - * Copyright (C) 2009-2011 Scalable Solutions AB - */ - -package akka.dispatch - -import akka.actor.{ Actor, ActorRef } -import akka.actor.newUuid -import akka.config.Config._ -import akka.util.{ Duration, ReflectiveAccess } - -import akka.config.Configuration - -import java.util.concurrent.TimeUnit - -/** - * Scala API. Dispatcher factory. - *

          - * Example usage: - *

          - *   val dispatcher = Dispatchers.newExecutorBasedEventDrivenDispatcher("name")
          - *   dispatcher
          - *     .withNewThreadPoolWithLinkedBlockingQueueWithCapacity(100)
          - *     .setCorePoolSize(16)
          - *     .setMaxPoolSize(128)
          - *     .setKeepAliveTimeInMillis(60000)
          - *     .setRejectionPolicy(new CallerRunsPolicy)
          - *     .build
          - * 
          - *

          - * Java API. Dispatcher factory. - *

          - * Example usage: - *

          - *   MessageDispatcher dispatcher = Dispatchers.newExecutorBasedEventDrivenDispatcher("name");
          - *   dispatcher
          - *     .withNewThreadPoolWithLinkedBlockingQueueWithCapacity(100)
          - *     .setCorePoolSize(16)
          - *     .setMaxPoolSize(128)
          - *     .setKeepAliveTimeInMillis(60000)
          - *     .setRejectionPolicy(new CallerRunsPolicy())
          - *     .build();
          - * 
          - *

          - * - * @author Jonas Bonér - */ -object Dispatchers { - val THROUGHPUT = config.getInt("akka.actor.throughput", 5) - val DEFAULT_SHUTDOWN_TIMEOUT = config.getLong("akka.actor.dispatcher-shutdown-timeout"). - map(time => Duration(time, TIME_UNIT)). - getOrElse(Duration(1000, TimeUnit.MILLISECONDS)) - val MAILBOX_CAPACITY = config.getInt("akka.actor.default-dispatcher.mailbox-capacity", -1) - val MAILBOX_PUSH_TIME_OUT = Duration(config.getInt("akka.actor.default-dispatcher.mailbox-push-timeout-time", 10), TIME_UNIT) - val THROUGHPUT_DEADLINE_TIME = Duration(config.getInt("akka.actor.throughput-deadline-time", -1), TIME_UNIT) - val THROUGHPUT_DEADLINE_TIME_MILLIS = THROUGHPUT_DEADLINE_TIME.toMillis.toInt - val MAILBOX_TYPE: MailboxType = if (MAILBOX_CAPACITY < 1) UnboundedMailbox() else BoundedMailbox() - - lazy val defaultGlobalDispatcher = { - config.getSection("akka.actor.default-dispatcher").flatMap(from).getOrElse(globalExecutorBasedEventDrivenDispatcher) - } - - object globalExecutorBasedEventDrivenDispatcher extends ExecutorBasedEventDrivenDispatcher("global", THROUGHPUT, THROUGHPUT_DEADLINE_TIME_MILLIS, MAILBOX_TYPE) - - /** - * Creates an thread based dispatcher serving a single actor through the same single thread. - * Uses the default timeout - *

          - * E.g. each actor consumes its own thread. - */ - def newThreadBasedDispatcher(actor: ActorRef) = new ThreadBasedDispatcher(actor) - - /** - * Creates an thread based dispatcher serving a single actor through the same single thread. - * Uses the default timeout - * If capacity is negative, it's Integer.MAX_VALUE - *

          - * E.g. each actor consumes its own thread. - */ - def newThreadBasedDispatcher(actor: ActorRef, mailboxCapacity: Int) = new ThreadBasedDispatcher(actor, mailboxCapacity) - - /** - * Creates an thread based dispatcher serving a single actor through the same single thread. - * If capacity is negative, it's Integer.MAX_VALUE - *

          - * E.g. each actor consumes its own thread. - */ - def newThreadBasedDispatcher(actor: ActorRef, mailboxCapacity: Int, pushTimeOut: Duration) = - new ThreadBasedDispatcher(actor, mailboxCapacity, pushTimeOut) - - /** - * Creates a executor-based event-driven dispatcher serving multiple (millions) of actors through a thread pool. - *

          - * Has a fluent builder interface for configuring its semantics. - */ - def newExecutorBasedEventDrivenDispatcher(name: String) = - ThreadPoolConfigDispatcherBuilder(config => new ExecutorBasedEventDrivenDispatcher(name, config), ThreadPoolConfig()) - - /** - * Creates a executor-based event-driven dispatcher serving multiple (millions) of actors through a thread pool. - *

          - * Has a fluent builder interface for configuring its semantics. - */ - def newExecutorBasedEventDrivenDispatcher(name: String, throughput: Int, mailboxType: MailboxType) = - ThreadPoolConfigDispatcherBuilder(config => - new ExecutorBasedEventDrivenDispatcher(name, throughput, THROUGHPUT_DEADLINE_TIME_MILLIS, mailboxType, config), ThreadPoolConfig()) - - /** - * Creates a executor-based event-driven dispatcher serving multiple (millions) of actors through a thread pool. - *

          - * Has a fluent builder interface for configuring its semantics. - */ - def newExecutorBasedEventDrivenDispatcher(name: String, throughput: Int, throughputDeadlineMs: Int, mailboxType: MailboxType) = - ThreadPoolConfigDispatcherBuilder(config => - new ExecutorBasedEventDrivenDispatcher(name, throughput, throughputDeadlineMs, mailboxType, config), ThreadPoolConfig()) - - /** - * Creates a executor-based event-driven dispatcher, with work-stealing, serving multiple (millions) of actors through a thread pool. - *

          - * Has a fluent builder interface for configuring its semantics. - */ - def newExecutorBasedEventDrivenWorkStealingDispatcher(name: String) = - ThreadPoolConfigDispatcherBuilder(config => new ExecutorBasedEventDrivenWorkStealingDispatcher(name, config), ThreadPoolConfig()) - - /** - * Creates a executor-based event-driven dispatcher, with work-stealing, serving multiple (millions) of actors through a thread pool. - *

          - * Has a fluent builder interface for configuring its semantics. - */ - def newExecutorBasedEventDrivenWorkStealingDispatcher(name: String, throughput: Int) = - ThreadPoolConfigDispatcherBuilder(config => - new ExecutorBasedEventDrivenWorkStealingDispatcher(name, throughput, THROUGHPUT_DEADLINE_TIME_MILLIS, MAILBOX_TYPE, config), ThreadPoolConfig()) - - /** - * Creates a executor-based event-driven dispatcher, with work-stealing, serving multiple (millions) of actors through a thread pool. - *

          - * Has a fluent builder interface for configuring its semantics. - */ - def newExecutorBasedEventDrivenWorkStealingDispatcher(name: String, throughput: Int, mailboxType: MailboxType) = - ThreadPoolConfigDispatcherBuilder(config => - new ExecutorBasedEventDrivenWorkStealingDispatcher(name, throughput, THROUGHPUT_DEADLINE_TIME_MILLIS, mailboxType, config), ThreadPoolConfig()) - - /** - * Creates a executor-based event-driven dispatcher, with work-stealing, serving multiple (millions) of actors through a thread pool. - *

          - * Has a fluent builder interface for configuring its semantics. - */ - def newExecutorBasedEventDrivenWorkStealingDispatcher(name: String, throughput: Int, throughputDeadlineMs: Int, mailboxType: MailboxType) = - ThreadPoolConfigDispatcherBuilder(config => - new ExecutorBasedEventDrivenWorkStealingDispatcher(name, throughput, throughputDeadlineMs, mailboxType, config), ThreadPoolConfig()) - /** - * Utility function that tries to load the specified dispatcher config from the akka.conf - * or else use the supplied default dispatcher - */ - def fromConfig(key: String, default: => MessageDispatcher = defaultGlobalDispatcher): MessageDispatcher = - config getSection key flatMap from getOrElse default - - /* - * Creates of obtains a dispatcher from a ConfigMap according to the format below - * - * default-dispatcher { - * type = "GlobalExecutorBasedEventDriven" # Must be one of the following, all "Global*" are non-configurable - * # (ExecutorBasedEventDrivenWorkStealing), ExecutorBasedEventDriven, - * # GlobalExecutorBasedEventDriven - * # A FQCN to a class inheriting MessageDispatcherConfigurator with a no-arg visible constructor - * keep-alive-time = 60 # Keep alive time for threads - * core-pool-size-factor = 1.0 # No of core threads ... ceil(available processors * factor) - * max-pool-size-factor = 4.0 # Max no of threads ... ceil(available processors * factor) - * executor-bounds = -1 # Makes the Executor bounded, -1 is unbounded - * allow-core-timeout = on # Allow core threads to time out - * rejection-policy = "caller-runs" # abort, caller-runs, discard-oldest, discard - * throughput = 5 # Throughput for ExecutorBasedEventDrivenDispatcher - * } - * ex: from(config.getConfigMap(identifier).get) - * - * Gotcha: Only configures the dispatcher if possible - * Returns: None if "type" isn't specified in the config - * Throws: IllegalArgumentException if the value of "type" is not valid - * IllegalArgumentException if it cannot - */ - def from(cfg: Configuration): Option[MessageDispatcher] = { - cfg.getString("type") map { - case "ExecutorBasedEventDriven" => new ExecutorBasedEventDrivenDispatcherConfigurator() - case "ExecutorBasedEventDrivenWorkStealing" => new ExecutorBasedEventDrivenWorkStealingDispatcherConfigurator() - case "GlobalExecutorBasedEventDriven" => GlobalExecutorBasedEventDrivenDispatcherConfigurator - case fqn => - ReflectiveAccess.getClassFor[MessageDispatcherConfigurator](fqn) match { - case r: Right[_, Class[MessageDispatcherConfigurator]] => - ReflectiveAccess.createInstance[MessageDispatcherConfigurator](r.b, Array[Class[_]](), Array[AnyRef]()) match { - case r: Right[Exception, MessageDispatcherConfigurator] => r.b - case l: Left[Exception, MessageDispatcherConfigurator] => - throw new IllegalArgumentException("Cannot instantiate MessageDispatcherConfigurator type [%s], make sure it has a default no-args constructor" format fqn, l.a) - } - case l: Left[Exception, _] => - throw new IllegalArgumentException("Unknown MessageDispatcherConfigurator type [%s]" format fqn, l.a) - } - } map { - _ configure cfg - } - } -} - -object GlobalExecutorBasedEventDrivenDispatcherConfigurator extends MessageDispatcherConfigurator { - def configure(config: Configuration): MessageDispatcher = Dispatchers.globalExecutorBasedEventDrivenDispatcher -} - -class ExecutorBasedEventDrivenDispatcherConfigurator extends MessageDispatcherConfigurator { - def configure(config: Configuration): MessageDispatcher = { - configureThreadPool(config, threadPoolConfig => new ExecutorBasedEventDrivenDispatcher( - config.getString("name", newUuid.toString), - config.getInt("throughput", Dispatchers.THROUGHPUT), - config.getInt("throughput-deadline-time", Dispatchers.THROUGHPUT_DEADLINE_TIME_MILLIS), - mailboxType(config), - threadPoolConfig)).build - } -} - -class ExecutorBasedEventDrivenWorkStealingDispatcherConfigurator extends MessageDispatcherConfigurator { - def configure(config: Configuration): MessageDispatcher = { - configureThreadPool(config, threadPoolConfig => new ExecutorBasedEventDrivenWorkStealingDispatcher( - config.getString("name", newUuid.toString), - config.getInt("throughput", Dispatchers.THROUGHPUT), - config.getInt("throughput-deadline-time", Dispatchers.THROUGHPUT_DEADLINE_TIME_MILLIS), - mailboxType(config), - threadPoolConfig)).build - } -} \ No newline at end of file diff --git a/test/files/presentation/akka/src/akka/dispatch/ExecutorBasedEventDrivenDispatcher.scala b/test/files/presentation/akka/src/akka/dispatch/ExecutorBasedEventDrivenDispatcher.scala deleted file mode 100644 index bc3f29ac68..0000000000 --- a/test/files/presentation/akka/src/akka/dispatch/ExecutorBasedEventDrivenDispatcher.scala +++ /dev/null @@ -1,305 +0,0 @@ -/** - * Copyright (C) 2009-2011 Scalable Solutions AB - */ - -package akka.dispatch - -import akka.event.EventHandler -import akka.actor.{ ActorRef, IllegalActorStateException } -import akka.util.{ ReflectiveAccess, Switch } - -import java.util.Queue -import java.util.concurrent.atomic.AtomicReference -import java.util.concurrent.{ TimeUnit, ExecutorService, RejectedExecutionException, ConcurrentLinkedQueue, LinkedBlockingQueue } - -/** - * Default settings are: - *

          - *   - withNewThreadPoolWithLinkedBlockingQueueWithUnboundedCapacity
          - *   - NR_START_THREADS = 16
          - *   - NR_MAX_THREADS = 128
          - *   - KEEP_ALIVE_TIME = 60000L // one minute
          - * 
          - *

          - * - * The dispatcher has a fluent builder interface to build up a thread pool to suite your use-case. - * There is a default thread pool defined but make use of the builder if you need it. Here are some examples. - *

          - * - * Scala API. - *

          - * Example usage: - *

          - *   val dispatcher = new ExecutorBasedEventDrivenDispatcher("name")
          - *   dispatcher
          - *     .withNewThreadPoolWithBoundedBlockingQueue(100)
          - *     .setCorePoolSize(16)
          - *     .setMaxPoolSize(128)
          - *     .setKeepAliveTimeInMillis(60000)
          - *     .setRejectionPolicy(new CallerRunsPolicy)
          - *     .buildThreadPool
          - * 
          - *

          - * - * Java API. - *

          - * Example usage: - *

          - *   ExecutorBasedEventDrivenDispatcher dispatcher = new ExecutorBasedEventDrivenDispatcher("name");
          - *   dispatcher
          - *     .withNewThreadPoolWithBoundedBlockingQueue(100)
          - *     .setCorePoolSize(16)
          - *     .setMaxPoolSize(128)
          - *     .setKeepAliveTimeInMillis(60000)
          - *     .setRejectionPolicy(new CallerRunsPolicy())
          - *     .buildThreadPool();
          - * 
          - *

          - * - * But the preferred way of creating dispatchers is to use - * the {@link akka.dispatch.Dispatchers} factory object. - * - * @author Jonas Bonér - * @param throughput positive integer indicates the dispatcher will only process so much messages at a time from the - * mailbox, without checking the mailboxes of other actors. Zero or negative means the dispatcher - * always continues until the mailbox is empty. - * Larger values (or zero or negative) increase throughput, smaller values increase fairness - */ -class ExecutorBasedEventDrivenDispatcher( - _name: String, - val throughput: Int = Dispatchers.THROUGHPUT, - val throughputDeadlineTime: Int = Dispatchers.THROUGHPUT_DEADLINE_TIME_MILLIS, - val mailboxType: MailboxType = Dispatchers.MAILBOX_TYPE, - val config: ThreadPoolConfig = ThreadPoolConfig()) - extends MessageDispatcher { - - def this(_name: String, throughput: Int, throughputDeadlineTime: Int, mailboxType: MailboxType) = - this(_name, throughput, throughputDeadlineTime, mailboxType, ThreadPoolConfig()) // Needed for Java API usage - - def this(_name: String, throughput: Int, mailboxType: MailboxType) = - this(_name, throughput, Dispatchers.THROUGHPUT_DEADLINE_TIME_MILLIS, mailboxType) // Needed for Java API usage - - def this(_name: String, throughput: Int) = - this(_name, throughput, Dispatchers.THROUGHPUT_DEADLINE_TIME_MILLIS, Dispatchers.MAILBOX_TYPE) // Needed for Java API usage - - def this(_name: String, _config: ThreadPoolConfig) = - this(_name, Dispatchers.THROUGHPUT, Dispatchers.THROUGHPUT_DEADLINE_TIME_MILLIS, Dispatchers.MAILBOX_TYPE, _config) - - def this(_name: String) = - this(_name, Dispatchers.THROUGHPUT, Dispatchers.THROUGHPUT_DEADLINE_TIME_MILLIS, Dispatchers.MAILBOX_TYPE) // Needed for Java API usage - - val name = "akka:event-driven:dispatcher:" + _name - - private[akka] val threadFactory = new MonitorableThreadFactory(name) - private[akka] val executorService = new AtomicReference[ExecutorService](config.createLazyExecutorService(threadFactory)) - - private[akka] def dispatch(invocation: MessageInvocation) = { - val mbox = getMailbox(invocation.receiver) - mbox enqueue invocation - registerForExecution(mbox) - } - - private[akka] def executeFuture(invocation: FutureInvocation[_]): Unit = if (active.isOn) { - try executorService.get() execute invocation - catch { - case e: RejectedExecutionException => - EventHandler.warning(this, e.toString) - throw e - } - } - - /** - * @return the mailbox associated with the actor - */ - protected def getMailbox(receiver: ActorRef) = receiver.mailbox.asInstanceOf[MessageQueue with ExecutableMailbox] - - override def mailboxSize(actorRef: ActorRef) = getMailbox(actorRef).size - - def createMailbox(actorRef: ActorRef): AnyRef = mailboxType match { - case b: UnboundedMailbox => - new ConcurrentLinkedQueue[MessageInvocation] with MessageQueue with ExecutableMailbox { - @inline - final def dispatcher = ExecutorBasedEventDrivenDispatcher.this - @inline - final def enqueue(m: MessageInvocation) = this.add(m) - @inline - final def dequeue(): MessageInvocation = this.poll() - } - case b: BoundedMailbox => - new DefaultBoundedMessageQueue(b.capacity, b.pushTimeOut) with ExecutableMailbox { - @inline - final def dispatcher = ExecutorBasedEventDrivenDispatcher.this - } - } - - private[akka] def start {} - - private[akka] def shutdown { - val old = executorService.getAndSet(config.createLazyExecutorService(threadFactory)) - if (old ne null) { - old.shutdownNow() - } - } - - private[akka] def registerForExecution(mbox: MessageQueue with ExecutableMailbox): Unit = { - if (mbox.dispatcherLock.tryLock()) { - if (active.isOn && !mbox.suspended.locked) { //If the dispatcher is active and the actor not suspended - try { - executorService.get() execute mbox - } catch { - case e: RejectedExecutionException => - EventHandler.warning(this, e.toString) - mbox.dispatcherLock.unlock() - throw e - } - } else { - mbox.dispatcherLock.unlock() //If the dispatcher isn't active or if the actor is suspended, unlock the dispatcher lock - } - } - } - - private[akka] def reRegisterForExecution(mbox: MessageQueue with ExecutableMailbox): Unit = - registerForExecution(mbox) - - override val toString = getClass.getSimpleName + "[" + name + "]" - - def suspend(actorRef: ActorRef) { - getMailbox(actorRef).suspended.tryLock - } - - def resume(actorRef: ActorRef) { - val mbox = getMailbox(actorRef) - mbox.suspended.tryUnlock - reRegisterForExecution(mbox) - } -} - -/** - * This is the behavior of an ExecutorBasedEventDrivenDispatchers mailbox. - */ -trait ExecutableMailbox extends Runnable { self: MessageQueue => - - def dispatcher: ExecutorBasedEventDrivenDispatcher - - final def run = { - try { - processMailbox() - } catch { - case ie: InterruptedException => - } - finally { - dispatcherLock.unlock() - } - if (!self.isEmpty) - dispatcher.reRegisterForExecution(this) - } - - /** - * Process the messages in the mailbox - * - * @return true if the processing finished before the mailbox was empty, due to the throughput constraint - */ - final def processMailbox() { - if (!self.suspended.locked) { - var nextMessage = self.dequeue - if (nextMessage ne null) { //If we have a message - if (dispatcher.throughput <= 1) //If we only run one message per process - nextMessage.invoke //Just run it - else { //But otherwise, if we are throttled, we need to do some book-keeping - var processedMessages = 0 - val isDeadlineEnabled = dispatcher.throughputDeadlineTime > 0 - val deadlineNs = if (isDeadlineEnabled) System.nanoTime + TimeUnit.MILLISECONDS.toNanos(dispatcher.throughputDeadlineTime) - else 0 - do { - nextMessage.invoke - nextMessage = - if (self.suspended.locked) { - null // If we are suspended, abort - } else { // If we aren't suspended, we need to make sure we're not overstepping our boundaries - processedMessages += 1 - if ((processedMessages >= dispatcher.throughput) || (isDeadlineEnabled && System.nanoTime >= deadlineNs)) // If we're throttled, break out - null //We reached our boundaries, abort - else self.dequeue //Dequeue the next message - } - } while (nextMessage ne null) - } - } - } - } -} - -object PriorityGenerator { - /** - * Creates a PriorityGenerator that uses the supplied function as priority generator - */ - def apply(priorityFunction: Any => Int): PriorityGenerator = new PriorityGenerator { - def gen(message: Any): Int = priorityFunction(message) - } -} - -/** - * A PriorityGenerator is a convenience API to create a Comparator that orders the messages of a - * PriorityExecutorBasedEventDrivenDispatcher - */ -abstract class PriorityGenerator extends java.util.Comparator[MessageInvocation] { - def gen(message: Any): Int - - final def compare(thisMessage: MessageInvocation, thatMessage: MessageInvocation): Int = - gen(thisMessage.message) - gen(thatMessage.message) -} - -/** - * A version of ExecutorBasedEventDrivenDispatcher that gives all actors registered to it a priority mailbox, - * prioritized according to the supplied comparator. - * - * The dispatcher will process the messages with the _lowest_ priority first. - */ -class PriorityExecutorBasedEventDrivenDispatcher( - name: String, - val comparator: java.util.Comparator[MessageInvocation], - throughput: Int = Dispatchers.THROUGHPUT, - throughputDeadlineTime: Int = Dispatchers.THROUGHPUT_DEADLINE_TIME_MILLIS, - mailboxType: MailboxType = Dispatchers.MAILBOX_TYPE, - config: ThreadPoolConfig = ThreadPoolConfig()) extends ExecutorBasedEventDrivenDispatcher(name, throughput, throughputDeadlineTime, mailboxType, config) with PriorityMailbox { - - def this(name: String, comparator: java.util.Comparator[MessageInvocation], throughput: Int, throughputDeadlineTime: Int, mailboxType: MailboxType) = - this(name, comparator, throughput, throughputDeadlineTime, mailboxType, ThreadPoolConfig()) // Needed for Java API usage - - def this(name: String, comparator: java.util.Comparator[MessageInvocation], throughput: Int, mailboxType: MailboxType) = - this(name, comparator, throughput, Dispatchers.THROUGHPUT_DEADLINE_TIME_MILLIS, mailboxType) // Needed for Java API usage - - def this(name: String, comparator: java.util.Comparator[MessageInvocation], throughput: Int) = - this(name, comparator, throughput, Dispatchers.THROUGHPUT_DEADLINE_TIME_MILLIS, Dispatchers.MAILBOX_TYPE) // Needed for Java API usage - - def this(name: String, comparator: java.util.Comparator[MessageInvocation], config: ThreadPoolConfig) = - this(name, comparator, Dispatchers.THROUGHPUT, Dispatchers.THROUGHPUT_DEADLINE_TIME_MILLIS, Dispatchers.MAILBOX_TYPE, config) - - def this(name: String, comparator: java.util.Comparator[MessageInvocation]) = - this(name, comparator, Dispatchers.THROUGHPUT, Dispatchers.THROUGHPUT_DEADLINE_TIME_MILLIS, Dispatchers.MAILBOX_TYPE) // Needed for Java API usage -} - -/** - * Can be used to give an ExecutorBasedEventDrivenDispatcher's actors priority-enabled mailboxes - * - * Usage: - * new ExecutorBasedEventDrivenDispatcher(...) with PriorityMailbox { - * val comparator = ...comparator that determines mailbox priority ordering... - * } - */ -trait PriorityMailbox { self: ExecutorBasedEventDrivenDispatcher => - def comparator: java.util.Comparator[MessageInvocation] - - override def createMailbox(actorRef: ActorRef): AnyRef = self.mailboxType match { - case b: UnboundedMailbox => - new UnboundedPriorityMessageQueue(comparator) with ExecutableMailbox { - @inline - final def dispatcher = self - } - - case b: BoundedMailbox => - new BoundedPriorityMessageQueue(b.capacity, b.pushTimeOut, comparator) with ExecutableMailbox { - @inline - final def dispatcher = self - } - } -} diff --git a/test/files/presentation/akka/src/akka/dispatch/ExecutorBasedEventDrivenWorkStealingDispatcher.scala b/test/files/presentation/akka/src/akka/dispatch/ExecutorBasedEventDrivenWorkStealingDispatcher.scala deleted file mode 100644 index 4cba8eec8b..0000000000 --- a/test/files/presentation/akka/src/akka/dispatch/ExecutorBasedEventDrivenWorkStealingDispatcher.scala +++ /dev/null @@ -1,165 +0,0 @@ -/** - * Copyright (C) 2009-2011 Scalable Solutions AB - */ - -package akka.dispatch - -import akka.actor.{ ActorRef, Actor, IllegalActorStateException } -import akka.util.{ ReflectiveAccess, Switch } - -import java.util.Queue -import java.util.concurrent.atomic.{ AtomicReference, AtomicInteger } -import java.util.concurrent.{ TimeUnit, ExecutorService, RejectedExecutionException, ConcurrentLinkedQueue, LinkedBlockingQueue } -import util.DynamicVariable - -/** - * An executor based event driven dispatcher which will try to redistribute work from busy actors to idle actors. It is assumed - * that all actors using the same instance of this dispatcher can process all messages that have been sent to one of the actors. I.e. the - * actors belong to a pool of actors, and to the client there is no guarantee about which actor instance actually processes a given message. - *

          - * Although the technique used in this implementation is commonly known as "work stealing", the actual implementation is probably - * best described as "work donating" because the actor of which work is being stolen takes the initiative. - *

          - * The preferred way of creating dispatchers is to use - * the {@link akka.dispatch.Dispatchers} factory object. - * - * @see akka.dispatch.ExecutorBasedEventDrivenWorkStealingDispatcher - * @see akka.dispatch.Dispatchers - * - * @author Viktor Klang - */ -class ExecutorBasedEventDrivenWorkStealingDispatcher( - _name: String, - throughput: Int = Dispatchers.THROUGHPUT, - throughputDeadlineTime: Int = Dispatchers.THROUGHPUT_DEADLINE_TIME_MILLIS, - mailboxType: MailboxType = Dispatchers.MAILBOX_TYPE, - config: ThreadPoolConfig = ThreadPoolConfig()) - extends ExecutorBasedEventDrivenDispatcher(_name, throughput, throughputDeadlineTime, mailboxType, config) { - - def this(_name: String, throughput: Int, throughputDeadlineTime: Int, mailboxType: MailboxType) = - this(_name, throughput, throughputDeadlineTime, mailboxType, ThreadPoolConfig()) // Needed for Java API usage - - def this(_name: String, throughput: Int, mailboxType: MailboxType) = - this(_name, throughput, Dispatchers.THROUGHPUT_DEADLINE_TIME_MILLIS, mailboxType) // Needed for Java API usage - - def this(_name: String, throughput: Int) = - this(_name, throughput, Dispatchers.THROUGHPUT_DEADLINE_TIME_MILLIS, Dispatchers.MAILBOX_TYPE) // Needed for Java API usage - - def this(_name: String, _config: ThreadPoolConfig) = - this(_name, Dispatchers.THROUGHPUT, Dispatchers.THROUGHPUT_DEADLINE_TIME_MILLIS, Dispatchers.MAILBOX_TYPE, _config) - - def this(_name: String, memberType: Class[_ <: Actor]) = - this(_name, Dispatchers.THROUGHPUT, Dispatchers.THROUGHPUT_DEADLINE_TIME_MILLIS, Dispatchers.MAILBOX_TYPE) // Needed for Java API usage - - def this(_name: String, mailboxType: MailboxType) = - this(_name, Dispatchers.THROUGHPUT, Dispatchers.THROUGHPUT_DEADLINE_TIME_MILLIS, mailboxType) // Needed for Java API usage - - @volatile - private var actorType: Option[Class[_]] = None - @volatile - private var members = Vector[ActorRef]() - private val donationInProgress = new DynamicVariable(false) - - private[akka] override def register(actorRef: ActorRef) = { - //Verify actor type conformity - actorType match { - case None => actorType = Some(actorRef.actor.getClass) - case Some(aType) => - if (aType != actorRef.actor.getClass) - throw new IllegalActorStateException(String.format( - "Can't register actor %s in a work stealing dispatcher which already knows actors of type %s", - actorRef, aType)) - } - - synchronized { members :+= actorRef } //Update members - super.register(actorRef) - } - - private[akka] override def unregister(actorRef: ActorRef) = { - synchronized { members = members.filterNot(actorRef eq) } //Update members - super.unregister(actorRef) - } - - override private[akka] def dispatch(invocation: MessageInvocation) = { - val mbox = getMailbox(invocation.receiver) - if (donationInProgress.value == false && (!mbox.isEmpty || mbox.dispatcherLock.locked) && attemptDonationOf(invocation, mbox)) { - //We were busy and we got to donate the message to some other lucky guy, we're done here - } else { - mbox enqueue invocation - registerForExecution(mbox) - } - } - - override private[akka] def reRegisterForExecution(mbox: MessageQueue with ExecutableMailbox): Unit = { - try { - donationInProgress.value = true - while (donateFrom(mbox)) {} //When we reregister, first donate messages to another actor - } finally { donationInProgress.value = false } - - if (!mbox.isEmpty) //If we still have messages left to process, reschedule for execution - super.reRegisterForExecution(mbox) - } - - /** - * Returns true if it successfully donated a message - */ - protected def donateFrom(donorMbox: MessageQueue with ExecutableMailbox): Boolean = { - val actors = members // copy to prevent concurrent modifications having any impact - - // we risk to pick a thief which is unregistered from the dispatcher in the meantime, but that typically means - // the dispatcher is being shut down... - // Starts at is seeded by current time - doFindDonorRecipient(donorMbox, actors, (System.currentTimeMillis % actors.size).asInstanceOf[Int]) match { - case null => false - case recipient => donate(donorMbox.dequeue, recipient) - } - } - - /** - * Returns true if the donation succeeded or false otherwise - */ - protected def attemptDonationOf(message: MessageInvocation, donorMbox: MessageQueue with ExecutableMailbox): Boolean = try { - donationInProgress.value = true - val actors = members // copy to prevent concurrent modifications having any impact - doFindDonorRecipient(donorMbox, actors, System.identityHashCode(message) % actors.size) match { - case null => false - case recipient => donate(message, recipient) - } - } finally { donationInProgress.value = false } - - /** - * Rewrites the message and adds that message to the recipients mailbox - * returns true if the message is non-null - */ - protected def donate(organ: MessageInvocation, recipient: ActorRef): Boolean = { - if (organ ne null) { - if (organ.senderFuture.isDefined) recipient.postMessageToMailboxAndCreateFutureResultWithTimeout[Any]( - organ.message, recipient.timeout, organ.sender, organ.senderFuture) - else if (organ.sender.isDefined) recipient.postMessageToMailbox(organ.message, organ.sender) - else recipient.postMessageToMailbox(organ.message, None) - true - } else false - } - - /** - * Returns an available recipient for the message, if any - */ - protected def doFindDonorRecipient(donorMbox: MessageQueue with ExecutableMailbox, potentialRecipients: Vector[ActorRef], startIndex: Int): ActorRef = { - val prSz = potentialRecipients.size - var i = 0 - var recipient: ActorRef = null - - while ((i < prSz) && (recipient eq null)) { - val actor = potentialRecipients((i + startIndex) % prSz) //Wrap-around, one full lap - val mbox = getMailbox(actor) - - if ((mbox ne donorMbox) && mbox.isEmpty) { //Don't donate to yourself - recipient = actor //Found! - } - - i += 1 - } - - recipient // nothing found, reuse same start index next time - } -} diff --git a/test/files/presentation/akka/src/akka/dispatch/Future.scala b/test/files/presentation/akka/src/akka/dispatch/Future.scala deleted file mode 100644 index 1ad304d726..0000000000 --- a/test/files/presentation/akka/src/akka/dispatch/Future.scala +++ /dev/null @@ -1,832 +0,0 @@ -/** - * Copyright (C) 2009-2011 Scalable Solutions AB - */ - -package akka.dispatch - -import akka.AkkaException -import akka.event.EventHandler -import akka.actor.{ Actor, Channel } -import akka.util.Duration -import akka.japi.{ Procedure, Function => JFunc } - -import scala.util.continuations._ - -import java.util.concurrent.locks.ReentrantLock -import java.util.concurrent.{ ConcurrentLinkedQueue, TimeUnit, Callable } -import java.util.concurrent.TimeUnit.{ NANOSECONDS => NANOS, MILLISECONDS => MILLIS } -import java.util.concurrent.atomic.{ AtomicBoolean } -import java.lang.{ Iterable => JIterable } -import java.util.{ LinkedList => JLinkedList } -import scala.collection.mutable.Stack -import annotation.tailrec - -class FutureTimeoutException(message: String, cause: Throwable = null) extends AkkaException(message, cause) - -object Futures { - - /** - * Java API, equivalent to Future.apply - */ - def future[T](body: Callable[T]): Future[T] = - Future(body.call) - - /** - * Java API, equivalent to Future.apply - */ - def future[T](body: Callable[T], timeout: Long): Future[T] = - Future(body.call, timeout) - - /** - * Java API, equivalent to Future.apply - */ - def future[T](body: Callable[T], dispatcher: MessageDispatcher): Future[T] = - Future(body.call)(dispatcher) - - /** - * Java API, equivalent to Future.apply - */ - def future[T](body: Callable[T], timeout: Long, dispatcher: MessageDispatcher): Future[T] = - Future(body.call, timeout)(dispatcher) - - /** - * Returns a Future to the result of the first future in the list that is completed - */ - def firstCompletedOf[T](futures: Iterable[Future[T]], timeout: Long = Long.MaxValue): Future[T] = { - val futureResult = new DefaultCompletableFuture[T](timeout) - - val completeFirst: Future[T] => Unit = _.value.foreach(futureResult complete _) - for (f ← futures) f onComplete completeFirst - - futureResult - } - - /** - * Java API. - * Returns a Future to the result of the first future in the list that is completed - */ - def firstCompletedOf[T <: AnyRef](futures: java.lang.Iterable[Future[T]], timeout: Long): Future[T] = - firstCompletedOf(scala.collection.JavaConversions.iterableAsScalaIterable(futures), timeout) - - /** - * A non-blocking fold over the specified futures. - * The fold is performed on the thread where the last future is completed, - * the result will be the first failure of any of the futures, or any failure in the actual fold, - * or the result of the fold. - * Example: - *

          -   *   val result = Futures.fold(0)(futures)(_ + _).await.result
          -   * 
          - */ - def fold[T, R](zero: R, timeout: Long = Actor.TIMEOUT)(futures: Iterable[Future[T]])(foldFun: (R, T) => R): Future[R] = { - if (futures.isEmpty) { - new AlreadyCompletedFuture[R](Right(zero)) - } else { - val result = new DefaultCompletableFuture[R](timeout) - val results = new ConcurrentLinkedQueue[T]() - val allDone = futures.size - - val aggregate: Future[T] => Unit = f => if (!result.isCompleted) { //TODO: This is an optimization, is it premature? - f.value.get match { - case r: Right[Throwable, T] => - results add r.b - if (results.size == allDone) { //Only one thread can get here - try { - result completeWithResult scala.collection.JavaConversions.collectionAsScalaIterable(results).foldLeft(zero)(foldFun) - } catch { - case e: Exception => - EventHandler.error(e, this, e.getMessage) - result completeWithException e - } - finally { - results.clear - } - } - case l: Left[Throwable, T] => - result completeWithException l.a - results.clear - } - } - - futures foreach { _ onComplete aggregate } - result - } - } - - /** - * Java API - * A non-blocking fold over the specified futures. - * The fold is performed on the thread where the last future is completed, - * the result will be the first failure of any of the futures, or any failure in the actual fold, - * or the result of the fold. - */ - def fold[T <: AnyRef, R <: AnyRef](zero: R, timeout: Long, futures: java.lang.Iterable[Future[T]], fun: akka.japi.Function2[R, T, R]): Future[R] = - fold(zero, timeout)(scala.collection.JavaConversions.iterableAsScalaIterable(futures))(fun.apply _) - - /** - * Initiates a fold over the supplied futures where the fold-zero is the result value of the Future that's completed first - * Example: - *
          -   *   val result = Futures.reduce(futures)(_ + _).await.result
          -   * 
          - */ - def reduce[T, R >: T](futures: Iterable[Future[T]], timeout: Long = Actor.TIMEOUT)(op: (R, T) => T): Future[R] = { - if (futures.isEmpty) - new AlreadyCompletedFuture[R](Left(new UnsupportedOperationException("empty reduce left"))) - else { - val result = new DefaultCompletableFuture[R](timeout) - val seedFound = new AtomicBoolean(false) - val seedFold: Future[T] => Unit = f => { - if (seedFound.compareAndSet(false, true)) { //Only the first completed should trigger the fold - f.value.get match { - case r: Right[Throwable, T] => - result.completeWith(fold(r.b, timeout)(futures.filterNot(_ eq f))(op)) - case l: Left[Throwable, T] => - result.completeWithException(l.a) - } - } - } - for (f ← futures) f onComplete seedFold //Attach the listener to the Futures - result - } - } - - /** - * Java API. - * Initiates a fold over the supplied futures where the fold-zero is the result value of the Future that's completed first - */ - def reduce[T <: AnyRef, R >: T](futures: java.lang.Iterable[Future[T]], timeout: Long, fun: akka.japi.Function2[R, T, T]): Future[R] = - reduce(scala.collection.JavaConversions.iterableAsScalaIterable(futures), timeout)(fun.apply _) - - /** - * Java API. - * Simple version of Futures.traverse. Transforms a java.lang.Iterable[Future[A]] into a Future[java.util.LinkedList[A]]. - * Useful for reducing many Futures into a single Future. - */ - def sequence[A](in: JIterable[Future[A]], timeout: Long): Future[JLinkedList[A]] = - scala.collection.JavaConversions.iterableAsScalaIterable(in).foldLeft(Future(new JLinkedList[A]()))((fr, fa) => - for (r ← fr; a ← fa) yield { - r add a - r - }) - - /** - * Java API. - * Simple version of Futures.traverse. Transforms a java.lang.Iterable[Future[A]] into a Future[java.util.LinkedList[A]]. - * Useful for reducing many Futures into a single Future. - */ - def sequence[A](in: JIterable[Future[A]]): Future[JLinkedList[A]] = sequence(in, Actor.TIMEOUT) - - /** - * Java API. - * Transforms a java.lang.Iterable[A] into a Future[java.util.LinkedList[B]] using the provided Function A => Future[B]. - * This is useful for performing a parallel map. For example, to apply a function to all items of a list - * in parallel. - */ - def traverse[A, B](in: JIterable[A], timeout: Long, fn: JFunc[A, Future[B]]): Future[JLinkedList[B]] = - scala.collection.JavaConversions.iterableAsScalaIterable(in).foldLeft(Future(new JLinkedList[B]())) { (fr, a) => - val fb = fn(a) - for (r ← fr; b ← fb) yield { - r add b - r - } - } - - /** - * Java API. - * Transforms a java.lang.Iterable[A] into a Future[java.util.LinkedList[B]] using the provided Function A => Future[B]. - * This is useful for performing a parallel map. For example, to apply a function to all items of a list - * in parallel. - */ - def traverse[A, B](in: JIterable[A], fn: JFunc[A, Future[B]]): Future[JLinkedList[B]] = traverse(in, Actor.TIMEOUT, fn) - - // ===================================== - // Deprecations - // ===================================== - - /** - * (Blocking!) - */ - @deprecated("Will be removed after 1.1, if you must block, use: futures.foreach(_.await)", "1.1") - def awaitAll(futures: List[Future[_]]): Unit = futures.foreach(_.await) - - /** - * Returns the First Future that is completed (blocking!) - */ - @deprecated("Will be removed after 1.1, if you must block, use: firstCompletedOf(futures).await", "1.1") - def awaitOne(futures: List[Future[_]], timeout: Long = Long.MaxValue): Future[_] = firstCompletedOf[Any](futures, timeout).await - - /** - * Applies the supplied function to the specified collection of Futures after awaiting each future to be completed - */ - @deprecated("Will be removed after 1.1, if you must block, use: futures map { f => fun(f.await) }", "1.1") - def awaitMap[A, B](in: Traversable[Future[A]])(fun: (Future[A]) => B): Traversable[B] = - in map { f => fun(f.await) } - - /** - * Returns Future.resultOrException of the first completed of the 2 Futures provided (blocking!) - */ - @deprecated("Will be removed after 1.1, if you must block, use: firstCompletedOf(List(f1,f2)).await.resultOrException", "1.1") - def awaitEither[T](f1: Future[T], f2: Future[T]): Option[T] = firstCompletedOf[T](List(f1, f2)).await.resultOrException -} - -object Future { - /** - * This method constructs and returns a Future that will eventually hold the result of the execution of the supplied body - * The execution is performed by the specified Dispatcher. - */ - def apply[T](body: => T, timeout: Long = Actor.TIMEOUT)(implicit dispatcher: MessageDispatcher): Future[T] = - dispatcher.dispatchFuture(() => body, timeout) - - /** - * Construct a completable channel - */ - def channel(timeout: Long = Actor.TIMEOUT) = new Channel[Any] { - val future = empty[Any](timeout) - def !(msg: Any) = future completeWithResult msg - } - - /** - * Create an empty Future with default timeout - */ - def empty[T](timeout: Long = Actor.TIMEOUT) = new DefaultCompletableFuture[T](timeout) - - import scala.collection.mutable.Builder - import scala.collection.generic.CanBuildFrom - - /** - * Simple version of Futures.traverse. Transforms a Traversable[Future[A]] into a Future[Traversable[A]]. - * Useful for reducing many Futures into a single Future. - */ - def sequence[A, M[_] <: Traversable[_]](in: M[Future[A]], timeout: Long = Actor.TIMEOUT)(implicit cbf: CanBuildFrom[M[Future[A]], A, M[A]]): Future[M[A]] = - in.foldLeft(new DefaultCompletableFuture[Builder[A, M[A]]](timeout).completeWithResult(cbf(in)): Future[Builder[A, M[A]]])((fr, fa) => for (r ← fr; a ← fa.asInstanceOf[Future[A]]) yield (r += a)).map(_.result) - - /** - * Transforms a Traversable[A] into a Future[Traversable[B]] using the provided Function A => Future[B]. - * This is useful for performing a parallel map. For example, to apply a function to all items of a list - * in parallel: - *
          -   * val myFutureList = Futures.traverse(myList)(x => Future(myFunc(x)))
          -   * 
          - */ - def traverse[A, B, M[_] <: Traversable[_]](in: M[A], timeout: Long = Actor.TIMEOUT)(fn: A => Future[B])(implicit cbf: CanBuildFrom[M[A], B, M[B]]): Future[M[B]] = - in.foldLeft(new DefaultCompletableFuture[Builder[B, M[B]]](timeout).completeWithResult(cbf(in)): Future[Builder[B, M[B]]]) { (fr, a) => - val fb = fn(a.asInstanceOf[A]) - for (r ← fr; b ← fb) yield (r += b) - }.map(_.result) - - /** - * Captures a block that will be transformed into 'Continuation Passing Style' using Scala's Delimited - * Continuations plugin. - * - * Within the block, the result of a Future may be accessed by calling Future.apply. At that point - * execution is suspended with the rest of the block being stored in a continuation until the result - * of the Future is available. If an Exception is thrown while processing, it will be contained - * within the resulting Future. - * - * This allows working with Futures in an imperative style without blocking for each result. - * - * Completing a Future using 'CompletableFuture << Future' will also suspend execution until the - * value of the other Future is available. - * - * The Delimited Continuations compiler plugin must be enabled in order to use this method. - */ - def flow[A](body: => A @cps[Future[Any]], timeout: Long = Actor.TIMEOUT): Future[A] = { - val future = Promise[A](timeout) - (reset(future.asInstanceOf[CompletableFuture[Any]].completeWithResult(body)): Future[Any]) onComplete { f => - val opte = f.exception - if (opte.isDefined) future completeWithException (opte.get) - } - future - } - - private[akka] val callbacksPendingExecution = new ThreadLocal[Option[Stack[() => Unit]]]() { - override def initialValue = None - } -} - -sealed trait Future[+T] { - - /** - * For use only within a Future.flow block or another compatible Delimited Continuations reset block. - * - * Returns the result of this Future without blocking, by suspending execution and storing it as a - * continuation until the result is available. - * - * If this Future is untyped (a Future[Nothing]), a type parameter must be explicitly provided or - * execution will fail. The normal result of getting a Future from an ActorRef using !!! will return - * an untyped Future. - */ - def apply[A >: T](): A @cps[Future[Any]] = shift(this flatMap (_: A => Future[Any])) - - /** - * Blocks awaiting completion of this Future, then returns the resulting value, - * or throws the completed exception - * - * Scala & Java API - * - * throws FutureTimeoutException if this Future times out when waiting for completion - */ - def get: T = this.await.resultOrException.get - - /** - * Blocks the current thread until the Future has been completed or the - * timeout has expired. In the case of the timeout expiring a - * FutureTimeoutException will be thrown. - */ - def await: Future[T] - - /** - * Blocks the current thread until the Future has been completed or the - * timeout has expired. The timeout will be the least value of 'atMost' and the timeout - * supplied at the constructuion of this Future. - * In the case of the timeout expiring a FutureTimeoutException will be thrown. - */ - def await(atMost: Duration): Future[T] - - /** - * Blocks the current thread until the Future has been completed. Use - * caution with this method as it ignores the timeout and will block - * indefinitely if the Future is never completed. - */ - @deprecated("Will be removed after 1.1, it's dangerous and can cause deadlocks, agony and insanity.", "1.1") - def awaitBlocking: Future[T] - - /** - * Tests whether this Future has been completed. - */ - final def isCompleted: Boolean = value.isDefined - - /** - * Tests whether this Future's timeout has expired. - * - * Note that an expired Future may still contain a value, or it may be - * completed with a value. - */ - def isExpired: Boolean - - /** - * This Future's timeout in nanoseconds. - */ - def timeoutInNanos: Long - - /** - * The contained value of this Future. Before this Future is completed - * the value will be None. After completion the value will be Some(Right(t)) - * if it contains a valid result, or Some(Left(error)) if it contains - * an exception. - */ - def value: Option[Either[Throwable, T]] - - /** - * Returns the successful result of this Future if it exists. - */ - final def result: Option[T] = { - val v = value - if (v.isDefined) v.get.right.toOption - else None - } - - /** - * Returns the contained exception of this Future if it exists. - */ - final def exception: Option[Throwable] = { - val v = value - if (v.isDefined) v.get.left.toOption - else None - } - - /** - * When this Future is completed, apply the provided function to the - * Future. If the Future has already been completed, this will apply - * immediately. - */ - def onComplete(func: Future[T] => Unit): Future[T] - - /** - * When the future is completed with a valid result, apply the provided - * PartialFunction to the result. - *
          -   *   val result = future receive {
          -   *     case Foo => "foo"
          -   *     case Bar => "bar"
          -   *   }.await.result
          -   * 
          - */ - final def receive(pf: PartialFunction[Any, Unit]): Future[T] = onComplete { f => - val optr = f.result - if (optr.isDefined) { - val r = optr.get - if (pf.isDefinedAt(r)) pf(r) - } - } - - /** - * Creates a new Future by applying a PartialFunction to the successful - * result of this Future if a match is found, or else return a MatchError. - * If this Future is completed with an exception then the new Future will - * also contain this exception. - * Example: - *
          -   * val future1 = for {
          -   *   a <- actor !!! Req("Hello") collect { case Res(x: Int)    => x }
          -   *   b <- actor !!! Req(a)       collect { case Res(x: String) => x }
          -   *   c <- actor !!! Req(7)       collect { case Res(x: String) => x }
          -   * } yield b + "-" + c
          -   * 
          - */ - final def collect[A](pf: PartialFunction[Any, A]): Future[A] = { - val fa = new DefaultCompletableFuture[A](timeoutInNanos, NANOS) - onComplete { ft => - val v = ft.value.get - fa complete { - if (v.isLeft) v.asInstanceOf[Either[Throwable, A]] - else { - try { - val r = v.right.get - if (pf isDefinedAt r) Right(pf(r)) - else Left(new MatchError(r)) - } catch { - case e: Exception => - EventHandler.error(e, this, e.getMessage) - Left(e) - } - } - } - } - fa - } - - /** - * Creates a new Future that will handle any matching Throwable that this - * Future might contain. If there is no match, or if this Future contains - * a valid result then the new Future will contain the same. - * Example: - *
          -   * Future(6 / 0) failure { case e: ArithmeticException => 0 } // result: 0
          -   * Future(6 / 0) failure { case e: NotFoundException   => 0 } // result: exception
          -   * Future(6 / 2) failure { case e: ArithmeticException => 0 } // result: 3
          -   * 
          - */ - final def failure[A >: T](pf: PartialFunction[Throwable, A]): Future[A] = { - val fa = new DefaultCompletableFuture[A](timeoutInNanos, NANOS) - onComplete { ft => - val opte = ft.exception - fa complete { - if (opte.isDefined) { - val e = opte.get - try { - if (pf isDefinedAt e) Right(pf(e)) - else Left(e) - } catch { - case x: Exception => Left(x) - } - } else ft.value.get - } - } - fa - } - - /** - * Creates a new Future by applying a function to the successful result of - * this Future. If this Future is completed with an exception then the new - * Future will also contain this exception. - * Example: - *
          -   * val future1 = for {
          -   *   a: Int    <- actor !!! "Hello" // returns 5
          -   *   b: String <- actor !!! a       // returns "10"
          -   *   c: String <- actor !!! 7       // returns "14"
          -   * } yield b + "-" + c
          -   * 
          - */ - final def map[A](f: T => A): Future[A] = { - val fa = new DefaultCompletableFuture[A](timeoutInNanos, NANOS) - onComplete { ft => - val optv = ft.value - if (optv.isDefined) { - val v = optv.get - if (v.isLeft) - fa complete v.asInstanceOf[Either[Throwable, A]] - else { - fa complete (try { - Right(f(v.right.get)) - } catch { - case e: Exception => - EventHandler.error(e, this, e.getMessage) - Left(e) - }) - } - } - } - fa - } - - /** - * Creates a new Future by applying a function to the successful result of - * this Future, and returns the result of the function as the new Future. - * If this Future is completed with an exception then the new Future will - * also contain this exception. - * Example: - *
          -   * val future1 = for {
          -   *   a: Int    <- actor !!! "Hello" // returns 5
          -   *   b: String <- actor !!! a       // returns "10"
          -   *   c: String <- actor !!! 7       // returns "14"
          -   * } yield b + "-" + c
          -   * 
          - */ - final def flatMap[A](f: T => Future[A]): Future[A] = { - val fa = new DefaultCompletableFuture[A](timeoutInNanos, NANOS) - onComplete { ft => - val optv = ft.value - if (optv.isDefined) { - val v = optv.get - if (v.isLeft) - fa complete v.asInstanceOf[Either[Throwable, A]] - else { - try { - fa.completeWith(f(v.right.get)) - } catch { - case e: Exception => - EventHandler.error(e, this, e.getMessage) - fa completeWithException e - } - } - } - } - fa - } - - final def foreach(f: T => Unit): Unit = onComplete { ft => - val optr = ft.result - if (optr.isDefined) - f(optr.get) - } - - final def filter(p: Any => Boolean): Future[Any] = { - val f = new DefaultCompletableFuture[T](timeoutInNanos, NANOS) - onComplete { ft => - val optv = ft.value - if (optv.isDefined) { - val v = optv.get - if (v.isLeft) - f complete v - else { - val r = v.right.get - f complete (try { - if (p(r)) Right(r) - else Left(new MatchError(r)) - } catch { - case e: Exception => - EventHandler.error(e, this, e.getMessage) - Left(e) - }) - } - } - } - f - } - - /** - * Returns the current result, throws the exception is one has been raised, else returns None - */ - final def resultOrException: Option[T] = { - val v = value - if (v.isDefined) { - val r = v.get - if (r.isLeft) throw r.left.get - else r.right.toOption - } else None - } - - /* Java API */ - final def onComplete[A >: T](proc: Procedure[Future[A]]): Future[T] = onComplete(proc(_)) - - final def map[A >: T, B](f: JFunc[A, B]): Future[B] = map(f(_)) - - final def flatMap[A >: T, B](f: JFunc[A, Future[B]]): Future[B] = flatMap(f(_)) - - final def foreach[A >: T](proc: Procedure[A]): Unit = foreach(proc(_)) - - final def filter(p: JFunc[Any, Boolean]): Future[Any] = filter(p(_)) - -} - -object Promise { - - def apply[A](timeout: Long): CompletableFuture[A] = new DefaultCompletableFuture[A](timeout) - - def apply[A](): CompletableFuture[A] = apply(Actor.TIMEOUT) - -} - -/** - * Essentially this is the Promise (or write-side) of a Future (read-side). - */ -trait CompletableFuture[T] extends Future[T] { - /** - * Completes this Future with the specified result, if not already completed. - * @return this - */ - def complete(value: Either[Throwable, T]): Future[T] - - /** - * Completes this Future with the specified result, if not already completed. - * @return this - */ - final def completeWithResult(result: T): Future[T] = complete(Right(result)) - - /** - * Completes this Future with the specified exception, if not already completed. - * @return this - */ - final def completeWithException(exception: Throwable): Future[T] = complete(Left(exception)) - - /** - * Completes this Future with the specified other Future, when that Future is completed, - * unless this Future has already been completed. - * @return this. - */ - final def completeWith(other: Future[T]): Future[T] = { - other onComplete { f => complete(f.value.get) } - this - } - - final def <<(value: T): Future[T] @cps[Future[Any]] = shift { cont: (Future[T] => Future[Any]) => cont(complete(Right(value))) } - - final def <<(other: Future[T]): Future[T] @cps[Future[Any]] = shift { cont: (Future[T] => Future[Any]) => - val fr = new DefaultCompletableFuture[Any](Actor.TIMEOUT) - this completeWith other onComplete { f => - try { - fr completeWith cont(f) - } catch { - case e: Exception => - EventHandler.error(e, this, e.getMessage) - fr completeWithException e - } - } - fr - } - -} - -/** - * The default concrete Future implementation. - */ -class DefaultCompletableFuture[T](timeout: Long, timeunit: TimeUnit) extends CompletableFuture[T] { - - def this() = this(0, MILLIS) - - def this(timeout: Long) = this(timeout, MILLIS) - - val timeoutInNanos = timeunit.toNanos(timeout) - private val _startTimeInNanos = currentTimeInNanos - private val _lock = new ReentrantLock - private val _signal = _lock.newCondition - private var _value: Option[Either[Throwable, T]] = None - private var _listeners: List[Future[T] => Unit] = Nil - - /** - * Must be called inside _lock.lock<->_lock.unlock - */ - @tailrec - private def awaitUnsafe(waitTimeNanos: Long): Boolean = { - if (_value.isEmpty && waitTimeNanos > 0) { - val start = currentTimeInNanos - val remainingNanos = try { - _signal.awaitNanos(waitTimeNanos) - } catch { - case e: InterruptedException => - waitTimeNanos - (currentTimeInNanos - start) - } - awaitUnsafe(remainingNanos) - } else { - _value.isDefined - } - } - - def await(atMost: Duration) = { - _lock.lock - if (try { awaitUnsafe(atMost.toNanos min timeLeft()) } finally { _lock.unlock }) this - else throw new FutureTimeoutException("Futures timed out after [" + NANOS.toMillis(timeoutInNanos) + "] milliseconds") - } - - def await = { - _lock.lock - if (try { awaitUnsafe(timeLeft()) } finally { _lock.unlock }) this - else throw new FutureTimeoutException("Futures timed out after [" + NANOS.toMillis(timeoutInNanos) + "] milliseconds") - } - - def awaitBlocking = { - _lock.lock - try { - while (_value.isEmpty) { - _signal.await - } - this - } finally { - _lock.unlock - } - } - - def isExpired: Boolean = timeLeft() <= 0 - - def value: Option[Either[Throwable, T]] = { - _lock.lock - try { - _value - } finally { - _lock.unlock - } - } - - def complete(value: Either[Throwable, T]): DefaultCompletableFuture[T] = { - _lock.lock - val notifyTheseListeners = try { - if (_value.isEmpty && !isExpired) { //Only complete if we aren't expired - _value = Some(value) - val existingListeners = _listeners - _listeners = Nil - existingListeners - } else Nil - } finally { - _signal.signalAll - _lock.unlock - } - - if (notifyTheseListeners.nonEmpty) { // Steps to ensure we don't run into a stack-overflow situation - @tailrec - def runCallbacks(rest: List[Future[T] => Unit], callbacks: Stack[() => Unit]) { - if (rest.nonEmpty) { - notifyCompleted(rest.head) - while (callbacks.nonEmpty) { callbacks.pop().apply() } - runCallbacks(rest.tail, callbacks) - } - } - - val pending = Future.callbacksPendingExecution.get - if (pending.isDefined) { //Instead of nesting the calls to the callbacks (leading to stack overflow) - pending.get.push(() => { // Linearize/aggregate callbacks at top level and then execute - val doNotify = notifyCompleted _ //Hoist closure to avoid garbage - notifyTheseListeners foreach doNotify - }) - } else { - try { - val callbacks = Stack[() => Unit]() // Allocate new aggregator for pending callbacks - Future.callbacksPendingExecution.set(Some(callbacks)) // Specify the callback aggregator - runCallbacks(notifyTheseListeners, callbacks) // Execute callbacks, if they trigger new callbacks, they are aggregated - } finally { Future.callbacksPendingExecution.set(None) } // Ensure cleanup - } - } - - this - } - - def onComplete(func: Future[T] => Unit): CompletableFuture[T] = { - _lock.lock - val notifyNow = try { - if (_value.isEmpty) { - if (!isExpired) { //Only add the listener if the future isn't expired - _listeners ::= func - false - } else false //Will never run the callback since the future is expired - } else true - } finally { - _lock.unlock - } - - if (notifyNow) notifyCompleted(func) - - this - } - - private def notifyCompleted(func: Future[T] => Unit) { - try { - func(this) - } catch { - case e => EventHandler notify EventHandler.Error(e, this) - } - } - - @inline - private def currentTimeInNanos: Long = MILLIS.toNanos(System.currentTimeMillis) - @inline - private def timeLeft(): Long = timeoutInNanos - (currentTimeInNanos - _startTimeInNanos) -} - -/** - * An already completed Future is seeded with it's result at creation, is useful for when you are participating in - * a Future-composition but you already have a value to contribute. - */ -sealed class AlreadyCompletedFuture[T](suppliedValue: Either[Throwable, T]) extends CompletableFuture[T] { - val value = Some(suppliedValue) - - def complete(value: Either[Throwable, T]): CompletableFuture[T] = this - def onComplete(func: Future[T] => Unit): Future[T] = { func(this); this } - def await(atMost: Duration): Future[T] = this - def await: Future[T] = this - def awaitBlocking: Future[T] = this - def isExpired: Boolean = true - def timeoutInNanos: Long = 0 -} diff --git a/test/files/presentation/akka/src/akka/dispatch/MailboxHandling.scala b/test/files/presentation/akka/src/akka/dispatch/MailboxHandling.scala deleted file mode 100644 index 4c00577157..0000000000 --- a/test/files/presentation/akka/src/akka/dispatch/MailboxHandling.scala +++ /dev/null @@ -1,68 +0,0 @@ -/** - * Copyright (C) 2009-2011 Scalable Solutions AB - */ - -package akka.dispatch - -import akka.AkkaException - -import java.util.{ Comparator, PriorityQueue } -import java.util.concurrent._ -import akka.util._ - -class MessageQueueAppendFailedException(message: String, cause: Throwable = null) extends AkkaException(message, cause) - -/** - * @author Jonas Bonér - */ -trait MessageQueue { - val dispatcherLock = new SimpleLock - val suspended = new SimpleLock - def enqueue(handle: MessageInvocation) - def dequeue(): MessageInvocation - def size: Int - def isEmpty: Boolean -} - -/** - * Mailbox configuration. - */ -sealed trait MailboxType - -case class UnboundedMailbox() extends MailboxType -case class BoundedMailbox( - val capacity: Int = { if (Dispatchers.MAILBOX_CAPACITY < 0) Int.MaxValue else Dispatchers.MAILBOX_CAPACITY }, - val pushTimeOut: Duration = Dispatchers.MAILBOX_PUSH_TIME_OUT) extends MailboxType { - if (capacity < 0) throw new IllegalArgumentException("The capacity for BoundedMailbox can not be negative") - if (pushTimeOut eq null) throw new IllegalArgumentException("The push time-out for BoundedMailbox can not be null") -} - -trait UnboundedMessageQueueSemantics extends MessageQueue { self: BlockingQueue[MessageInvocation] => - @inline - final def enqueue(handle: MessageInvocation): Unit = this add handle - @inline - final def dequeue(): MessageInvocation = this.poll() -} - -trait BoundedMessageQueueSemantics extends MessageQueue { self: BlockingQueue[MessageInvocation] => - def pushTimeOut: Duration - - final def enqueue(handle: MessageInvocation) { - if (pushTimeOut.length > 0) { - this.offer(handle, pushTimeOut.length, pushTimeOut.unit) || { - throw new MessageQueueAppendFailedException("Couldn't enqueue message " + handle + " to " + toString) - } - } else this put handle - } - - @inline - final def dequeue(): MessageInvocation = this.poll() -} - -class DefaultUnboundedMessageQueue extends LinkedBlockingQueue[MessageInvocation] with UnboundedMessageQueueSemantics - -class DefaultBoundedMessageQueue(capacity: Int, val pushTimeOut: Duration) extends LinkedBlockingQueue[MessageInvocation](capacity) with BoundedMessageQueueSemantics - -class UnboundedPriorityMessageQueue(cmp: Comparator[MessageInvocation]) extends PriorityBlockingQueue[MessageInvocation](11, cmp) with UnboundedMessageQueueSemantics - -class BoundedPriorityMessageQueue(capacity: Int, val pushTimeOut: Duration, cmp: Comparator[MessageInvocation]) extends BoundedBlockingQueue[MessageInvocation](capacity, new PriorityQueue[MessageInvocation](11, cmp)) with BoundedMessageQueueSemantics diff --git a/test/files/presentation/akka/src/akka/dispatch/MessageHandling.scala b/test/files/presentation/akka/src/akka/dispatch/MessageHandling.scala deleted file mode 100644 index 20887c3867..0000000000 --- a/test/files/presentation/akka/src/akka/dispatch/MessageHandling.scala +++ /dev/null @@ -1,260 +0,0 @@ -/** - * Copyright (C) 2009-2011 Scalable Solutions AB - */ - -package akka.dispatch - -import java.util.concurrent._ -import java.util.concurrent.atomic.AtomicLong -import akka.event.EventHandler -import akka.config.Configuration -import akka.config.Config.TIME_UNIT -import akka.util.{ Duration, Switch, ReentrantGuard } -import java.util.concurrent.ThreadPoolExecutor.{ AbortPolicy, CallerRunsPolicy, DiscardOldestPolicy, DiscardPolicy } -import akka.actor._ - -/** - * @author Jonas Bonér - */ -final case class MessageInvocation(val receiver: ActorRef, - val message: Any, - val sender: Option[ActorRef], - val senderFuture: Option[CompletableFuture[Any]]) { - if (receiver eq null) throw new IllegalArgumentException("Receiver can't be null") - - def invoke = try { - receiver.invoke(this) - } catch { - case e: NullPointerException => throw new ActorInitializationException( - "Don't call 'self ! message' in the Actor's constructor (in Scala this means in the body of the class).") - } -} - -final case class FutureInvocation[T](future: CompletableFuture[T], function: () => T, cleanup: () => Unit) extends Runnable { - def run = { - future complete (try { - Right(function()) - } catch { - case e => - EventHandler.error(e, this, e.getMessage) - Left(e) - } - finally { - cleanup() - }) - } -} - -object MessageDispatcher { - val UNSCHEDULED = 0 - val SCHEDULED = 1 - val RESCHEDULED = 2 - - implicit def defaultGlobalDispatcher = Dispatchers.defaultGlobalDispatcher -} - -/** - * @author Jonas Bonér - */ -trait MessageDispatcher { - import MessageDispatcher._ - - protected val uuids = new ConcurrentSkipListSet[Uuid] - protected val futures = new AtomicLong(0L) - protected val guard = new ReentrantGuard - protected val active = new Switch(false) - - private var shutdownSchedule = UNSCHEDULED //This can be non-volatile since it is protected by guard withGuard - - /** - * Creates and returns a mailbox for the given actor. - */ - private[akka] def createMailbox(actorRef: ActorRef): AnyRef - - /** - * Attaches the specified actorRef to this dispatcher - */ - final def attach(actorRef: ActorRef): Unit = guard withGuard { - register(actorRef) - } - - /** - * Detaches the specified actorRef from this dispatcher - */ - final def detach(actorRef: ActorRef): Unit = guard withGuard { - unregister(actorRef) - } - - private[akka] final def dispatchMessage(invocation: MessageInvocation): Unit = dispatch(invocation) - - private[akka] final def dispatchFuture[T](block: () => T, timeout: Long): Future[T] = { - futures.getAndIncrement() - try { - val future = new DefaultCompletableFuture[T](timeout) - - if (active.isOff) - guard withGuard { active.switchOn { start } } - - executeFuture(FutureInvocation[T](future, block, futureCleanup)) - future - } catch { - case e => - futures.decrementAndGet - throw e - } - } - - private val futureCleanup: () => Unit = - () => if (futures.decrementAndGet() == 0) { - guard withGuard { - if (futures.get == 0 && uuids.isEmpty) { - shutdownSchedule match { - case UNSCHEDULED => - shutdownSchedule = SCHEDULED - Scheduler.scheduleOnce(shutdownAction, timeoutMs, TimeUnit.MILLISECONDS) - case SCHEDULED => - shutdownSchedule = RESCHEDULED - case RESCHEDULED => //Already marked for reschedule - } - } - } - } - - private[akka] def register(actorRef: ActorRef) { - if (actorRef.mailbox eq null) - actorRef.mailbox = createMailbox(actorRef) - - uuids add actorRef.uuid - if (active.isOff) { - active.switchOn { - start - } - } - } - - private[akka] def unregister(actorRef: ActorRef) = { - if (uuids remove actorRef.uuid) { - actorRef.mailbox = null - if (uuids.isEmpty && futures.get == 0) { - shutdownSchedule match { - case UNSCHEDULED => - shutdownSchedule = SCHEDULED - Scheduler.scheduleOnce(shutdownAction, timeoutMs, TimeUnit.MILLISECONDS) - case SCHEDULED => - shutdownSchedule = RESCHEDULED - case RESCHEDULED => //Already marked for reschedule - } - } - } - } - - /** - * Traverses the list of actors (uuids) currently being attached to this dispatcher and stops those actors - */ - def stopAllAttachedActors { - val i = uuids.iterator - while (i.hasNext()) { - val uuid = i.next() - Actor.registry.actorFor(uuid) match { - case Some(actor) => actor.stop() - case None => {} - } - } - } - - private val shutdownAction = new Runnable { - def run = guard withGuard { - shutdownSchedule match { - case RESCHEDULED => - shutdownSchedule = SCHEDULED - Scheduler.scheduleOnce(this, timeoutMs, TimeUnit.MILLISECONDS) - case SCHEDULED => - if (uuids.isEmpty && futures.get == 0) { - active switchOff { - shutdown // shut down in the dispatcher's references is zero - } - } - shutdownSchedule = UNSCHEDULED - case UNSCHEDULED => //Do nothing - } - } - } - - /** - * When the dispatcher no longer has any actors registered, how long will it wait until it shuts itself down, in Ms - * defaulting to your akka configs "akka.actor.dispatcher-shutdown-timeout" or otherwise, 1 Second - */ - private[akka] def timeoutMs: Long = Dispatchers.DEFAULT_SHUTDOWN_TIMEOUT.toMillis - - /** - * After the call to this method, the dispatcher mustn't begin any new message processing for the specified reference - */ - def suspend(actorRef: ActorRef): Unit - - /* - * After the call to this method, the dispatcher must begin any new message processing for the specified reference - */ - def resume(actorRef: ActorRef): Unit - - /** - * Will be called when the dispatcher is to queue an invocation for execution - */ - private[akka] def dispatch(invocation: MessageInvocation): Unit - - private[akka] def executeFuture(invocation: FutureInvocation[_]): Unit - - /** - * Called one time every time an actor is attached to this dispatcher and this dispatcher was previously shutdown - */ - private[akka] def start(): Unit - - /** - * Called one time every time an actor is detached from this dispatcher and this dispatcher has no actors left attached - */ - private[akka] def shutdown(): Unit - - /** - * Returns the size of the mailbox for the specified actor - */ - def mailboxSize(actorRef: ActorRef): Int - - /** - * Returns the amount of futures queued for execution - */ - def pendingFutures: Long = futures.get -} - -/** - * Trait to be used for hooking in new dispatchers into Dispatchers.fromConfig - */ -abstract class MessageDispatcherConfigurator { - /** - * Returns an instance of MessageDispatcher given a Configuration - */ - def configure(config: Configuration): MessageDispatcher - - def mailboxType(config: Configuration): MailboxType = { - val capacity = config.getInt("mailbox-capacity", Dispatchers.MAILBOX_CAPACITY) - if (capacity < 1) UnboundedMailbox() - else BoundedMailbox(capacity, Duration(config.getInt("mailbox-push-timeout-time", Dispatchers.MAILBOX_PUSH_TIME_OUT.toMillis.toInt), TIME_UNIT)) - } - - def configureThreadPool(config: Configuration, createDispatcher: => (ThreadPoolConfig) => MessageDispatcher): ThreadPoolConfigDispatcherBuilder = { - import ThreadPoolConfigDispatcherBuilder.conf_? - - //Apply the following options to the config if they are present in the config - ThreadPoolConfigDispatcherBuilder(createDispatcher, ThreadPoolConfig()).configure( - conf_?(config getInt "keep-alive-time")(time => _.setKeepAliveTime(Duration(time, TIME_UNIT))), - conf_?(config getDouble "core-pool-size-factor")(factor => _.setCorePoolSizeFromFactor(factor)), - conf_?(config getDouble "max-pool-size-factor")(factor => _.setMaxPoolSizeFromFactor(factor)), - conf_?(config getInt "executor-bounds")(bounds => _.setExecutorBounds(bounds)), - conf_?(config getBool "allow-core-timeout")(allow => _.setAllowCoreThreadTimeout(allow)), - conf_?(config getString "rejection-policy" map { - case "abort" => new AbortPolicy() - case "caller-runs" => new CallerRunsPolicy() - case "discard-oldest" => new DiscardOldestPolicy() - case "discard" => new DiscardPolicy() - case x => throw new IllegalArgumentException("[%s] is not a valid rejectionPolicy!" format x) - })(policy => _.setRejectionPolicy(policy))) - } -} diff --git a/test/files/presentation/akka/src/akka/dispatch/ThreadBasedDispatcher.scala b/test/files/presentation/akka/src/akka/dispatch/ThreadBasedDispatcher.scala deleted file mode 100644 index 3169c70ef9..0000000000 --- a/test/files/presentation/akka/src/akka/dispatch/ThreadBasedDispatcher.scala +++ /dev/null @@ -1,52 +0,0 @@ -/** - * Copyright (C) 2009-2011 Scalable Solutions AB - */ - -package akka.dispatch - -import akka.actor.{ Actor, ActorRef } -import akka.config.Config.config -import akka.util.Duration - -import java.util.Queue -import java.util.concurrent.{ ConcurrentLinkedQueue, BlockingQueue, TimeUnit, LinkedBlockingQueue } -import akka.actor -import java.util.concurrent.atomic.AtomicReference - -/** - * Dedicates a unique thread for each actor passed in as reference. Served through its messageQueue. - * - * @author Jonas Bonér - */ -class ThreadBasedDispatcher(_actor: ActorRef, _mailboxType: MailboxType) - extends ExecutorBasedEventDrivenDispatcher( - _actor.uuid.toString, Dispatchers.THROUGHPUT, -1, _mailboxType, ThreadBasedDispatcher.oneThread) { - - private[akka] val owner = new AtomicReference[ActorRef](_actor) - - def this(actor: ActorRef) = - this(actor, UnboundedMailbox()) // For Java API - - def this(actor: ActorRef, capacity: Int) = - this(actor, BoundedMailbox(capacity)) //For Java API - - def this(actor: ActorRef, capacity: Int, pushTimeOut: Duration) = //For Java API - this(actor, BoundedMailbox(capacity, pushTimeOut)) - - override def register(actorRef: ActorRef) = { - val actor = owner.get() - if ((actor ne null) && actorRef != actor) throw new IllegalArgumentException("Cannot register to anyone but " + actor) - owner.compareAndSet(null, actorRef) //Register if unregistered - super.register(actorRef) - } - - override def unregister(actorRef: ActorRef) = { - super.unregister(actorRef) - owner.compareAndSet(actorRef, null) //Unregister (prevent memory leak) - } -} - -object ThreadBasedDispatcher { - val oneThread: ThreadPoolConfig = ThreadPoolConfig(allowCorePoolTimeout = true, corePoolSize = 1, maxPoolSize = 1) -} - diff --git a/test/files/presentation/akka/src/akka/dispatch/ThreadPoolBuilder.scala b/test/files/presentation/akka/src/akka/dispatch/ThreadPoolBuilder.scala deleted file mode 100644 index e847610c4c..0000000000 --- a/test/files/presentation/akka/src/akka/dispatch/ThreadPoolBuilder.scala +++ /dev/null @@ -1,259 +0,0 @@ -/** - * Copyright (C) 2009-2011 Scalable Solutions AB - */ - -package akka.dispatch - -import java.util.Collection -import java.util.concurrent._ -import atomic.{ AtomicLong, AtomicInteger } -import ThreadPoolExecutor.CallerRunsPolicy - -import akka.util.Duration -import akka.event.EventHandler - -object ThreadPoolConfig { - type Bounds = Int - type FlowHandler = Either[RejectedExecutionHandler, Bounds] - type QueueFactory = () => BlockingQueue[Runnable] - - val defaultAllowCoreThreadTimeout: Boolean = false - val defaultCorePoolSize: Int = 16 - val defaultMaxPoolSize: Int = 128 - val defaultTimeout: Duration = Duration(60000L, TimeUnit.MILLISECONDS) - def defaultFlowHandler: FlowHandler = flowHandler(new CallerRunsPolicy) - - def flowHandler(rejectionHandler: RejectedExecutionHandler): FlowHandler = Left(rejectionHandler) - def flowHandler(bounds: Int): FlowHandler = Right(bounds) - - def fixedPoolSize(size: Int): Int = size - def scaledPoolSize(multiplier: Double): Int = - (Runtime.getRuntime.availableProcessors * multiplier).ceil.toInt - - def arrayBlockingQueue(capacity: Int, fair: Boolean): QueueFactory = - () => new ArrayBlockingQueue[Runnable](capacity, fair) - - def synchronousQueue(fair: Boolean): QueueFactory = - () => new SynchronousQueue[Runnable](fair) - - def linkedBlockingQueue(): QueueFactory = - () => new LinkedBlockingQueue[Runnable]() - - def linkedBlockingQueue(capacity: Int): QueueFactory = - () => new LinkedBlockingQueue[Runnable](capacity) - - def reusableQueue(queue: BlockingQueue[Runnable]): QueueFactory = - () => queue - - def reusableQueue(queueFactory: QueueFactory): QueueFactory = { - val queue = queueFactory() - () => queue - } -} - -case class ThreadPoolConfig(allowCorePoolTimeout: Boolean = ThreadPoolConfig.defaultAllowCoreThreadTimeout, - corePoolSize: Int = ThreadPoolConfig.defaultCorePoolSize, - maxPoolSize: Int = ThreadPoolConfig.defaultMaxPoolSize, - threadTimeout: Duration = ThreadPoolConfig.defaultTimeout, - flowHandler: ThreadPoolConfig.FlowHandler = ThreadPoolConfig.defaultFlowHandler, - queueFactory: ThreadPoolConfig.QueueFactory = ThreadPoolConfig.linkedBlockingQueue()) { - - final def createLazyExecutorService(threadFactory: ThreadFactory): ExecutorService = - new LazyExecutorServiceWrapper(createExecutorService(threadFactory)) - - final def createExecutorService(threadFactory: ThreadFactory): ExecutorService = { - flowHandler match { - case Left(rejectHandler) => - val service = new ThreadPoolExecutor(corePoolSize, maxPoolSize, threadTimeout.length, threadTimeout.unit, queueFactory(), threadFactory, rejectHandler) - service.allowCoreThreadTimeOut(allowCorePoolTimeout) - service - case Right(bounds) => - val service = new ThreadPoolExecutor(corePoolSize, maxPoolSize, threadTimeout.length, threadTimeout.unit, queueFactory(), threadFactory) - service.allowCoreThreadTimeOut(allowCorePoolTimeout) - new BoundedExecutorDecorator(service, bounds) - } - } -} - -trait DispatcherBuilder { - def build: MessageDispatcher -} - -object ThreadPoolConfigDispatcherBuilder { - def conf_?[T](opt: Option[T])(fun: (T) => ThreadPoolConfigDispatcherBuilder => ThreadPoolConfigDispatcherBuilder): Option[(ThreadPoolConfigDispatcherBuilder) => ThreadPoolConfigDispatcherBuilder] = opt map fun -} - -case class ThreadPoolConfigDispatcherBuilder(dispatcherFactory: (ThreadPoolConfig) => MessageDispatcher, config: ThreadPoolConfig) extends DispatcherBuilder { - import ThreadPoolConfig._ - def build = dispatcherFactory(config) - - //TODO remove this, for backwards compat only - @deprecated("Use .build instead", "1.1") - def buildThreadPool = build - - def withNewBoundedThreadPoolWithLinkedBlockingQueueWithUnboundedCapacity(bounds: Int): ThreadPoolConfigDispatcherBuilder = - this.copy(config = config.copy(flowHandler = flowHandler(bounds), queueFactory = linkedBlockingQueue())) - - def withNewThreadPoolWithCustomBlockingQueue(newQueueFactory: QueueFactory): ThreadPoolConfigDispatcherBuilder = - this.copy(config = config.copy(flowHandler = defaultFlowHandler, queueFactory = newQueueFactory)) - - def withNewThreadPoolWithCustomBlockingQueue(queue: BlockingQueue[Runnable]): ThreadPoolConfigDispatcherBuilder = - withNewThreadPoolWithCustomBlockingQueue(reusableQueue(queue)) - - def withNewThreadPoolWithLinkedBlockingQueueWithUnboundedCapacity: ThreadPoolConfigDispatcherBuilder = - this.copy(config = config.copy(queueFactory = linkedBlockingQueue(), flowHandler = defaultFlowHandler)) - - def withNewThreadPoolWithLinkedBlockingQueueWithCapacity(capacity: Int): ThreadPoolConfigDispatcherBuilder = - this.copy(config = config.copy(queueFactory = linkedBlockingQueue(capacity), flowHandler = defaultFlowHandler)) - - def withNewThreadPoolWithSynchronousQueueWithFairness(fair: Boolean): ThreadPoolConfigDispatcherBuilder = - this.copy(config = config.copy(queueFactory = synchronousQueue(fair), flowHandler = defaultFlowHandler)) - - def withNewThreadPoolWithArrayBlockingQueueWithCapacityAndFairness(capacity: Int, fair: Boolean): ThreadPoolConfigDispatcherBuilder = - this.copy(config = config.copy(queueFactory = arrayBlockingQueue(capacity, fair), flowHandler = defaultFlowHandler)) - - def setCorePoolSize(size: Int): ThreadPoolConfigDispatcherBuilder = - this.copy(config = config.copy(corePoolSize = size)) - - def setMaxPoolSize(size: Int): ThreadPoolConfigDispatcherBuilder = - this.copy(config = config.copy(maxPoolSize = size)) - - def setCorePoolSizeFromFactor(multiplier: Double): ThreadPoolConfigDispatcherBuilder = - setCorePoolSize(scaledPoolSize(multiplier)) - - def setMaxPoolSizeFromFactor(multiplier: Double): ThreadPoolConfigDispatcherBuilder = - setMaxPoolSize(scaledPoolSize(multiplier)) - - def setExecutorBounds(bounds: Int): ThreadPoolConfigDispatcherBuilder = - this.copy(config = config.copy(flowHandler = flowHandler(bounds))) - - def setKeepAliveTimeInMillis(time: Long): ThreadPoolConfigDispatcherBuilder = - setKeepAliveTime(Duration(time, TimeUnit.MILLISECONDS)) - - def setKeepAliveTime(time: Duration): ThreadPoolConfigDispatcherBuilder = - this.copy(config = config.copy(threadTimeout = time)) - - def setRejectionPolicy(policy: RejectedExecutionHandler): ThreadPoolConfigDispatcherBuilder = - setFlowHandler(flowHandler(policy)) - - def setFlowHandler(newFlowHandler: FlowHandler): ThreadPoolConfigDispatcherBuilder = - this.copy(config = config.copy(flowHandler = newFlowHandler)) - - def setAllowCoreThreadTimeout(allow: Boolean): ThreadPoolConfigDispatcherBuilder = - this.copy(config = config.copy(allowCorePoolTimeout = allow)) - - def configure(fs: Option[Function[ThreadPoolConfigDispatcherBuilder, ThreadPoolConfigDispatcherBuilder]]*): ThreadPoolConfigDispatcherBuilder = fs.foldLeft(this)((c, f) => f.map(_(c)).getOrElse(c)) -} - -/** - * @author Jonas Bonér - */ -class MonitorableThreadFactory(val name: String) extends ThreadFactory { - protected val counter = new AtomicLong - - def newThread(runnable: Runnable) = new MonitorableThread(runnable, name) -} - -/** - * @author Jonas Bonér - */ -object MonitorableThread { - val DEFAULT_NAME = "MonitorableThread" - - // FIXME use MonitorableThread.created and MonitorableThread.alive in monitoring - val created = new AtomicInteger - val alive = new AtomicInteger -} - -/** - * @author Jonas Bonér - */ -class MonitorableThread(runnable: Runnable, name: String) - extends Thread(runnable, name + "-" + MonitorableThread.created.incrementAndGet) { - - setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { - def uncaughtException(thread: Thread, cause: Throwable) = {} - }) - - override def run = { - try { - MonitorableThread.alive.incrementAndGet - super.run - } finally { - MonitorableThread.alive.decrementAndGet - } - } -} - -/** - * @author Jonas Bonér - */ -class BoundedExecutorDecorator(val executor: ExecutorService, bound: Int) extends ExecutorServiceDelegate { - protected val semaphore = new Semaphore(bound) - - override def execute(command: Runnable) = { - semaphore.acquire - try { - executor.execute(new Runnable() { - def run = { - try { - command.run - } finally { - semaphore.release - } - } - }) - } catch { - case e: RejectedExecutionException => - EventHandler.warning(this, e.toString) - semaphore.release - case e: Throwable => - EventHandler.error(e, this, e.getMessage) - throw e - } - } -} - -trait ExecutorServiceDelegate extends ExecutorService { - - def executor: ExecutorService - - def execute(command: Runnable) = executor.execute(command) - - def shutdown() { executor.shutdown() } - - def shutdownNow() = executor.shutdownNow() - - def isShutdown = executor.isShutdown - - def isTerminated = executor.isTerminated - - def awaitTermination(l: Long, timeUnit: TimeUnit) = executor.awaitTermination(l, timeUnit) - - def submit[T](callable: Callable[T]) = executor.submit(callable) - - def submit[T](runnable: Runnable, t: T) = executor.submit(runnable, t) - - def submit(runnable: Runnable) = executor.submit(runnable) - - def invokeAll[T](callables: Collection[_ <: Callable[T]]) = executor.invokeAll(callables) - - def invokeAll[T](callables: Collection[_ <: Callable[T]], l: Long, timeUnit: TimeUnit) = executor.invokeAll(callables, l, timeUnit) - - def invokeAny[T](callables: Collection[_ <: Callable[T]]) = executor.invokeAny(callables) - - def invokeAny[T](callables: Collection[_ <: Callable[T]], l: Long, timeUnit: TimeUnit) = executor.invokeAny(callables, l, timeUnit) -} - -trait LazyExecutorService extends ExecutorServiceDelegate { - - def createExecutor: ExecutorService - - lazy val executor = { - createExecutor - } -} - -class LazyExecutorServiceWrapper(executorFactory: => ExecutorService) extends LazyExecutorService { - def createExecutor = executorFactory -} diff --git a/test/files/presentation/akka/src/akka/event/EventHandler.scala b/test/files/presentation/akka/src/akka/event/EventHandler.scala deleted file mode 100644 index f3176b7c21..0000000000 --- a/test/files/presentation/akka/src/akka/event/EventHandler.scala +++ /dev/null @@ -1,235 +0,0 @@ -/** - * Copyright (C) 2009-2011 Scalable Solutions AB - */ - -package akka.event - -import akka.actor._ -import akka.config.Config._ -import akka.config.ConfigurationException -import akka.util.{ ListenerManagement, ReflectiveAccess } -import akka.AkkaException - -/** - * Event handler. - *

          - * Create, add and remove a listener: - *

          - * val eventHandlerListener = Actor.actorOf(new Actor {
          - *   self.dispatcher = EventHandler.EventHandlerDispatcher
          - *
          - *   def receive = {
          - *     case EventHandler.Error(cause, instance, message) => ...
          - *     case EventHandler.Warning(instance, message)      => ...
          - *     case EventHandler.Info(instance, message)         => ...
          - *     case EventHandler.Debug(instance, message)        => ...
          - *     case genericEvent                                 => ...
          - *   }
          - * })
          - *
          - * EventHandler.addListener(eventHandlerListener)
          - * ...
          - * EventHandler.removeListener(eventHandlerListener)
          - * 
          - *

          - * However best is probably to register the listener in the 'akka.conf' - * configuration file. - *

          - * Log an error event: - *

          - * EventHandler.notify(EventHandler.Error(exception, this, message))
          - * 
          - * Or use the direct methods (better performance): - *
          - * EventHandler.error(exception, this, message)
          - * 
          - * - * Shut down the EventHandler: - *
          - * EventHandler.shutdown()
          - * 
          - * - * @author Jonas Bonér - */ -object EventHandler extends ListenerManagement { - import java.io.{ StringWriter, PrintWriter } - import java.text.DateFormat - import java.util.Date - import akka.dispatch.Dispatchers - - val ErrorLevel = 1 - val WarningLevel = 2 - val InfoLevel = 3 - val DebugLevel = 4 - - sealed trait Event { - @transient - val thread: Thread = Thread.currentThread - val level: Int - } - case class Error(cause: Throwable, instance: AnyRef, message: Any = "") extends Event { - override val level = ErrorLevel - } - case class Warning(instance: AnyRef, message: Any = "") extends Event { - override val level = WarningLevel - } - case class Info(instance: AnyRef, message: Any = "") extends Event { - override val level = InfoLevel - } - case class Debug(instance: AnyRef, message: Any = "") extends Event { - override val level = DebugLevel - } - - val error = "[ERROR] [%s] [%s] [%s] %s\n%s".intern - val warning = "[WARN] [%s] [%s] [%s] %s".intern - val info = "[INFO] [%s] [%s] [%s] %s".intern - val debug = "[DEBUG] [%s] [%s] [%s] %s".intern - val generic = "[GENERIC] [%s] [%s]".intern - val ID = "event:handler".intern - - class EventHandlerException extends AkkaException - - lazy val EventHandlerDispatcher = Dispatchers.newExecutorBasedEventDrivenDispatcher(ID).build - - val level: Int = config.getString("akka.event-handler-level", "INFO") match { - case "ERROR" => ErrorLevel - case "WARNING" => WarningLevel - case "INFO" => InfoLevel - case "DEBUG" => DebugLevel - case unknown => throw new ConfigurationException( - "Configuration option 'akka.event-handler-level' is invalid [" + unknown + "]") - } - - /** - * Shuts down all event handler listeners including the event handle dispatcher. - */ - def shutdown() { - foreachListener(_.stop()) - EventHandlerDispatcher.shutdown() - } - - def notify(event: Any) { - if (event.isInstanceOf[Event]) { - if (level >= event.asInstanceOf[Event].level) notifyListeners(event) - } else - notifyListeners(event) - } - - def notify[T <: Event: ClassManifest](event: => T) { - if (level >= levelFor(classManifest[T].erasure.asInstanceOf[Class[_ <: Event]])) notifyListeners(event) - } - - def error(cause: Throwable, instance: AnyRef, message: => String) { - if (level >= ErrorLevel) notifyListeners(Error(cause, instance, message)) - } - - def error(cause: Throwable, instance: AnyRef, message: Any) { - if (level >= ErrorLevel) notifyListeners(Error(cause, instance, message)) - } - - def error(instance: AnyRef, message: => String) { - if (level >= ErrorLevel) notifyListeners(Error(new EventHandlerException, instance, message)) - } - - def error(instance: AnyRef, message: Any) { - if (level >= ErrorLevel) notifyListeners(Error(new EventHandlerException, instance, message)) - } - - def warning(instance: AnyRef, message: => String) { - if (level >= WarningLevel) notifyListeners(Warning(instance, message)) - } - - def warning(instance: AnyRef, message: Any) { - if (level >= WarningLevel) notifyListeners(Warning(instance, message)) - } - - def info(instance: AnyRef, message: => String) { - if (level >= InfoLevel) notifyListeners(Info(instance, message)) - } - - def info(instance: AnyRef, message: Any) { - if (level >= InfoLevel) notifyListeners(Info(instance, message)) - } - - def debug(instance: AnyRef, message: => String) { - if (level >= DebugLevel) notifyListeners(Debug(instance, message)) - } - - def debug(instance: AnyRef, message: Any) { - if (level >= DebugLevel) notifyListeners(Debug(instance, message)) - } - - def isInfoEnabled = level >= InfoLevel - - def isDebugEnabled = level >= DebugLevel - - def formattedTimestamp = DateFormat.getInstance.format(new Date) - - def stackTraceFor(e: Throwable) = { - val sw = new StringWriter - val pw = new PrintWriter(sw) - e.printStackTrace(pw) - sw.toString - } - - private def levelFor(eventClass: Class[_ <: Event]) = { - if (eventClass.isInstanceOf[Error]) ErrorLevel - else if (eventClass.isInstanceOf[Warning]) WarningLevel - else if (eventClass.isInstanceOf[Info]) InfoLevel - else if (eventClass.isInstanceOf[Debug]) DebugLevel - else DebugLevel - } - - class DefaultListener extends Actor { - self.id = ID - self.dispatcher = EventHandlerDispatcher - - def receive = { - case event@Error(cause, instance, message) => - println(error.format( - formattedTimestamp, - event.thread.getName, - instance.getClass.getSimpleName, - message, - stackTraceFor(cause))) - case event@Warning(instance, message) => - println(warning.format( - formattedTimestamp, - event.thread.getName, - instance.getClass.getSimpleName, - message)) - case event@Info(instance, message) => - println(info.format( - formattedTimestamp, - event.thread.getName, - instance.getClass.getSimpleName, - message)) - case event@Debug(instance, message) => - println(debug.format( - formattedTimestamp, - event.thread.getName, - instance.getClass.getSimpleName, - message)) - case event => - println(generic.format(formattedTimestamp, event.toString)) - } - } - - val defaultListeners = config.getList("akka.event-handlers") match { - case Nil => "akka.event.EventHandler$DefaultListener" :: Nil - case listeners => listeners - } - defaultListeners foreach { listenerName => - try { - ReflectiveAccess.getClassFor[Actor](listenerName) match { - case r: Right[_, Class[Actor]] => addListener(Actor.actorOf(r.b).start()) - case l: Left[Exception, _] => throw l.a - } - } catch { - case e: Exception => - throw new ConfigurationException( - "Event Handler specified in config can't be loaded [" + listenerName + - "] due to [" + e.toString + "]", e) - } - } -} diff --git a/test/files/presentation/akka/src/akka/event/JavaEventHandler.java b/test/files/presentation/akka/src/akka/event/JavaEventHandler.java deleted file mode 100644 index 7e6e2d4143..0000000000 --- a/test/files/presentation/akka/src/akka/event/JavaEventHandler.java +++ /dev/null @@ -1,35 +0,0 @@ -package akka.event; - - -import akka.actor.ActorRef; - -/** - * Java API for Akka EventHandler - */ - -public class JavaEventHandler { - - - public static void notify(Object message){ - EventHandler$.MODULE$.notify(message); - } - - public static void debug(ActorRef instance, Object message){ - EventHandler$.MODULE$.debug(instance, message); - } - - public static void info(ActorRef instance, Object message){ - EventHandler$.MODULE$.info(instance,message); - } - - public static void warning(ActorRef instance, Object message){ - EventHandler$.MODULE$.warning(instance,message); - } - - public static void error(ActorRef instance, Object message){ - EventHandler$.MODULE$.debug(instance,message); - } - -} - - diff --git a/test/files/presentation/akka/src/akka/japi/JavaAPI.scala b/test/files/presentation/akka/src/akka/japi/JavaAPI.scala deleted file mode 100644 index f5c4ccdcaa..0000000000 --- a/test/files/presentation/akka/src/akka/japi/JavaAPI.scala +++ /dev/null @@ -1,108 +0,0 @@ -package akka.japi - -/** - * A Function interface. Used to create first-class-functions is Java (sort of). - */ -trait Function[T, R] { - def apply(param: T): R -} - -/** - * A Function interface. Used to create 2-arg first-class-functions is Java (sort of). - */ -trait Function2[T1, T2, R] { - def apply(arg1: T1, arg2: T2): R -} - -/** - * A Procedure is like a Function, but it doesn't produce a return value - */ -trait Procedure[T] { - def apply(param: T): Unit -} - -/** - * A Procedure is like a Function, but it doesn't produce a return value - */ -trait Procedure2[T1, T2] { - def apply(param: T1, param2: T2): Unit -} - -/** - * An executable piece of code that takes no parameters and doesn't return any value. - */ -trait SideEffect { - def apply: Unit -} - -/** - * An executable piece of code that takes no parameters and doesn't return any value. - */ -trait Effect { - def apply: Unit -} - -/** - * + * A constructor/factory, takes no parameters but creates a new value of type T every call - * + - */ -trait Creator[T] { - def create: T -} - -/** - * This class represents optional values. Instances of Option - * are either instances of case class Some or it is case - * object None. - *

          - * Java API - */ -sealed abstract class Option[A] extends java.lang.Iterable[A] { - import scala.collection.JavaConversions._ - - def get: A - def isEmpty: Boolean - def isDefined = !isEmpty - def asScala: scala.Option[A] - def iterator = if (isEmpty) Iterator.empty else Iterator.single(get) -} - -object Option { - /** - * Option factory that creates Some - */ - def some[A](v: A): Option[A] = Some(v) - - /** - * Option factory that creates None - */ - def none[A] = None.asInstanceOf[Option[A]] - - /** - * Option factory that creates None if - * v is null, Some(v) otherwise. - */ - def option[A](v: A): Option[A] = if (v == null) none else some(v) - - /** - * Class Some[A] represents existing values of type - * A. - */ - final case class Some[A](v: A) extends Option[A] { - def get = v - def isEmpty = false - def asScala = scala.Some(v) - } - - /** - * This case object represents non-existent values. - */ - private case object None extends Option[Nothing] { - def get = throw new NoSuchElementException("None.get") - def isEmpty = true - def asScala = scala.None - } - - implicit def java2ScalaOption[A](o: Option[A]): scala.Option[A] = o.asScala - implicit def scala2JavaOption[A](o: scala.Option[A]): Option[A] = option(o.get) -} diff --git a/test/files/presentation/akka/src/akka/remoteinterface/RemoteEventHandler.scala b/test/files/presentation/akka/src/akka/remoteinterface/RemoteEventHandler.scala deleted file mode 100644 index 1c75618301..0000000000 --- a/test/files/presentation/akka/src/akka/remoteinterface/RemoteEventHandler.scala +++ /dev/null @@ -1,43 +0,0 @@ -package akka.remoteinterface - -/** - * Copyright (C) 2009-2011 Scalable Solutions AB - */ - -import akka.actor.Actor -import akka.event.EventHandler - -/** - * Remote client and server event listener that pipes the events to the standard Akka EventHander. - * - * @author Jonas Bonér - */ -class RemoteEventHandler extends Actor { - import EventHandler._ - - self.id = ID - self.dispatcher = EventHandlerDispatcher - - def receive = { - - // client - case RemoteClientError(cause, client, address) => EventHandler.error(cause, client, "RemoteClientError - Address[%s]" format address.toString) - case RemoteClientWriteFailed(request, cause, client, address) => EventHandler.error(cause, client, "RemoteClientWriteFailed - Request[%s] Address[%s]".format(address.toString)) - case RemoteClientDisconnected(client, address) => EventHandler.info(client, "RemoteClientDisconnected - Address[%s]" format address.toString) - case RemoteClientConnected(client, address) => EventHandler.info(client, "RemoteClientConnected - Address[%s]" format address.toString) - case RemoteClientStarted(client, address) => EventHandler.info(client, "RemoteClientStarted - Address[%s]" format address.toString) - case RemoteClientShutdown(client, address) => EventHandler.info(client, "RemoteClientShutdown - Address[%s]" format address.toString) - - // server - case RemoteServerError(cause, server) => EventHandler.error(cause, server, "RemoteServerError") - case RemoteServerWriteFailed(request, cause, server, clientAddress) => EventHandler.error(cause, server, "RemoteServerWriteFailed - Request[%s] Address[%s]" format (request, clientAddress.toString)) - case RemoteServerStarted(server) => EventHandler.info(server, "RemoteServerStarted") - case RemoteServerShutdown(server) => EventHandler.info(server, "RemoteServerShutdown") - case RemoteServerClientConnected(server, clientAddress) => EventHandler.info(server, "RemoteServerClientConnected - Address[%s]" format clientAddress.toString) - case RemoteServerClientDisconnected(server, clientAddress) => EventHandler.info(server, "RemoteServerClientDisconnected - Address[%s]" format clientAddress.toString) - case RemoteServerClientClosed(server, clientAddress) => EventHandler.info(server, "RemoteServerClientClosed - Address[%s]" format clientAddress.toString) - - case _ => //ignore other - } -} - diff --git a/test/files/presentation/akka/src/akka/remoteinterface/RemoteInterface.scala b/test/files/presentation/akka/src/akka/remoteinterface/RemoteInterface.scala deleted file mode 100644 index 0c5da82294..0000000000 --- a/test/files/presentation/akka/src/akka/remoteinterface/RemoteInterface.scala +++ /dev/null @@ -1,493 +0,0 @@ -/** - * Copyright (C) 2009-2010 Scalable Solutions AB - */ - -package akka.remoteinterface - -import akka.japi.Creator -import akka.actor._ -import akka.util._ -import akka.dispatch.CompletableFuture -import akka.AkkaException - -import scala.beans.BeanProperty - -import java.net.InetSocketAddress -import java.util.concurrent.ConcurrentHashMap -import java.io.{ PrintWriter, PrintStream } -import java.lang.reflect.InvocationTargetException - -trait RemoteModule { - val UUID_PREFIX = "uuid:".intern - - def optimizeLocalScoped_?(): Boolean //Apply optimizations for remote operations in local scope - protected[akka] def notifyListeners(message: => Any): Unit - - private[akka] def actors: ConcurrentHashMap[String, ActorRef] - private[akka] def actorsByUuid: ConcurrentHashMap[String, ActorRef] - private[akka] def actorsFactories: ConcurrentHashMap[String, () => ActorRef] - private[akka] def typedActors: ConcurrentHashMap[String, AnyRef] - private[akka] def typedActorsByUuid: ConcurrentHashMap[String, AnyRef] - private[akka] def typedActorsFactories: ConcurrentHashMap[String, () => AnyRef] - - /** Lookup methods **/ - - private[akka] def findActorById(id: String): ActorRef = actors.get(id) - - private[akka] def findActorByUuid(uuid: String): ActorRef = actorsByUuid.get(uuid) - - private[akka] def findActorFactory(id: String): () => ActorRef = actorsFactories.get(id) - - private[akka] def findTypedActorById(id: String): AnyRef = typedActors.get(id) - - private[akka] def findTypedActorFactory(id: String): () => AnyRef = typedActorsFactories.get(id) - - private[akka] def findTypedActorByUuid(uuid: String): AnyRef = typedActorsByUuid.get(uuid) - - private[akka] def findActorByIdOrUuid(id: String, uuid: String): ActorRef = { - var actorRefOrNull = if (id.startsWith(UUID_PREFIX)) findActorByUuid(id.substring(UUID_PREFIX.length)) - else findActorById(id) - if (actorRefOrNull eq null) actorRefOrNull = findActorByUuid(uuid) - actorRefOrNull - } - - private[akka] def findTypedActorByIdOrUuid(id: String, uuid: String): AnyRef = { - var actorRefOrNull = if (id.startsWith(UUID_PREFIX)) findTypedActorByUuid(id.substring(UUID_PREFIX.length)) - else findTypedActorById(id) - if (actorRefOrNull eq null) actorRefOrNull = findTypedActorByUuid(uuid) - actorRefOrNull - } -} - -/** - * Life-cycle events for RemoteClient. - */ -sealed trait RemoteClientLifeCycleEvent -case class RemoteClientError( - @BeanProperty cause: Throwable, - @BeanProperty client: RemoteClientModule, - @BeanProperty remoteAddress: InetSocketAddress) extends RemoteClientLifeCycleEvent -case class RemoteClientDisconnected( - @BeanProperty client: RemoteClientModule, - @BeanProperty remoteAddress: InetSocketAddress) extends RemoteClientLifeCycleEvent -case class RemoteClientConnected( - @BeanProperty client: RemoteClientModule, - @BeanProperty remoteAddress: InetSocketAddress) extends RemoteClientLifeCycleEvent -case class RemoteClientStarted( - @BeanProperty client: RemoteClientModule, - @BeanProperty remoteAddress: InetSocketAddress) extends RemoteClientLifeCycleEvent -case class RemoteClientShutdown( - @BeanProperty client: RemoteClientModule, - @BeanProperty remoteAddress: InetSocketAddress) extends RemoteClientLifeCycleEvent -case class RemoteClientWriteFailed( - @BeanProperty request: AnyRef, - @BeanProperty cause: Throwable, - @BeanProperty client: RemoteClientModule, - @BeanProperty remoteAddress: InetSocketAddress) extends RemoteClientLifeCycleEvent - -/** - * Life-cycle events for RemoteServer. - */ -sealed trait RemoteServerLifeCycleEvent -case class RemoteServerStarted( - @BeanProperty val server: RemoteServerModule) extends RemoteServerLifeCycleEvent -case class RemoteServerShutdown( - @BeanProperty val server: RemoteServerModule) extends RemoteServerLifeCycleEvent -case class RemoteServerError( - @BeanProperty val cause: Throwable, - @BeanProperty val server: RemoteServerModule) extends RemoteServerLifeCycleEvent -case class RemoteServerClientConnected( - @BeanProperty val server: RemoteServerModule, - @BeanProperty val clientAddress: Option[InetSocketAddress]) extends RemoteServerLifeCycleEvent -case class RemoteServerClientDisconnected( - @BeanProperty val server: RemoteServerModule, - @BeanProperty val clientAddress: Option[InetSocketAddress]) extends RemoteServerLifeCycleEvent -case class RemoteServerClientClosed( - @BeanProperty val server: RemoteServerModule, - @BeanProperty val clientAddress: Option[InetSocketAddress]) extends RemoteServerLifeCycleEvent -case class RemoteServerWriteFailed( - @BeanProperty request: AnyRef, - @BeanProperty cause: Throwable, - @BeanProperty server: RemoteServerModule, - @BeanProperty clientAddress: Option[InetSocketAddress]) extends RemoteServerLifeCycleEvent - -/** - * Thrown for example when trying to send a message using a RemoteClient that is either not started or shut down. - */ -class RemoteClientException private[akka] ( - message: String, - @BeanProperty val client: RemoteClientModule, - val remoteAddress: InetSocketAddress, cause: Throwable = null) extends AkkaException(message, cause) - -/** - * Thrown when the remote server actor dispatching fails for some reason. - */ -class RemoteServerException private[akka] (message: String) extends AkkaException(message) - -/** - * Thrown when a remote exception sent over the wire cannot be loaded and instantiated - */ -case class CannotInstantiateRemoteExceptionDueToRemoteProtocolParsingErrorException private[akka] (cause: Throwable, originalClassName: String, originalMessage: String) - extends AkkaException("\nParsingError[%s]\nOriginalException[%s]\nOriginalMessage[%s]" - .format(cause.toString, originalClassName, originalMessage)) { - override def printStackTrace = cause.printStackTrace - override def printStackTrace(printStream: PrintStream) = cause.printStackTrace(printStream) - override def printStackTrace(printWriter: PrintWriter) = cause.printStackTrace(printWriter) -} - -abstract class RemoteSupport extends ListenerManagement with RemoteServerModule with RemoteClientModule { - - lazy val eventHandler: ActorRef = { - val handler = Actor.actorOf[RemoteEventHandler].start() - // add the remote client and server listener that pipes the events to the event handler system - addListener(handler) - handler - } - - def shutdown() { - eventHandler.stop() - removeListener(eventHandler) - this.shutdownClientModule() - this.shutdownServerModule() - clear - } - - /** - * Creates a Client-managed ActorRef out of the Actor of the specified Class. - * If the supplied host and port is identical of the configured local node, it will be a local actor - *

          -   *   import Actor._
          -   *   val actor = actorOf(classOf[MyActor],"www.akka.io", 2552)
          -   *   actor.start()
          -   *   actor ! message
          -   *   actor.stop()
          -   * 
          - * You can create and start the actor in one statement like this: - *
          -   *   val actor = actorOf(classOf[MyActor],"www.akka.io", 2552).start()
          -   * 
          - */ - @deprecated("Will be removed after 1.1", "1.1") - def actorOf(factory: => Actor, host: String, port: Int): ActorRef = - Actor.remote.clientManagedActorOf(() => factory, host, port) - - /** - * Creates a Client-managed ActorRef out of the Actor of the specified Class. - * If the supplied host and port is identical of the configured local node, it will be a local actor - *
          -   *   import Actor._
          -   *   val actor = actorOf(classOf[MyActor],"www.akka.io",2552)
          -   *   actor.start()
          -   *   actor ! message
          -   *   actor.stop()
          -   * 
          - * You can create and start the actor in one statement like this: - *
          -   *   val actor = actorOf(classOf[MyActor],"www.akka.io",2552).start()
          -   * 
          - */ - @deprecated("Will be removed after 1.1", "1.1") - def actorOf(clazz: Class[_ <: Actor], host: String, port: Int): ActorRef = - clientManagedActorOf(() => createActorFromClass(clazz), host, port) - - /** - * Creates a Client-managed ActorRef out of the Actor of the specified Class. - * If the supplied host and port is identical of the configured local node, it will be a local actor - *
          -   *   import Actor._
          -   *   val actor = actorOf[MyActor]("www.akka.io",2552)
          -   *   actor.start()
          -   *   actor ! message
          -   *   actor.stop()
          -   * 
          - * You can create and start the actor in one statement like this: - *
          -   *   val actor = actorOf[MyActor]("www.akka.io",2552).start()
          -   * 
          - */ - @deprecated("Will be removed after 1.1", "1.1") - def actorOf[T <: Actor: Manifest](host: String, port: Int): ActorRef = - clientManagedActorOf(() => createActorFromClass(manifest.erasure), host, port) - - protected def createActorFromClass(clazz: Class[_]): Actor = { - import ReflectiveAccess.{ createInstance, noParams, noArgs } - createInstance[Actor](clazz, noParams, noArgs) match { - case Right(actor) => actor - case Left(exception) => - val cause = exception match { - case i: InvocationTargetException => i.getTargetException - case _ => exception - } - - throw new ActorInitializationException( - "Could not instantiate Actor of " + clazz + - "\nMake sure Actor is NOT defined inside a class/trait," + - "\nif so put it outside the class/trait, f.e. in a companion object," + - "\nOR try to change: 'actorOf[MyActor]' to 'actorOf(new MyActor)'.", cause) - } - } - - protected override def manageLifeCycleOfListeners = false - protected[akka] override def notifyListeners(message: => Any): Unit = super.notifyListeners(message) - - private[akka] val actors = new ConcurrentHashMap[String, ActorRef] - private[akka] val actorsByUuid = new ConcurrentHashMap[String, ActorRef] - private[akka] val actorsFactories = new ConcurrentHashMap[String, () => ActorRef] - private[akka] val typedActors = new ConcurrentHashMap[String, AnyRef] - private[akka] val typedActorsByUuid = new ConcurrentHashMap[String, AnyRef] - private[akka] val typedActorsFactories = new ConcurrentHashMap[String, () => AnyRef] - - def clear { - actors.clear - actorsByUuid.clear - typedActors.clear - typedActorsByUuid.clear - actorsFactories.clear - typedActorsFactories.clear - } -} - -/** - * This is the interface for the RemoteServer functionality, it's used in Actor.remote - */ -trait RemoteServerModule extends RemoteModule { - protected val guard = new ReentrantGuard - - /** - * Signals whether the server is up and running or not - */ - def isRunning: Boolean - - /** - * Gets the name of the server instance - */ - def name: String - - /** - * Gets the address of the server instance - */ - def address: InetSocketAddress - - /** - * Starts the server up - */ - def start(): RemoteServerModule = - start(ReflectiveAccess.Remote.configDefaultAddress.getAddress.getHostAddress, - ReflectiveAccess.Remote.configDefaultAddress.getPort, - None) - - /** - * Starts the server up - */ - def start(loader: ClassLoader): RemoteServerModule = - start(ReflectiveAccess.Remote.configDefaultAddress.getAddress.getHostAddress, - ReflectiveAccess.Remote.configDefaultAddress.getPort, - Option(loader)) - - /** - * Starts the server up - */ - def start(host: String, port: Int): RemoteServerModule = - start(host, port, None) - - /** - * Starts the server up - */ - def start(host: String, port: Int, loader: ClassLoader): RemoteServerModule = - start(host, port, Option(loader)) - - /** - * Starts the server up - */ - def start(host: String, port: Int, loader: Option[ClassLoader]): RemoteServerModule - - /** - * Shuts the server down - */ - def shutdownServerModule(): Unit - - /** - * Register typed actor by interface name. - */ - def registerTypedActor(intfClass: Class[_], typedActor: AnyRef): Unit = registerTypedActor(intfClass.getName, typedActor) - - /** - * Register remote typed actor by a specific id. - * @param id custom actor id - * @param typedActor typed actor to register - */ - def registerTypedActor(id: String, typedActor: AnyRef): Unit - - /** - * Register typed actor by interface name. - */ - def registerTypedPerSessionActor(intfClass: Class[_], factory: => AnyRef): Unit = registerTypedActor(intfClass.getName, factory) - - /** - * Register typed actor by interface name. - * Java API - */ - def registerTypedPerSessionActor(intfClass: Class[_], factory: Creator[AnyRef]): Unit = registerTypedActor(intfClass.getName, factory) - - /** - * Register remote typed actor by a specific id. - * @param id custom actor id - * @param typedActor typed actor to register - */ - def registerTypedPerSessionActor(id: String, factory: => AnyRef): Unit - - /** - * Register remote typed actor by a specific id. - * @param id custom actor id - * @param typedActor typed actor to register - * Java API - */ - def registerTypedPerSessionActor(id: String, factory: Creator[AnyRef]): Unit = registerTypedPerSessionActor(id, factory.create) - - /** - * Register Remote Actor by the Actor's 'id' field. It starts the Actor if it is not started already. - */ - def register(actorRef: ActorRef): Unit = register(actorRef.id, actorRef) - - /** - * Register Remote Actor by the Actor's uuid field. It starts the Actor if it is not started already. - */ - def registerByUuid(actorRef: ActorRef): Unit - - /** - * Register Remote Actor by a specific 'id' passed as argument. The actor is registered by UUID rather than ID - * when prefixing the handle with the “uuid:” protocol. - *

          - * NOTE: If you use this method to register your remote actor then you must unregister the actor by this ID yourself. - */ - def register(id: String, actorRef: ActorRef): Unit - - /** - * Register Remote Session Actor by a specific 'id' passed as argument. - *

          - * NOTE: If you use this method to register your remote actor then you must unregister the actor by this ID yourself. - */ - def registerPerSession(id: String, factory: => ActorRef): Unit - - /** - * Register Remote Session Actor by a specific 'id' passed as argument. - *

          - * NOTE: If you use this method to register your remote actor then you must unregister the actor by this ID yourself. - * Java API - */ - def registerPerSession(id: String, factory: Creator[ActorRef]): Unit = registerPerSession(id, factory.create) - - /** - * Unregister Remote Actor that is registered using its 'id' field (not custom ID). - */ - def unregister(actorRef: ActorRef): Unit - - /** - * Unregister Remote Actor by specific 'id'. - *

          - * NOTE: You need to call this method if you have registered an actor by a custom ID. - */ - def unregister(id: String): Unit - - /** - * Unregister Remote Actor by specific 'id'. - *

          - * NOTE: You need to call this method if you have registered an actor by a custom ID. - */ - def unregisterPerSession(id: String): Unit - - /** - * Unregister Remote Typed Actor by specific 'id'. - *

          - * NOTE: You need to call this method if you have registered an actor by a custom ID. - */ - def unregisterTypedActor(id: String): Unit - - /** - * Unregister Remote Typed Actor by specific 'id'. - *

          - * NOTE: You need to call this method if you have registered an actor by a custom ID. - */ - def unregisterTypedPerSessionActor(id: String): Unit -} - -trait RemoteClientModule extends RemoteModule { self: RemoteModule => - - def actorFor(classNameOrServiceId: String, hostname: String, port: Int): ActorRef = - actorFor(classNameOrServiceId, classNameOrServiceId, Actor.TIMEOUT, hostname, port, None) - - def actorFor(classNameOrServiceId: String, hostname: String, port: Int, loader: ClassLoader): ActorRef = - actorFor(classNameOrServiceId, classNameOrServiceId, Actor.TIMEOUT, hostname, port, Some(loader)) - - def actorFor(serviceId: String, className: String, hostname: String, port: Int): ActorRef = - actorFor(serviceId, className, Actor.TIMEOUT, hostname, port, None) - - def actorFor(serviceId: String, className: String, hostname: String, port: Int, loader: ClassLoader): ActorRef = - actorFor(serviceId, className, Actor.TIMEOUT, hostname, port, Some(loader)) - - def actorFor(classNameOrServiceId: String, timeout: Long, hostname: String, port: Int): ActorRef = - actorFor(classNameOrServiceId, classNameOrServiceId, timeout, hostname, port, None) - - def actorFor(classNameOrServiceId: String, timeout: Long, hostname: String, port: Int, loader: ClassLoader): ActorRef = - actorFor(classNameOrServiceId, classNameOrServiceId, timeout, hostname, port, Some(loader)) - - def actorFor(serviceId: String, className: String, timeout: Long, hostname: String, port: Int): ActorRef = - actorFor(serviceId, className, timeout, hostname, port, None) - - def typedActorFor[T](intfClass: Class[T], serviceIdOrClassName: String, hostname: String, port: Int): T = - typedActorFor(intfClass, serviceIdOrClassName, serviceIdOrClassName, Actor.TIMEOUT, hostname, port, None) - - def typedActorFor[T](intfClass: Class[T], serviceIdOrClassName: String, timeout: Long, hostname: String, port: Int): T = - typedActorFor(intfClass, serviceIdOrClassName, serviceIdOrClassName, timeout, hostname, port, None) - - def typedActorFor[T](intfClass: Class[T], serviceIdOrClassName: String, timeout: Long, hostname: String, port: Int, loader: ClassLoader): T = - typedActorFor(intfClass, serviceIdOrClassName, serviceIdOrClassName, timeout, hostname, port, Some(loader)) - - def typedActorFor[T](intfClass: Class[T], serviceId: String, implClassName: String, timeout: Long, hostname: String, port: Int, loader: ClassLoader): T = - typedActorFor(intfClass, serviceId, implClassName, timeout, hostname, port, Some(loader)) - - @deprecated("Will be removed after 1.1", "1.1") - def clientManagedActorOf(factory: () => Actor, host: String, port: Int): ActorRef - - /** - * Clean-up all open connections. - */ - def shutdownClientModule(): Unit - - /** - * Shuts down a specific client connected to the supplied remote address returns true if successful - */ - def shutdownClientConnection(address: InetSocketAddress): Boolean - - /** - * Restarts a specific client connected to the supplied remote address, but only if the client is not shut down - */ - def restartClientConnection(address: InetSocketAddress): Boolean - - /** Methods that needs to be implemented by a transport **/ - - protected[akka] def typedActorFor[T](intfClass: Class[T], serviceId: String, implClassName: String, timeout: Long, host: String, port: Int, loader: Option[ClassLoader]): T - - protected[akka] def actorFor(serviceId: String, className: String, timeout: Long, hostname: String, port: Int, loader: Option[ClassLoader]): ActorRef - - protected[akka] def send[T](message: Any, - senderOption: Option[ActorRef], - senderFuture: Option[CompletableFuture[T]], - remoteAddress: InetSocketAddress, - timeout: Long, - isOneWay: Boolean, - actorRef: ActorRef, - typedActorInfo: Option[Tuple2[String, String]], - actorType: ActorType, - loader: Option[ClassLoader]): Option[CompletableFuture[T]] - - private[akka] def registerSupervisorForActor(actorRef: ActorRef): ActorRef - - private[akka] def deregisterSupervisorForActor(actorRef: ActorRef): ActorRef - - @deprecated("Will be removed after 1.1", "1.1") - private[akka] def registerClientManagedActor(hostname: String, port: Int, uuid: Uuid): Unit - - @deprecated("Will be removed after 1.1", "1.1") - private[akka] def unregisterClientManagedActor(hostname: String, port: Int, uuid: Uuid): Unit -} diff --git a/test/files/presentation/akka/src/akka/routing/Iterators.scala b/test/files/presentation/akka/src/akka/routing/Iterators.scala deleted file mode 100644 index 315e7bea51..0000000000 --- a/test/files/presentation/akka/src/akka/routing/Iterators.scala +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Copyright (C) 2009-2011 Scalable Solutions AB - */ - -package akka.routing - -import akka.actor.ActorRef -import scala.collection.JavaConversions._ -import scala.collection.immutable.Seq - -/** - * An Iterator that is either always empty or yields an infinite number of Ts. - */ -trait InfiniteIterator[T] extends Iterator[T] { - val items: Seq[T] -} - -/** - * CyclicIterator is a round-robin style InfiniteIterator that cycles the supplied List. - */ -case class CyclicIterator[T](val items: Seq[T]) extends InfiniteIterator[T] { - def this(items: java.util.List[T]) = this(items.toList) - - @volatile - private[this] var current: Seq[T] = items - - def hasNext = items != Nil - - def next = { - val nc = if (current == Nil) items else current - current = nc.tail - nc.head - } - - override def exists(f: T => Boolean): Boolean = items.exists(f) -} - -/** - * This InfiniteIterator always returns the Actor that has the currently smallest mailbox - * useful for work-stealing. - */ -case class SmallestMailboxFirstIterator(val items: Seq[ActorRef]) extends InfiniteIterator[ActorRef] { - def this(items: java.util.List[ActorRef]) = this(items.toList) - def hasNext = items != Nil - - def next = items.reduceLeft((a1, a2) => if (a1.mailboxSize < a2.mailboxSize) a1 else a2) - - override def exists(f: ActorRef => Boolean): Boolean = items.exists(f) -} diff --git a/test/files/presentation/akka/src/akka/routing/Listeners.scala b/test/files/presentation/akka/src/akka/routing/Listeners.scala deleted file mode 100644 index 04f6c1259f..0000000000 --- a/test/files/presentation/akka/src/akka/routing/Listeners.scala +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Copyright (C) 2009-2011 Scalable Solutions AB - */ - -package akka.routing - -import akka.actor.{ Actor, ActorRef } -import java.util.concurrent.ConcurrentSkipListSet -import scala.collection.JavaConversions._ - -sealed trait ListenerMessage -case class Listen(listener: ActorRef) extends ListenerMessage -case class Deafen(listener: ActorRef) extends ListenerMessage -case class WithListeners(f: (ActorRef) => Unit) extends ListenerMessage - -/** - * Listeners is a generic trait to implement listening capability on an Actor. - *

          - * Use the gossip(msg) method to have it sent to the listeners. - *

          - * Send Listen(self) to start listening. - *

          - * Send Deafen(self) to stop listening. - *

          - * Send WithListeners(fun) to traverse the current listeners. - */ -trait Listeners { self: Actor => - private val listeners = new ConcurrentSkipListSet[ActorRef] - - protected def listenerManagement: Receive = { - case Listen(l) => listeners add l - case Deafen(l) => listeners remove l - case WithListeners(f) => listeners foreach f - } - - protected def gossip(msg: Any) = listeners foreach (_ ! msg) -} diff --git a/test/files/presentation/akka/src/akka/routing/Pool.scala b/test/files/presentation/akka/src/akka/routing/Pool.scala deleted file mode 100644 index 0fd1bc8f49..0000000000 --- a/test/files/presentation/akka/src/akka/routing/Pool.scala +++ /dev/null @@ -1,292 +0,0 @@ -/** - * Copyright (C) 2009-2011 Scalable Solutions AB - */ - -package akka.routing - -import akka.actor.{ Actor, ActorRef, PoisonPill } -import java.util.concurrent.TimeUnit - -/** - * Actor pooling - * - * An actor pool is an message router for a set of delegate actors. The pool is an actor itself. - * There are a handful of basic concepts that need to be understood when working with and defining your pool. - * - * Selectors - A selector is a trait that determines how and how many pooled actors will receive an incoming message. - * Capacitors - A capacitor is a trait that influences the size of pool. There are effectively two types. - * The first determines the size itself - either fixed or bounded. - * The second determines how to adjust of the pool according to some internal pressure characteristic. - * Filters - A filter can be used to refine the raw pressure value returned from a capacitor. - * - * It should be pointed out that all actors in the pool are treated as essentially equivalent. This is not to say - * that one couldn't instance different classes within the pool, only that the pool, when selecting and routing, - * will not take any type information into consideration. - * - * @author Garrick Evans - */ - -object ActorPool { - case object Stat - case class Stats(size: Int) -} - -/** - * Defines the nature of an actor pool. - */ -trait ActorPool { - def instance(): ActorRef //Question, Instance of what? - def capacity(delegates: Seq[ActorRef]): Int //Question, What is the semantics of this return value? - def select(delegates: Seq[ActorRef]): Tuple2[Iterator[ActorRef], Int] //Question, Why does select return this instead of an ordered Set? -} - -/** - * A default implementation of a pool, on each message to route, - * - checks the current capacity and adjusts accordingly if needed - * - routes the incoming message to a selection set of delegate actors - */ -trait DefaultActorPool extends ActorPool { this: Actor => - import ActorPool._ - import collection.mutable.LinkedList - import akka.actor.MaximumNumberOfRestartsWithinTimeRangeReached - - protected var _delegates = Vector[ActorRef]() - private var _lastCapacityChange = 0 - private var _lastSelectorCount = 0 - - override def postStop() = _delegates foreach { delegate => - try { - delegate ! PoisonPill - } catch { case e: Exception => } //Ignore any exceptions here - } - - protected def _route(): Receive = { - // for testing... - case Stat => - self reply_? Stats(_delegates length) - case max: MaximumNumberOfRestartsWithinTimeRangeReached => - _delegates = _delegates filterNot { _.uuid == max.victim.uuid } - case msg => - resizeIfAppropriate() - - select(_delegates) match { - case (selectedDelegates, count) => - _lastSelectorCount = count - selectedDelegates foreach { _ forward msg } //Should we really send the same message to several actors? - } - } - - private def resizeIfAppropriate() { - val requestedCapacity = capacity(_delegates) - val newDelegates = requestedCapacity match { - case qty if qty > 0 => - _delegates ++ { - for (i ← 0 until requestedCapacity) yield { - val delegate = instance() - self startLink delegate - delegate - } - } - case qty if qty < 0 => - _delegates.splitAt(_delegates.length + requestedCapacity) match { - case (keep, abandon) => - abandon foreach { _ ! PoisonPill } - keep - } - case _ => _delegates //No change - } - - _lastCapacityChange = requestedCapacity - _delegates = newDelegates - } -} - -/** - * Selectors - * These traits define how, when a message needs to be routed, delegate(s) are chosen from the pool - */ - -/** - * Returns the set of delegates with the least amount of message backlog. - */ -trait SmallestMailboxSelector { - def selectionCount: Int - def partialFill: Boolean - - def select(delegates: Seq[ActorRef]): Tuple2[Iterator[ActorRef], Int] = { - var set: Seq[ActorRef] = Nil - var take = if (partialFill) math.min(selectionCount, delegates.length) else selectionCount - - while (take > 0) { - set = delegates.sortWith(_.mailboxSize < _.mailboxSize).take(take) ++ set //Question, doesn't this risk selecting the same actor multiple times? - take -= set.size - } - - (set.iterator, set.size) - } -} - -/** - * Returns the set of delegates that occur sequentially 'after' the last delegate from the previous selection - */ -trait RoundRobinSelector { - private var _last: Int = -1; - - def selectionCount: Int - def partialFill: Boolean - - def select(delegates: Seq[ActorRef]): Tuple2[Iterator[ActorRef], Int] = { - val length = delegates.length - val take = if (partialFill) math.min(selectionCount, length) - else selectionCount - - val set = - for (i ← 0 until take) yield { - _last = (_last + 1) % length - delegates(_last) - } - - (set.iterator, set.size) - } -} - -/** - * Capacitors - * These traits define how to alter the size of the pool - */ - -/** - * Ensures a fixed number of delegates in the pool - */ -trait FixedSizeCapacitor { - def limit: Int - def capacity(delegates: Seq[ActorRef]): Int = (limit - delegates.size) max 0 -} - -/** - * Constrains the pool capacity to a bounded range - */ -trait BoundedCapacitor { - def lowerBound: Int - def upperBound: Int - - def capacity(delegates: Seq[ActorRef]): Int = { - val current = delegates length - val delta = _eval(delegates) - val proposed = current + delta - - if (proposed < lowerBound) delta + (lowerBound - proposed) - else if (proposed > upperBound) delta - (proposed - upperBound) - else delta - } - - protected def _eval(delegates: Seq[ActorRef]): Int -} - -/** - * Returns the number of delegates required to manage the current message backlogs - */ -trait MailboxPressureCapacitor { - def pressureThreshold: Int - def pressure(delegates: Seq[ActorRef]): Int = - delegates count { _.mailboxSize > pressureThreshold } -} - -/** - * Returns the number of delegates required to respond to the number of pending futures - */ -trait ActiveFuturesPressureCapacitor { - def pressure(delegates: Seq[ActorRef]): Int = - delegates count { _.senderFuture.isDefined } -} - -/** - */ -trait CapacityStrategy { - import ActorPool._ - - def pressure(delegates: Seq[ActorRef]): Int - def filter(pressure: Int, capacity: Int): Int - - protected def _eval(delegates: Seq[ActorRef]): Int = filter(pressure(delegates), delegates.size) -} - -trait FixedCapacityStrategy extends FixedSizeCapacitor -trait BoundedCapacityStrategy extends CapacityStrategy with BoundedCapacitor - -/** - * Filters - * These traits refine the raw pressure reading into a more appropriate capacity delta. - */ - -/** - * The basic filter trait that composes ramp-up and and back-off subfiltering. - */ -trait Filter { - def rampup(pressure: Int, capacity: Int): Int - def backoff(pressure: Int, capacity: Int): Int - - // pass through both filters just to be sure any internal counters - // are updated consistently. ramping up is always + and backing off - // is always - and each should return 0 otherwise... - def filter(pressure: Int, capacity: Int): Int = - rampup(pressure, capacity) + backoff(pressure, capacity) -} - -trait BasicFilter extends Filter with BasicRampup with BasicBackoff - -/** - * Filter performs steady incremental growth using only the basic ramp-up subfilter - */ -trait BasicNoBackoffFilter extends BasicRampup { - def filter(pressure: Int, capacity: Int): Int = rampup(pressure, capacity) -} - -/** - * Basic incremental growth as a percentage of the current pool capacity - */ -trait BasicRampup { - def rampupRate: Double - - def rampup(pressure: Int, capacity: Int): Int = - if (pressure < capacity) 0 else math.ceil(rampupRate * capacity) toInt -} - -/** - * Basic decrement as a percentage of the current pool capacity - */ -trait BasicBackoff { - def backoffThreshold: Double - def backoffRate: Double - - def backoff(pressure: Int, capacity: Int): Int = - if (capacity > 0 && pressure / capacity < backoffThreshold) math.ceil(-1.0 * backoffRate * capacity) toInt else 0 -} -/** - * This filter tracks the average pressure over the lifetime of the pool (or since last reset) and - * will begin to reduce capacity once this value drops below the provided threshold. The number of - * delegates to cull from the pool is determined by some scaling factor (the backoffRate) multiplied - * by the difference in capacity and pressure. - */ -trait RunningMeanBackoff { - def backoffThreshold: Double - def backoffRate: Double - - private var _pressure: Double = 0.0 - private var _capacity: Double = 0.0 - - def backoff(pressure: Int, capacity: Int): Int = { - _pressure += pressure - _capacity += capacity - - if (capacity > 0 && pressure / capacity < backoffThreshold - && _capacity > 0 && _pressure / _capacity < backoffThreshold) //Why does the entire clause need to be true? - math.floor(-1.0 * backoffRate * (capacity - pressure)).toInt - else 0 - } - - def backoffReset { - _pressure = 0.0 - _capacity = 0.0 - } -} diff --git a/test/files/presentation/akka/src/akka/routing/Routers.scala b/test/files/presentation/akka/src/akka/routing/Routers.scala deleted file mode 100644 index a4c34c5c67..0000000000 --- a/test/files/presentation/akka/src/akka/routing/Routers.scala +++ /dev/null @@ -1,87 +0,0 @@ -/** - * Copyright (C) 2009-2011 Scalable Solutions AB - */ - -package akka.routing - -import akka.actor.{ UntypedActor, Actor, ActorRef } - -/** - * A Dispatcher is a trait whose purpose is to route incoming messages to actors. - */ -trait Dispatcher { this: Actor => - - protected def transform(msg: Any): Any = msg - - protected def routes: PartialFunction[Any, ActorRef] - - protected def broadcast(message: Any) {} - - protected def dispatch: Receive = { - case Routing.Broadcast(message) => - broadcast(message) - case a if routes.isDefinedAt(a) => - if (isSenderDefined) routes(a).forward(transform(a))(someSelf) - else routes(a).!(transform(a))(None) - } - - def receive = dispatch - - private def isSenderDefined = self.senderFuture.isDefined || self.sender.isDefined -} - -/** - * An UntypedDispatcher is an abstract class whose purpose is to route incoming messages to actors. - */ -abstract class UntypedDispatcher extends UntypedActor { - protected def transform(msg: Any): Any = msg - - protected def route(msg: Any): ActorRef - - protected def broadcast(message: Any) {} - - private def isSenderDefined = self.senderFuture.isDefined || self.sender.isDefined - - @throws(classOf[Exception]) - def onReceive(msg: Any): Unit = { - if (msg.isInstanceOf[Routing.Broadcast]) broadcast(msg.asInstanceOf[Routing.Broadcast].message) - else { - val r = route(msg) - if (r eq null) throw new IllegalStateException("No route for " + msg + " defined!") - if (isSenderDefined) r.forward(transform(msg))(someSelf) - else r.!(transform(msg))(None) - } - } -} - -/** - * A LoadBalancer is a specialized kind of Dispatcher, that is supplied an InfiniteIterator of targets - * to dispatch incoming messages to. - */ -trait LoadBalancer extends Dispatcher { self: Actor => - protected def seq: InfiniteIterator[ActorRef] - - protected def routes = { - case x if seq.hasNext => seq.next - } - - override def broadcast(message: Any) = seq.items.foreach(_ ! message) - - override def isDefinedAt(msg: Any) = seq.exists(_.isDefinedAt(msg)) -} - -/** - * A UntypedLoadBalancer is a specialized kind of UntypedDispatcher, that is supplied an InfiniteIterator of targets - * to dispatch incoming messages to. - */ -abstract class UntypedLoadBalancer extends UntypedDispatcher { - protected def seq: InfiniteIterator[ActorRef] - - protected def route(msg: Any) = - if (seq.hasNext) seq.next - else null - - override def broadcast(message: Any) = seq.items.foreach(_ ! message) - - override def isDefinedAt(msg: Any) = seq.exists(_.isDefinedAt(msg)) -} diff --git a/test/files/presentation/akka/src/akka/routing/Routing.scala b/test/files/presentation/akka/src/akka/routing/Routing.scala deleted file mode 100644 index befc124248..0000000000 --- a/test/files/presentation/akka/src/akka/routing/Routing.scala +++ /dev/null @@ -1,64 +0,0 @@ -/** - * Copyright (C) 2009-2011 Scalable Solutions AB - */ - -package akka.routing - -import akka.actor.{ Actor, ActorRef } -import akka.actor.Actor._ - -object Routing { - - sealed trait RoutingMessage - case class Broadcast(message: Any) extends RoutingMessage - - type PF[A, B] = PartialFunction[A, B] - - /** - * Creates a new PartialFunction whose isDefinedAt is a combination - * of the two parameters, and whose apply is first to call filter.apply - * and then filtered.apply. - */ - def filter[A, B](filter: PF[A, Unit], filtered: PF[A, B]): PF[A, B] = { - case a: A if filtered.isDefinedAt(a) && filter.isDefinedAt(a) => - filter(a) - filtered(a) - } - - /** - * Interceptor is a filter(x,y) where x.isDefinedAt is considered to be always true. - */ - def intercept[A, B](interceptor: (A) => Unit, interceptee: PF[A, B]): PF[A, B] = - filter({ case a if a.isInstanceOf[A] => interceptor(a) }, interceptee) - - /** - * Creates a LoadBalancer from the thunk-supplied InfiniteIterator. - */ - def loadBalancerActor(actors: => InfiniteIterator[ActorRef]): ActorRef = - actorOf(new Actor with LoadBalancer { - val seq = actors - }).start() - - /** - * Creates a Dispatcher given a routing and a message-transforming function. - */ - def dispatcherActor(routing: PF[Any, ActorRef], msgTransformer: (Any) => Any): ActorRef = - actorOf(new Actor with Dispatcher { - override def transform(msg: Any) = msgTransformer(msg) - def routes = routing - }).start() - - /** - * Creates a Dispatcher given a routing. - */ - def dispatcherActor(routing: PF[Any, ActorRef]): ActorRef = actorOf(new Actor with Dispatcher { - def routes = routing - }).start() - - /** - * Creates an actor that pipes all incoming messages to - * both another actor and through the supplied function - */ - def loggerActor(actorToLog: ActorRef, logger: (Any) => Unit): ActorRef = - dispatcherActor({ case _ => actorToLog }, logger) -} diff --git a/test/files/presentation/akka/src/akka/util/Address.scala b/test/files/presentation/akka/src/akka/util/Address.scala deleted file mode 100644 index 65b5c0a834..0000000000 --- a/test/files/presentation/akka/src/akka/util/Address.scala +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Copyright (C) 2009-2011 Scalable Solutions AB - */ -package akka.util - -import java.net.InetSocketAddress - -object Address { - def apply(hostname: String, port: Int) = new Address(hostname, port) - def apply(inetAddress: InetSocketAddress): Address = inetAddress match { - case null => null - case inet => new Address(inet.getAddress.getHostAddress, inet.getPort) - } -} - -class Address(val hostname: String, val port: Int) { - override val hashCode: Int = { - var result = HashCode.SEED - result = HashCode.hash(result, hostname) - result = HashCode.hash(result, port) - result - } - - override def equals(that: Any): Boolean = { - that.isInstanceOf[Address] && - that.asInstanceOf[Address].hostname == hostname && - that.asInstanceOf[Address].port == port - } -} diff --git a/test/files/presentation/akka/src/akka/util/AkkaLoader.scala b/test/files/presentation/akka/src/akka/util/AkkaLoader.scala deleted file mode 100644 index cb246f2ecf..0000000000 --- a/test/files/presentation/akka/src/akka/util/AkkaLoader.scala +++ /dev/null @@ -1,94 +0,0 @@ -/** - * Copyright (C) 2009-2011 Scalable Solutions AB - */ - -package akka.util - -import akka.config.Config -import akka.actor.Actor - -/* - * This class is responsible for booting up a stack of bundles and then shutting them down - */ -class AkkaLoader { - private val hasBooted = new Switch(false) - - @volatile - private var _bundles: Option[Bootable] = None - - def bundles = _bundles; - - /* - * Boot initializes the specified bundles - */ - def boot(withBanner: Boolean, b: Bootable): Unit = hasBooted switchOn { - if (withBanner) printBanner() - println("Starting Akka...") - b.onLoad - Thread.currentThread.setContextClassLoader(getClass.getClassLoader) - _bundles = Some(b) - println("Akka started successfully") - } - - /* - * Shutdown, well, shuts down the bundles used in boot - */ - def shutdown() { - hasBooted switchOff { - println("Shutting down Akka...") - _bundles.foreach(_.onUnload) - _bundles = None - Actor.shutdownHook.run - println("Akka succesfully shut down") - } - } - - private def printBanner() { - println(""" -============================================================================== - - ZZ: - ZZZZ - ZZZZZZ - ZZZ' ZZZ - ~7 7ZZ' ZZZ - :ZZZ: IZZ' ZZZ - ,OZZZZ.~ZZ? ZZZ - ZZZZ' 'ZZZ$ ZZZ - . $ZZZ ~ZZ$ ZZZ - .=Z?. .ZZZO ~ZZ7 OZZ - .ZZZZ7..:ZZZ~ 7ZZZ ZZZ~ - .$ZZZ$Z+.ZZZZ ZZZ: ZZZ$ - .,ZZZZ?' =ZZO= .OZZ 'ZZZ - .$ZZZZ+ .ZZZZ IZZZ ZZZ$ - .ZZZZZ' .ZZZZ' .ZZZ$ ?ZZZ - .ZZZZZZ' .OZZZ? ?ZZZ 'ZZZ$ - .?ZZZZZZ' .ZZZZ? .ZZZ? 'ZZZO - .+ZZZZZZ?' .7ZZZZ' .ZZZZ :ZZZZ - .ZZZZZZ$' .?ZZZZZ' .~ZZZZ 'ZZZZ. - - - NNNNN $NNNN+ - NNNNN $NNNN+ - NNNNN $NNNN+ - NNNNN $NNNN+ - NNNNN $NNNN+ - =NNNNNNNNND$ NNNNN DDDDDD: $NNNN+ DDDDDN NDDNNNNNNNN, - NNNNNNNNNNNNND NNNNN DNNNNN $NNNN+ 8NNNNN= :NNNNNNNNNNNNNN - NNNNN$ DNNNNN NNNNN $NNNNN~ $NNNN+ NNNNNN NNNNN, :NNNNN+ - ?DN~ NNNNN NNNNN MNNNNN $NNNN+:NNNNN7 $ND =NNNNN - DNNNNN NNNNNDNNNN$ $NNNNDNNNNN :DNNNNN - ZNDNNNNNNNNND NNNNNNNNNND, $NNNNNNNNNNN DNDNNNNNNNNNN - NNNNNNNDDINNNNN NNNNNNNNNNND $NNNNNNNNNNND ONNNNNNND8+NNNNN - :NNNND NNNNN NNNNNN DNNNN, $NNNNNO 7NNNND NNNNNO :NNNNN - DNNNN NNNNN NNNNN DNNNN $NNNN+ 8NNNNN NNNNN $NNNNN - DNNNNO NNNNNN NNNNN NNNNN $NNNN+ NNNNN$ NNNND, ,NNNNND - NNNNNNDDNNNNNNNN NNNNN =NNNNN $NNNN+ DNNNN? DNNNNNNDNNNNNNNND - NNNNNNNNN NNNN$ NNNNN 8NNNND $NNNN+ NNNNN= ,DNNNNNNND NNNNN$ - -============================================================================== - Running version %s -============================================================================== -""".format(Config.VERSION)) - } -} diff --git a/test/files/presentation/akka/src/akka/util/Bootable.scala b/test/files/presentation/akka/src/akka/util/Bootable.scala deleted file mode 100644 index d07643e1ac..0000000000 --- a/test/files/presentation/akka/src/akka/util/Bootable.scala +++ /dev/null @@ -1,10 +0,0 @@ -/** - * Copyright (C) 2009-2011 Scalable Solutions AB - */ - -package akka.util - -trait Bootable { - def onLoad() {} - def onUnload() {} -} diff --git a/test/files/presentation/akka/src/akka/util/BoundedBlockingQueue.scala b/test/files/presentation/akka/src/akka/util/BoundedBlockingQueue.scala deleted file mode 100644 index f8deda746c..0000000000 --- a/test/files/presentation/akka/src/akka/util/BoundedBlockingQueue.scala +++ /dev/null @@ -1,326 +0,0 @@ -/** - * Copyright (C) 2009-2011 Scalable Solutions AB - */ - -package akka.util - -import java.util.concurrent.locks.ReentrantLock -import java.util.concurrent.{ TimeUnit, BlockingQueue } -import java.util.{ AbstractQueue, Queue, Collection, Iterator } - -class BoundedBlockingQueue[E <: AnyRef]( - val maxCapacity: Int, private val backing: Queue[E]) extends AbstractQueue[E] with BlockingQueue[E] { - - backing match { - case null => throw new IllegalArgumentException("Backing Queue may not be null") - case b: BlockingQueue[_] => - require(maxCapacity > 0) - require(b.size() == 0) - require(b.remainingCapacity >= maxCapacity) - case b: Queue[_] => - require(b.size() == 0) - require(maxCapacity > 0) - } - - protected val lock = new ReentrantLock(false) - - private val notEmpty = lock.newCondition() - private val notFull = lock.newCondition() - - def put(e: E): Unit = { //Blocks until not full - if (e eq null) throw new NullPointerException - lock.lock() - try { - while (backing.size() == maxCapacity) - notFull.await() - require(backing.offer(e)) - notEmpty.signal() - } finally { - lock.unlock() - } - } - - def take(): E = { //Blocks until not empty - lock.lockInterruptibly() - try { - while (backing.size() == 0) - notEmpty.await() - val e = backing.poll() - require(e ne null) - notFull.signal() - e - } finally { - lock.unlock() - } - } - - def offer(e: E): Boolean = { //Tries to do it immediately, if fail return false - if (e eq null) throw new NullPointerException - lock.lock() - try { - if (backing.size() == maxCapacity) false - else { - require(backing.offer(e)) //Should never fail - notEmpty.signal() - true - } - } finally { - lock.unlock() - } - } - - def offer(e: E, timeout: Long, unit: TimeUnit): Boolean = { //Tries to do it within the timeout, return false if fail - if (e eq null) throw new NullPointerException - var nanos = unit.toNanos(timeout) - lock.lockInterruptibly() - try { - while (backing.size() == maxCapacity) { - if (nanos <= 0) - return false - else - nanos = notFull.awaitNanos(nanos) - } - require(backing.offer(e)) //Should never fail - notEmpty.signal() - true - } finally { - lock.unlock() - } - } - - def poll(timeout: Long, unit: TimeUnit): E = { //Tries to do it within the timeout, returns null if fail - var nanos = unit.toNanos(timeout) - lock.lockInterruptibly() - try { - var result: E = null.asInstanceOf[E] - var hasResult = false - while (!hasResult) { - hasResult = backing.poll() match { - case null if nanos <= 0 => - result = null.asInstanceOf[E] - true - case null => - try { - nanos = notEmpty.awaitNanos(nanos) - } catch { - case ie: InterruptedException => - notEmpty.signal() - throw ie - } - false - case e => - notFull.signal() - result = e - true - } - } - result - } finally { - lock.unlock() - } - } - - def poll(): E = { //Tries to remove the head of the queue immediately, if fail, return null - lock.lock() - try { - backing.poll() match { - case null => null.asInstanceOf[E] - case e => - notFull.signal() - e - } - } finally { - lock.unlock - } - } - - override def remove(e: AnyRef): Boolean = { //Tries to do it immediately, if fail, return false - if (e eq null) throw new NullPointerException - lock.lock() - try { - if (backing remove e) { - notFull.signal() - true - } else false - } finally { - lock.unlock() - } - } - - override def contains(e: AnyRef): Boolean = { - if (e eq null) throw new NullPointerException - lock.lock() - try { - backing contains e - } finally { - lock.unlock() - } - } - - override def clear(): Unit = { - lock.lock() - try { - backing.clear - } finally { - lock.unlock() - } - } - - def remainingCapacity(): Int = { - lock.lock() - try { - maxCapacity - backing.size() - } finally { - lock.unlock() - } - } - - def size(): Int = { - lock.lock() - try { - backing.size() - } finally { - lock.unlock() - } - } - - def peek(): E = { - lock.lock() - try { - backing.peek() - } finally { - lock.unlock() - } - } - - def drainTo(c: Collection[_ >: E]): Int = drainTo(c, Int.MaxValue) - - def drainTo(c: Collection[_ >: E], maxElements: Int): Int = { - if (c eq null) throw new NullPointerException - if (c eq this) throw new IllegalArgumentException - if (maxElements <= 0) 0 - else { - lock.lock() - try { - var n = 0 - var e: E = null.asInstanceOf[E] - while (n < maxElements) { - backing.poll() match { - case null => return n - case e => - c add e - n += 1 - } - } - n - } finally { - lock.unlock() - } - } - } - - override def containsAll(c: Collection[_]): Boolean = { - lock.lock() - try { - backing containsAll c - } finally { - lock.unlock() - } - } - - override def removeAll(c: Collection[_]): Boolean = { - lock.lock() - try { - if (backing.removeAll(c)) { - val sz = backing.size() - if (sz < maxCapacity) notFull.signal() - if (sz > 0) notEmpty.signal() //FIXME needed? - true - } else false - } finally { - lock.unlock() - } - } - - override def retainAll(c: Collection[_]): Boolean = { - lock.lock() - try { - if (backing.retainAll(c)) { - val sz = backing.size() - if (sz < maxCapacity) notFull.signal() //FIXME needed? - if (sz > 0) notEmpty.signal() - true - } else false - } finally { - lock.unlock() - } - } - - def iterator(): Iterator[E] = { - lock.lock - try { - val elements = backing.toArray - new Iterator[E] { - var at = 0 - var last = -1 - - def hasNext(): Boolean = at < elements.length - - def next(): E = { - if (at >= elements.length) throw new NoSuchElementException - last = at - at += 1 - elements(last).asInstanceOf[E] - } - - def remove(): Unit = { - if (last < 0) throw new IllegalStateException - val target = elements(last) - last = -1 //To avoid 2 subsequent removes without a next in between - lock.lock() - try { - val i = backing.iterator() - while (i.hasNext) { - if (i.next eq target) { - i.remove() - notFull.signal() - return () - } - } - } finally { - lock.unlock() - } - } - } - } finally { - lock.unlock - } - } - - override def toArray(): Array[AnyRef] = { - lock.lock() - try { - backing.toArray - } finally { - lock.unlock() - } - } - - override def isEmpty(): Boolean = { - lock.lock() - try { - backing.isEmpty() - } finally { - lock.unlock() - } - } - - override def toArray[X](a: Array[X with AnyRef]) = { - lock.lock() - try { - backing.toArray[X](a) - } finally { - lock.unlock() - } - } -} diff --git a/test/files/presentation/akka/src/akka/util/Crypt.scala b/test/files/presentation/akka/src/akka/util/Crypt.scala deleted file mode 100644 index 3ce2d559a2..0000000000 --- a/test/files/presentation/akka/src/akka/util/Crypt.scala +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Copyright (C) 2009-2011 Scalable Solutions AB - */ - -package akka.util - -import java.security.{ MessageDigest, SecureRandom } - -/** - * @author Jonas Bonér - */ -object Crypt { - val hex = "0123456789ABCDEF" - val lineSeparator = System.getProperty("line.separator") - - lazy val random = SecureRandom.getInstance("SHA1PRNG") - - def md5(text: String): String = md5(unifyLineSeparator(text).getBytes("ASCII")) - - def md5(bytes: Array[Byte]): String = digest(bytes, MessageDigest.getInstance("MD5")) - - def sha1(text: String): String = sha1(unifyLineSeparator(text).getBytes("ASCII")) - - def sha1(bytes: Array[Byte]): String = digest(bytes, MessageDigest.getInstance("SHA1")) - - def generateSecureCookie: String = { - val bytes = Array.fill(32)(0.byteValue) - random.nextBytes(bytes) - sha1(bytes) - } - - def digest(bytes: Array[Byte], md: MessageDigest): String = { - md.update(bytes) - hexify(md.digest) - } - - def hexify(bytes: Array[Byte]): String = { - val builder = new StringBuilder - bytes.foreach { byte => builder.append(hex.charAt((byte & 0xF) >> 4)).append(hex.charAt(byte & 0xF)) } - builder.toString - } - - private def unifyLineSeparator(text: String): String = text.replaceAll(lineSeparator, "\n") -} diff --git a/test/files/presentation/akka/src/akka/util/Duration.scala b/test/files/presentation/akka/src/akka/util/Duration.scala deleted file mode 100644 index 316cb86689..0000000000 --- a/test/files/presentation/akka/src/akka/util/Duration.scala +++ /dev/null @@ -1,437 +0,0 @@ -/** - * Copyright (C) 2009-2011 Scalable Solutions AB - */ - -package akka.util - -import java.util.concurrent.TimeUnit -import TimeUnit._ -import java.lang.{ Long => JLong, Double => JDouble } - -object Duration { - def apply(length: Long, unit: TimeUnit): Duration = new FiniteDuration(length, unit) - def apply(length: Double, unit: TimeUnit): Duration = fromNanos(unit.toNanos(1) * length) - def apply(length: Long, unit: String): Duration = new FiniteDuration(length, timeUnit(unit)) - - def fromNanos(nanos: Long): Duration = { - if (nanos % 86400000000000L == 0) { - Duration(nanos / 86400000000000L, DAYS) - } else if (nanos % 3600000000000L == 0) { - Duration(nanos / 3600000000000L, HOURS) - } else if (nanos % 60000000000L == 0) { - Duration(nanos / 60000000000L, MINUTES) - } else if (nanos % 1000000000L == 0) { - Duration(nanos / 1000000000L, SECONDS) - } else if (nanos % 1000000L == 0) { - Duration(nanos / 1000000L, MILLISECONDS) - } else if (nanos % 1000L == 0) { - Duration(nanos / 1000L, MICROSECONDS) - } else { - Duration(nanos, NANOSECONDS) - } - } - - def fromNanos(nanos: Double): Duration = fromNanos((nanos + 0.5).asInstanceOf[Long]) - - /** - * Construct a Duration by parsing a String. In case of a format error, a - * RuntimeException is thrown. See `unapply(String)` for more information. - */ - def apply(s: String): Duration = unapply(s) getOrElse sys.error("format error") - - /** - * Deconstruct a Duration into length and unit if it is finite. - */ - def unapply(d: Duration): Option[(Long, TimeUnit)] = { - if (d.finite_?) { - Some((d.length, d.unit)) - } else { - None - } - } - - private val RE = ("""^\s*(\d+(?:\.\d+)?)\s*""" + // length part - "(?:" + // units are distinguished in separate match groups - "(d|day|days)|" + - "(h|hour|hours)|" + - "(min|minute|minutes)|" + - "(s|sec|second|seconds)|" + - "(ms|milli|millis|millisecond|milliseconds)|" + - "(µs|micro|micros|microsecond|microseconds)|" + - "(ns|nano|nanos|nanosecond|nanoseconds)" + - """)\s*$""").r // close the non-capturing group - private val REinf = """^\s*Inf\s*$""".r - private val REminf = """^\s*(?:-\s*|Minus)Inf\s*""".r - - /** - * Parse String, return None if no match. Format is `""`, where - * whitespace is allowed before, between and after the parts. Infinities are - * designated by `"Inf"` and `"-Inf"` or `"MinusInf"`. - */ - def unapply(s: String): Option[Duration] = s match { - case RE(length, d, h, m, s, ms, mus, ns) => - if (d ne null) Some(Duration(JDouble.parseDouble(length), DAYS)) else if (h ne null) Some(Duration(JDouble.parseDouble(length), HOURS)) else if (m ne null) Some(Duration(JDouble.parseDouble(length), MINUTES)) else if (s ne null) Some(Duration(JDouble.parseDouble(length), SECONDS)) else if (ms ne null) Some(Duration(JDouble.parseDouble(length), MILLISECONDS)) else if (mus ne null) Some(Duration(JDouble.parseDouble(length), MICROSECONDS)) else if (ns ne null) Some(Duration(JDouble.parseDouble(length), NANOSECONDS)) else - sys.error("made some error in regex (should not be possible)") - case REinf() => Some(Inf) - case REminf() => Some(MinusInf) - case _ => None - } - - /** - * Parse TimeUnit from string representation. - */ - def timeUnit(unit: String) = unit.toLowerCase match { - case "d" | "day" | "days" => DAYS - case "h" | "hour" | "hours" => HOURS - case "min" | "minute" | "minutes" => MINUTES - case "s" | "sec" | "second" | "seconds" => SECONDS - case "ms" | "milli" | "millis" | "millisecond" | "milliseconds" => MILLISECONDS - case "µs" | "micro" | "micros" | "microsecond" | "microseconds" => MICROSECONDS - case "ns" | "nano" | "nanos" | "nanosecond" | "nanoseconds" => NANOSECONDS - } - - val Zero: Duration = new FiniteDuration(0, NANOSECONDS) - - trait Infinite { - this: Duration => - - override def equals(other: Any) = false - - def +(other: Duration): Duration = - other match { - case _: this.type => this - case _: Infinite => throw new IllegalArgumentException("illegal addition of infinities") - case _ => this - } - def -(other: Duration): Duration = - other match { - case _: this.type => throw new IllegalArgumentException("illegal subtraction of infinities") - case _ => this - } - def *(factor: Double): Duration = this - def /(factor: Double): Duration = this - def /(other: Duration): Double = - other match { - case _: Infinite => throw new IllegalArgumentException("illegal division of infinities") - // maybe questionable but pragmatic: Inf / 0 => Inf - case x => Double.PositiveInfinity * (if ((this > Zero) ^ (other >= Zero)) -1 else 1) - } - - def finite_? = false - - def length: Long = throw new IllegalArgumentException("length not allowed on infinite Durations") - def unit: TimeUnit = throw new IllegalArgumentException("unit not allowed on infinite Durations") - def toNanos: Long = throw new IllegalArgumentException("toNanos not allowed on infinite Durations") - def toMicros: Long = throw new IllegalArgumentException("toMicros not allowed on infinite Durations") - def toMillis: Long = throw new IllegalArgumentException("toMillis not allowed on infinite Durations") - def toSeconds: Long = throw new IllegalArgumentException("toSeconds not allowed on infinite Durations") - def toMinutes: Long = throw new IllegalArgumentException("toMinutes not allowed on infinite Durations") - def toHours: Long = throw new IllegalArgumentException("toHours not allowed on infinite Durations") - def toDays: Long = throw new IllegalArgumentException("toDays not allowed on infinite Durations") - def toUnit(unit: TimeUnit): Double = throw new IllegalArgumentException("toUnit not allowed on infinite Durations") - - def printHMS = toString - } - - /** - * Infinite duration: greater than any other and not equal to any other, - * including itself. - */ - val Inf: Duration = new Duration with Infinite { - override def toString = "Duration.Inf" - def >(other: Duration) = true - def >=(other: Duration) = true - def <(other: Duration) = false - def <=(other: Duration) = false - def unary_- : Duration = MinusInf - } - - /** - * Infinite negative duration: lesser than any other and not equal to any other, - * including itself. - */ - val MinusInf: Duration = new Duration with Infinite { - override def toString = "Duration.MinusInf" - def >(other: Duration) = false - def >=(other: Duration) = false - def <(other: Duration) = true - def <=(other: Duration) = true - def unary_- : Duration = Inf - } - - // Java Factories - def create(length: Long, unit: TimeUnit): Duration = apply(length, unit) - def create(length: Double, unit: TimeUnit): Duration = apply(length, unit) - def create(length: Long, unit: String): Duration = apply(length, unit) - def parse(s: String): Duration = unapply(s).get -} - -/** - * Utility for working with java.util.concurrent.TimeUnit durations. - * - *

          - * Examples of usage from Java: - *

          - * import akka.util.FiniteDuration;
          - * import java.util.concurrent.TimeUnit;
          - *
          - * Duration duration = new FiniteDuration(100, MILLISECONDS);
          - * Duration duration = new FiniteDuration(5, "seconds");
          - *
          - * duration.toNanos();
          - * 
          - * - *

          - * Examples of usage from Scala: - *

          - * import akka.util.Duration
          - * import java.util.concurrent.TimeUnit
          - *
          - * val duration = Duration(100, MILLISECONDS)
          - * val duration = Duration(100, "millis")
          - *
          - * duration.toNanos
          - * duration < 1.second
          - * duration <= Duration.Inf
          - * 
          - * - *

          - * Implicits are also provided for Int, Long and Double. Example usage: - *

          - * import akka.util.duration._
          - *
          - * val duration = 100 millis
          - * 
          - * - * Extractors, parsing and arithmetic are also included: - *
          - * val d = Duration("1.2 µs")
          - * val Duration(length, unit) = 5 millis
          - * val d2 = d * 2.5
          - * val d3 = d2 + 1.millisecond
          - * 
          - */ -abstract class Duration { - def length: Long - def unit: TimeUnit - def toNanos: Long - def toMicros: Long - def toMillis: Long - def toSeconds: Long - def toMinutes: Long - def toHours: Long - def toDays: Long - def toUnit(unit: TimeUnit): Double - def printHMS: String - def <(other: Duration): Boolean - def <=(other: Duration): Boolean - def >(other: Duration): Boolean - def >=(other: Duration): Boolean - def +(other: Duration): Duration - def -(other: Duration): Duration - def *(factor: Double): Duration - def /(factor: Double): Duration - def /(other: Duration): Double - def unary_- : Duration - def finite_? : Boolean - - // Java API - def lt(other: Duration) = this < other - def lteq(other: Duration) = this <= other - def gt(other: Duration) = this > other - def gteq(other: Duration) = this >= other - def plus(other: Duration) = this + other - def minus(other: Duration) = this - other - def mul(factor: Double) = this * factor - def div(factor: Double) = this / factor - def div(other: Duration) = this / other - def neg() = -this - def isFinite() = finite_? -} - -class FiniteDuration(val length: Long, val unit: TimeUnit) extends Duration { - import Duration._ - - def this(length: Long, unit: String) = this(length, Duration.timeUnit(unit)) - - def toNanos = unit.toNanos(length) - def toMicros = unit.toMicros(length) - def toMillis = unit.toMillis(length) - def toSeconds = unit.toSeconds(length) - def toMinutes = unit.toMinutes(length) - def toHours = unit.toHours(length) - def toDays = unit.toDays(length) - def toUnit(u: TimeUnit) = long2double(toNanos) / NANOSECONDS.convert(1, u) - - override def toString = this match { - case Duration(1, DAYS) => "1 day" - case Duration(x, DAYS) => x + " days" - case Duration(1, HOURS) => "1 hour" - case Duration(x, HOURS) => x + " hours" - case Duration(1, MINUTES) => "1 minute" - case Duration(x, MINUTES) => x + " minutes" - case Duration(1, SECONDS) => "1 second" - case Duration(x, SECONDS) => x + " seconds" - case Duration(1, MILLISECONDS) => "1 millisecond" - case Duration(x, MILLISECONDS) => x + " milliseconds" - case Duration(1, MICROSECONDS) => "1 microsecond" - case Duration(x, MICROSECONDS) => x + " microseconds" - case Duration(1, NANOSECONDS) => "1 nanosecond" - case Duration(x, NANOSECONDS) => x + " nanoseconds" - } - - def printHMS = "%02d:%02d:%06.3f".format(toHours, toMinutes % 60, toMillis / 1000. % 60) - - def <(other: Duration) = { - if (other.finite_?) { - toNanos < other.asInstanceOf[FiniteDuration].toNanos - } else { - other > this - } - } - - def <=(other: Duration) = { - if (other.finite_?) { - toNanos <= other.asInstanceOf[FiniteDuration].toNanos - } else { - other >= this - } - } - - def >(other: Duration) = { - if (other.finite_?) { - toNanos > other.asInstanceOf[FiniteDuration].toNanos - } else { - other < this - } - } - - def >=(other: Duration) = { - if (other.finite_?) { - toNanos >= other.asInstanceOf[FiniteDuration].toNanos - } else { - other <= this - } - } - - def +(other: Duration) = { - if (!other.finite_?) { - other - } else { - val nanos = toNanos + other.asInstanceOf[FiniteDuration].toNanos - fromNanos(nanos) - } - } - - def -(other: Duration) = { - if (!other.finite_?) { - other - } else { - val nanos = toNanos - other.asInstanceOf[FiniteDuration].toNanos - fromNanos(nanos) - } - } - - def *(factor: Double) = fromNanos(long2double(toNanos) * factor) - - def /(factor: Double) = fromNanos(long2double(toNanos) / factor) - - def /(other: Duration) = if (other.finite_?) long2double(toNanos) / other.toNanos else 0 - - def unary_- = Duration(-length, unit) - - def finite_? = true - - override def equals(other: Any) = - other.isInstanceOf[FiniteDuration] && - toNanos == other.asInstanceOf[FiniteDuration].toNanos - - override def hashCode = toNanos.asInstanceOf[Int] -} - -class DurationInt(n: Int) { - def nanoseconds = Duration(n, NANOSECONDS) - def nanos = Duration(n, NANOSECONDS) - def nanosecond = Duration(n, NANOSECONDS) - def nano = Duration(n, NANOSECONDS) - - def microseconds = Duration(n, MICROSECONDS) - def micros = Duration(n, MICROSECONDS) - def microsecond = Duration(n, MICROSECONDS) - def micro = Duration(n, MICROSECONDS) - - def milliseconds = Duration(n, MILLISECONDS) - def millis = Duration(n, MILLISECONDS) - def millisecond = Duration(n, MILLISECONDS) - def milli = Duration(n, MILLISECONDS) - - def seconds = Duration(n, SECONDS) - def second = Duration(n, SECONDS) - - def minutes = Duration(n, MINUTES) - def minute = Duration(n, MINUTES) - - def hours = Duration(n, HOURS) - def hour = Duration(n, HOURS) - - def days = Duration(n, DAYS) - def day = Duration(n, DAYS) -} - -class DurationLong(n: Long) { - def nanoseconds = Duration(n, NANOSECONDS) - def nanos = Duration(n, NANOSECONDS) - def nanosecond = Duration(n, NANOSECONDS) - def nano = Duration(n, NANOSECONDS) - - def microseconds = Duration(n, MICROSECONDS) - def micros = Duration(n, MICROSECONDS) - def microsecond = Duration(n, MICROSECONDS) - def micro = Duration(n, MICROSECONDS) - - def milliseconds = Duration(n, MILLISECONDS) - def millis = Duration(n, MILLISECONDS) - def millisecond = Duration(n, MILLISECONDS) - def milli = Duration(n, MILLISECONDS) - - def seconds = Duration(n, SECONDS) - def second = Duration(n, SECONDS) - - def minutes = Duration(n, MINUTES) - def minute = Duration(n, MINUTES) - - def hours = Duration(n, HOURS) - def hour = Duration(n, HOURS) - - def days = Duration(n, DAYS) - def day = Duration(n, DAYS) -} - -class DurationDouble(d: Double) { - def nanoseconds = Duration(d, NANOSECONDS) - def nanos = Duration(d, NANOSECONDS) - def nanosecond = Duration(d, NANOSECONDS) - def nano = Duration(d, NANOSECONDS) - - def microseconds = Duration(d, MICROSECONDS) - def micros = Duration(d, MICROSECONDS) - def microsecond = Duration(d, MICROSECONDS) - def micro = Duration(d, MICROSECONDS) - - def milliseconds = Duration(d, MILLISECONDS) - def millis = Duration(d, MILLISECONDS) - def millisecond = Duration(d, MILLISECONDS) - def milli = Duration(d, MILLISECONDS) - - def seconds = Duration(d, SECONDS) - def second = Duration(d, SECONDS) - - def minutes = Duration(d, MINUTES) - def minute = Duration(d, MINUTES) - - def hours = Duration(d, HOURS) - def hour = Duration(d, HOURS) - - def days = Duration(d, DAYS) - def day = Duration(d, DAYS) -} diff --git a/test/files/presentation/akka/src/akka/util/HashCode.scala b/test/files/presentation/akka/src/akka/util/HashCode.scala deleted file mode 100644 index d015f12f5d..0000000000 --- a/test/files/presentation/akka/src/akka/util/HashCode.scala +++ /dev/null @@ -1,57 +0,0 @@ -/** - * Copyright (C) 2009-2011 Scalable Solutions AB - */ - -package akka.util - -import java.lang.reflect.{ Array => JArray } -import java.lang.{ Float => JFloat, Double => JDouble } - -/** - * Set of methods which allow easy implementation of hashCode. - * - * Example: - *
          - *  override def hashCode: Int = {
          - *    var result = HashCode.SEED
          - *    //collect the contributions of various fields
          - *    result = HashCode.hash(result, fPrimitive)
          - *    result = HashCode.hash(result, fObject)
          - *    result = HashCode.hash(result, fArray)
          - *    result
          - *  }
          - * 
          - * - * @author Jonas Bonér - */ -object HashCode { - val SEED = 23 - - def hash(seed: Int, any: Any): Int = any match { - case value: Boolean => hash(seed, value) - case value: Char => hash(seed, value) - case value: Short => hash(seed, value) - case value: Int => hash(seed, value) - case value: Long => hash(seed, value) - case value: Float => hash(seed, value) - case value: Double => hash(seed, value) - case value: Byte => hash(seed, value) - case value: AnyRef => - var result = seed - if (value eq null) result = hash(result, 0) - else if (!isArray(value)) result = hash(result, value.hashCode()) - else for (id ← 0 until JArray.getLength(value)) result = hash(result, JArray.get(value, id)) // is an array - result - } - def hash(seed: Int, value: Boolean): Int = firstTerm(seed) + (if (value) 1 else 0) - def hash(seed: Int, value: Char): Int = firstTerm(seed) + value.asInstanceOf[Int] - def hash(seed: Int, value: Int): Int = firstTerm(seed) + value - def hash(seed: Int, value: Long): Int = firstTerm(seed) + (value ^ (value >>> 32)).asInstanceOf[Int] - def hash(seed: Int, value: Float): Int = hash(seed, JFloat.floatToIntBits(value)) - def hash(seed: Int, value: Double): Int = hash(seed, JDouble.doubleToLongBits(value)) - - private def firstTerm(seed: Int): Int = PRIME * seed - private def isArray(anyRef: AnyRef): Boolean = anyRef.getClass.isArray - private val PRIME = 37 -} - diff --git a/test/files/presentation/akka/src/akka/util/Helpers.scala b/test/files/presentation/akka/src/akka/util/Helpers.scala deleted file mode 100644 index 48477426c9..0000000000 --- a/test/files/presentation/akka/src/akka/util/Helpers.scala +++ /dev/null @@ -1,99 +0,0 @@ -/** - * Copyright (C) 2009-2011 Scalable Solutions AB - */ - -package akka.util - -/** - * @author Jonas Bonér - */ -object Helpers { - - implicit def null2Option[T](t: T): Option[T] = Option(t) - - def intToBytes(value: Int): Array[Byte] = { - val bytes = new Array[Byte](4) - bytes(0) = (value >>> 24).asInstanceOf[Byte] - bytes(1) = (value >>> 16).asInstanceOf[Byte] - bytes(2) = (value >>> 8).asInstanceOf[Byte] - bytes(3) = value.asInstanceOf[Byte] - bytes - } - - def bytesToInt(bytes: Array[Byte], offset: Int): Int = { - (0 until 4).foldLeft(0)((value, index) => value + ((bytes(index + offset) & 0x000000FF) << ((4 - 1 - index) * 8))) - } - - /** - * Convenience helper to cast the given Option of Any to an Option of the given type. Will throw a ClassCastException - * if the actual type is not assignable from the given one. - */ - def narrow[T](o: Option[Any]): Option[T] = { - require((o ne null), "Option to be narrowed must not be null!") - o.asInstanceOf[Option[T]] - } - - /** - * Convenience helper to cast the given Option of Any to an Option of the given type. Will swallow a possible - * ClassCastException and return None in that case. - */ - def narrowSilently[T: Manifest](o: Option[Any]): Option[T] = - try { - narrow(o) - } catch { - case e: ClassCastException => - None - } - - /** - * Reference that can hold either a typed value or an exception. - * - * Usage: - *
          -   * scala> ResultOrError(1)
          -   * res0: ResultOrError[Int] = ResultOrError@a96606
          -   *
          -   * scala> res0()
          -   * res1: Int = 1
          -   *
          -   * scala> res0() = 3
          -   *
          -   * scala> res0()
          -   * res3: Int = 3
          -   *
          -   * scala> res0() = { println("Hello world"); 3}
          -   * Hello world
          -   *
          -   * scala> res0()
          -   * res5: Int = 3
          -   *
          -   * scala> res0() = error("Lets see what happens here...")
          -   *
          -   * scala> res0()
          -   * java.lang.RuntimeException: Lets see what happens here...
          -   *    at ResultOrError.apply(Helper.scala:11)
          -   *    at .(:6)
          -   *    at .()
          -   *    at Re...
          -   * 
          - */ - class ResultOrError[R](result: R) { - private[this] var contents: Either[R, Throwable] = Left(result) - - def update(value: => R) = { - contents = try { - Left(value) - } catch { - case (error: Throwable) => Right(error) - } - } - - def apply() = contents match { - case Left(result) => result - case Right(error) => throw error.fillInStackTrace - } - } - object ResultOrError { - def apply[R](result: R) = new ResultOrError(result) - } -} diff --git a/test/files/presentation/akka/src/akka/util/ListenerManagement.scala b/test/files/presentation/akka/src/akka/util/ListenerManagement.scala deleted file mode 100644 index 7065397a45..0000000000 --- a/test/files/presentation/akka/src/akka/util/ListenerManagement.scala +++ /dev/null @@ -1,81 +0,0 @@ -/** - * Copyright (C) 2009-2011 Scalable Solutions AB - */ - -package akka.util - -import java.util.concurrent.ConcurrentSkipListSet -import akka.actor.{ ActorInitializationException, ActorRef } - -/** - * A manager for listener actors. Intended for mixin by observables. - * - * @author Martin Krasser - */ -trait ListenerManagement { - - private val listeners = new ConcurrentSkipListSet[ActorRef] - - /** - * Specifies whether listeners should be started when added and stopped when removed or not - */ - protected def manageLifeCycleOfListeners: Boolean = true - - /** - * Adds the listener this this registry's listener list. - * The listener is started by this method if manageLifeCycleOfListeners yields true. - */ - def addListener(listener: ActorRef) { - if (manageLifeCycleOfListeners) listener.start() - listeners add listener - } - - /** - * Removes the listener this this registry's listener list. - * The listener is stopped by this method if manageLifeCycleOfListeners yields true. - */ - def removeListener(listener: ActorRef) { - listeners remove listener - if (manageLifeCycleOfListeners) listener.stop() - } - - /* - * Returns whether there are any listeners currently - */ - def hasListeners: Boolean = !listeners.isEmpty - - /** - * Checks if a specific listener is registered. ActorInitializationException leads to removal of listener if that - * one isShutdown. - */ - def hasListener(listener: ActorRef): Boolean = listeners.contains(listener) - - protected[akka] def notifyListeners(message: => Any) { - if (hasListeners) { - val msg = message - val iterator = listeners.iterator - while (iterator.hasNext) { - val listener = iterator.next - // Uncomment if those exceptions are so frequent as to bottleneck - // if (listener.isShutdown) iterator.remove() else - try { - listener ! msg - } catch { - case e: ActorInitializationException => - if (listener.isShutdown) iterator.remove() - } - } - } - } - - /** - * Execute f with each listener as argument. ActorInitializationException is not handled. - */ - protected[akka] def foreachListener(f: (ActorRef) => Unit) { - val iterator = listeners.iterator - while (iterator.hasNext) { - val listener = iterator.next - if (listener.isRunning) f(listener) - } - } -} diff --git a/test/files/presentation/akka/src/akka/util/LockUtil.scala b/test/files/presentation/akka/src/akka/util/LockUtil.scala deleted file mode 100644 index 4aaefadc4a..0000000000 --- a/test/files/presentation/akka/src/akka/util/LockUtil.scala +++ /dev/null @@ -1,197 +0,0 @@ -/** - * Copyright (C) 2009-2011 Scalable Solutions AB - */ - -package akka.util - -import java.util.concurrent.locks.{ ReentrantReadWriteLock, ReentrantLock } -import java.util.concurrent.atomic.{ AtomicBoolean } -import akka.event.EventHandler - -/** - * @author Jonas Bonér - */ -final class ReentrantGuard { - val lock = new ReentrantLock - - final def withGuard[T](body: => T): T = { - lock.lock - try { - body - } finally { - lock.unlock - } - } - - final def tryWithGuard[T](body: => T): T = { - while (!lock.tryLock) { Thread.sleep(10) } // wait on the monitor to be unlocked - try { - body - } finally { - lock.unlock - } - } -} - -/** - * @author Jonas Bonér - */ -class ReadWriteGuard { - private val rwl = new ReentrantReadWriteLock - val readLock = rwl.readLock - val writeLock = rwl.writeLock - - def withWriteGuard[T](body: => T): T = { - writeLock.lock - try { - body - } finally { - writeLock.unlock - } - } - - def withReadGuard[T](body: => T): T = { - readLock.lock - try { - body - } finally { - readLock.unlock - } - } -} - -/** - * A very simple lock that uses CCAS (Compare Compare-And-Swap) - * Does not keep track of the owner and isn't Reentrant, so don't nest and try to stick to the if*-methods - */ -class SimpleLock { - val acquired = new AtomicBoolean(false) - - def ifPossible(perform: () => Unit): Boolean = { - if (tryLock()) { - try { - perform - } finally { - unlock() - } - true - } else false - } - - def ifPossibleYield[T](perform: () => T): Option[T] = { - if (tryLock()) { - try { - Some(perform()) - } finally { - unlock() - } - } else None - } - - def ifPossibleApply[T, R](value: T)(function: (T) => R): Option[R] = { - if (tryLock()) { - try { - Some(function(value)) - } finally { - unlock() - } - } else None - } - - def tryLock() = { - if (acquired.get) false - else acquired.compareAndSet(false, true) - } - - def tryUnlock() = { - acquired.compareAndSet(true, false) - } - - def locked = acquired.get - - def unlock() { - acquired.set(false) - } -} - -/** - * An atomic switch that can be either on or off - */ -class Switch(startAsOn: Boolean = false) { - private val switch = new AtomicBoolean(startAsOn) - - protected def transcend(from: Boolean, action: => Unit): Boolean = synchronized { - if (switch.compareAndSet(from, !from)) { - try { - action - } catch { - case e: Throwable => - EventHandler.error(e, this, e.getMessage) - switch.compareAndSet(!from, from) // revert status - throw e - } - true - } else false - } - - def switchOff(action: => Unit): Boolean = transcend(from = true, action) - def switchOn(action: => Unit): Boolean = transcend(from = false, action) - - def switchOff: Boolean = synchronized { switch.compareAndSet(true, false) } - def switchOn: Boolean = synchronized { switch.compareAndSet(false, true) } - - def ifOnYield[T](action: => T): Option[T] = { - if (switch.get) Some(action) - else None - } - - def ifOffYield[T](action: => T): Option[T] = { - if (!switch.get) Some(action) - else None - } - - def ifOn(action: => Unit): Boolean = { - if (switch.get) { - action - true - } else false - } - - def ifOff(action: => Unit): Boolean = { - if (!switch.get) { - action - true - } else false - } - - def whileOnYield[T](action: => T): Option[T] = synchronized { - if (switch.get) Some(action) - else None - } - - def whileOffYield[T](action: => T): Option[T] = synchronized { - if (!switch.get) Some(action) - else None - } - - def whileOn(action: => Unit): Boolean = synchronized { - if (switch.get) { - action - true - } else false - } - - def whileOff(action: => Unit): Boolean = synchronized { - if (switch.get) { - action - true - } else false - } - - def ifElseYield[T](on: => T)(off: => T) = synchronized { - if (switch.get) on else off - } - - def isOn = switch.get - def isOff = !isOn -} diff --git a/test/files/presentation/akka/src/akka/util/ReflectiveAccess.scala b/test/files/presentation/akka/src/akka/util/ReflectiveAccess.scala deleted file mode 100644 index f38d1f9b98..0000000000 --- a/test/files/presentation/akka/src/akka/util/ReflectiveAccess.scala +++ /dev/null @@ -1,232 +0,0 @@ -/** - * Copyright (C) 2009-2011 Scalable Solutions AB - */ - -package akka.util - -import akka.dispatch.{ Future, CompletableFuture, MessageInvocation } -import akka.config.{ Config, ModuleNotAvailableException } - -import java.net.InetSocketAddress -import akka.remoteinterface.RemoteSupport -import akka.actor._ -import akka.event.EventHandler - -/** - * Helper class for reflective access to different modules in order to allow optional loading of modules. - * - * @author Jonas Bonér - */ -object ReflectiveAccess { - - val loader = getClass.getClassLoader - - def isRemotingEnabled = Remote.isEnabled - lazy val isTypedActorEnabled = TypedActorModule.isEnabled - - def ensureRemotingEnabled = Remote.ensureEnabled - def ensureTypedActorEnabled = TypedActorModule.ensureEnabled - - /** - * Reflective access to the RemoteClient module. - * - * @author Jonas Bonér - */ - object Remote { - val TRANSPORT = Config.config.getString("akka.remote.layer", "akka.remote.netty.NettyRemoteSupport") - - private[akka] val configDefaultAddress = - new InetSocketAddress(Config.config.getString("akka.remote.server.hostname", "localhost"), - Config.config.getInt("akka.remote.server.port", 2552)) - - lazy val isEnabled = remoteSupportClass.isDefined - - def ensureEnabled = if (!isEnabled) { - val e = new ModuleNotAvailableException("Can't load the remoting module, make sure that akka-remote.jar is on the classpath") - EventHandler.debug(this, e.toString) - throw e - } - val remoteSupportClass = getClassFor[RemoteSupport](TRANSPORT) match { - case Right(value) => Some(value) - case Left(exception) => - EventHandler.debug(this, exception.toString) - None - } - - protected[akka] val defaultRemoteSupport: Option[() => RemoteSupport] = - remoteSupportClass map { remoteClass => - () => createInstance[RemoteSupport]( - remoteClass, - Array[Class[_]](), - Array[AnyRef]()) match { - case Right(value) => value - case Left(exception) => - val e = new ModuleNotAvailableException( - "Can't instantiate [%s] - make sure that akka-remote.jar is on the classpath".format(remoteClass.getName), exception) - EventHandler.debug(this, e.toString) - throw e - } - } - } - - /** - * Reflective access to the TypedActors module. - * - * @author Jonas Bonér - */ - object TypedActorModule { - - type TypedActorObject = { - def isJoinPoint(message: Any): Boolean - def isJoinPointAndOneWay(message: Any): Boolean - def actorFor(proxy: AnyRef): Option[ActorRef] - def proxyFor(actorRef: ActorRef): Option[AnyRef] - def stop(anyRef: AnyRef): Unit - } - - lazy val isEnabled = typedActorObjectInstance.isDefined - - def ensureEnabled = if (!isTypedActorEnabled) throw new ModuleNotAvailableException( - "Can't load the typed actor module, make sure that akka-typed-actor.jar is on the classpath") - - val typedActorObjectInstance: Option[TypedActorObject] = - getObjectFor[TypedActorObject]("akka.actor.TypedActor$") match { - case Right(value) => Some(value) - case Left(exception) => - EventHandler.debug(this, exception.toString) - None - } - - def resolveFutureIfMessageIsJoinPoint(message: Any, future: Future[_]): Boolean = { - ensureEnabled - if (typedActorObjectInstance.get.isJoinPointAndOneWay(message)) { - future.asInstanceOf[CompletableFuture[Option[_]]].completeWithResult(None) - } - typedActorObjectInstance.get.isJoinPoint(message) - } - } - - object AkkaCloudModule { - - type Mailbox = { - def enqueue(message: MessageInvocation) - def dequeue: MessageInvocation - } - - type Serializer = { - def toBinary(obj: AnyRef): Array[Byte] - def fromBinary(bytes: Array[Byte], clazz: Option[Class[_]]): AnyRef - } - - lazy val isEnabled = clusterObjectInstance.isDefined - - val clusterObjectInstance: Option[AnyRef] = - getObjectFor[AnyRef]("akka.cloud.cluster.Cluster$") match { - case Right(value) => Some(value) - case Left(exception) => - EventHandler.debug(this, exception.toString) - None - } - - val serializerClass: Option[Class[_]] = - getClassFor("akka.serialization.Serializer") match { - case Right(value) => Some(value) - case Left(exception) => - EventHandler.debug(this, exception.toString) - None - } - - def ensureEnabled = if (!isEnabled) throw new ModuleNotAvailableException( - "Feature is only available in Akka Cloud") - } - - val noParams = Array[Class[_]]() - val noArgs = Array[AnyRef]() - - def createInstance[T](clazz: Class[_], - params: Array[Class[_]], - args: Array[AnyRef]): Either[Exception, T] = try { - assert(clazz ne null) - assert(params ne null) - assert(args ne null) - val ctor = clazz.getDeclaredConstructor(params: _*) - ctor.setAccessible(true) - Right(ctor.newInstance(args: _*).asInstanceOf[T]) - } catch { - case e: Exception => Left(e) - } - - def createInstance[T](fqn: String, - params: Array[Class[_]], - args: Array[AnyRef], - classloader: ClassLoader = loader): Either[Exception, T] = try { - assert(params ne null) - assert(args ne null) - getClassFor(fqn) match { - case Right(value) => - val ctor = value.getDeclaredConstructor(params: _*) - ctor.setAccessible(true) - Right(ctor.newInstance(args: _*).asInstanceOf[T]) - case Left(exception) => Left(exception) //We could just cast this to Either[Exception, T] but it's ugly - } - } catch { - case e: Exception => - Left(e) - } - - //Obtains a reference to fqn.MODULE$ - def getObjectFor[T](fqn: String, classloader: ClassLoader = loader): Either[Exception, T] = try { - getClassFor(fqn) match { - case Right(value) => - val instance = value.getDeclaredField("MODULE$") - instance.setAccessible(true) - val obj = instance.get(null) - if (obj eq null) Left(new NullPointerException) else Right(obj.asInstanceOf[T]) - case Left(exception) => Left(exception) //We could just cast this to Either[Exception, T] but it's ugly - } - } catch { - case e: Exception => - Left(e) - } - - def getClassFor[T](fqn: String, classloader: ClassLoader = loader): Either[Exception, Class[T]] = try { - assert(fqn ne null) - - // First, use the specified CL - val first = try { - Right(classloader.loadClass(fqn).asInstanceOf[Class[T]]) - } catch { - case c: ClassNotFoundException => Left(c) - } - - if (first.isRight) first - else { - // Second option is to use the ContextClassLoader - val second = try { - Right(Thread.currentThread.getContextClassLoader.loadClass(fqn).asInstanceOf[Class[T]]) - } catch { - case c: ClassNotFoundException => Left(c) - } - - if (second.isRight) second - else { - val third = try { - if (classloader ne loader) Right(loader.loadClass(fqn).asInstanceOf[Class[T]]) else Left(null) //Horrid - } catch { - case c: ClassNotFoundException => Left(c) - } - - if (third.isRight) third - else { - try { - Right(Class.forName(fqn).asInstanceOf[Class[T]]) // Last option is Class.forName - } catch { - case c: ClassNotFoundException => Left(c) - } - } - } - } - } catch { - case e: Exception => Left(e) - } -} diff --git a/test/files/presentation/akka/src/akka/util/package.scala b/test/files/presentation/akka/src/akka/util/package.scala deleted file mode 100644 index 26a24929c9..0000000000 --- a/test/files/presentation/akka/src/akka/util/package.scala +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Copyright (C) 2009-2011 Scalable Solutions AB - */ - -package akka.util - -import java.util.concurrent.TimeUnit - -package object duration { - implicit def intToDurationInt(n: Int) = new DurationInt(n) - implicit def longToDurationLong(n: Long) = new DurationLong(n) - implicit def doubleToDurationDouble(d: Double) = new DurationDouble(d) - - implicit def pairIntToDuration(p: (Int, TimeUnit)) = Duration(p._1, p._2) - implicit def pairLongToDuration(p: (Long, TimeUnit)) = Duration(p._1, p._2) - implicit def durationToPair(d: Duration) = (d.length, d.unit) - - implicit def intMult(i: Int) = new { - def *(d: Duration) = d * i - } - implicit def longMult(l: Long) = new { - def *(d: Duration) = d * l - } - implicit def doubleMult(f: Double) = new { - def *(d: Duration) = d * f - } -} diff --git a/test/files/presentation/akka/src/com/eaio/util/lang/Hex.java b/test/files/presentation/akka/src/com/eaio/util/lang/Hex.java deleted file mode 100644 index 7794059517..0000000000 --- a/test/files/presentation/akka/src/com/eaio/util/lang/Hex.java +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Hex.java - * - * Created 04.07.2003. - * - * eaio: UUID - an implementation of the UUID specification Copyright (c) 2003-2009 Johann Burkard (jb@eaio.com) - * http://eaio.com. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated - * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE - * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ -package com.eaio.util.lang; - -import java.io.IOException; - -/** - * Number-to-hexadecimal and hexadecimal-to-number conversions. - * - * @see UUID - * @author Johann Burkard - * @version $Id: Hex.java 1888 2009-03-15 12:43:24Z johann $ - */ -public final class Hex { - - /** - * No instances needed. - */ - private Hex() { - super(); - } - - private static final char[] DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', - 'f' }; - - /** - * Turns a short into hex octets. - * - * @param a the {@link Appendable}, may not be null - * @param in the integer - * @return {@link Appendable} - */ - public static Appendable append(Appendable a, short in) { - return append(a, (long) in, 4); - } - - /** - * Turns a short into hex octets. - * - * @param a the {@link Appendable}, may not be null - * @param in the integer - * @param length the number of octets to produce - * @return {@link Appendable} - */ - public static Appendable append(Appendable a, short in, int length) { - return append(a, (long) in, length); - } - - /** - * Turns an int into hex octets. - * - * @param a the {@link Appendable}, may not be null - * @param in the integer - * @return {@link Appendable} - */ - public static Appendable append(Appendable a, int in) { - return append(a, (long) in, 8); - } - - /** - * Turns an int into hex octets. - * - * @param a the {@link Appendable}, may not be null - * @param in the integer - * @param length the number of octets to produce - * @return {@link Appendable} - */ - public static Appendable append(Appendable a, int in, int length) { - return append(a, (long) in, length); - } - - /** - * Turns a long into hex octets. - * - * @param a the {@link Appendable}, may not be null - * @param in the long - * @return {@link Appendable} - */ - public static Appendable append(Appendable a, long in) { - return append(a, in, 16); - } - - /** - * Turns a long into hex octets. - * - * @param a the {@link Appendable}, may not be null - * @param in the long - * @param length the number of octets to produce - * @return {@link Appendable} - */ - public static Appendable append(Appendable a, long in, int length) { - try { - int lim = (length << 2) - 4; - while (lim >= 0) { - a.append(DIGITS[(byte) (in >> lim) & 0x0f]); - lim -= 4; - } - } - catch (IOException ex) { - // Bla - } - return a; - } - - /** - * Turns a byte array into hex octets. - * - * @param a the {@link Appendable}, may not be null - * @param bytes the byte array - * @return {@link Appendable} - */ - public static Appendable append(Appendable a, byte[] bytes) { - try { - for (byte b : bytes) { - a.append(DIGITS[(byte) ((b & 0xF0) >> 4)]); - a.append(DIGITS[(byte) (b & 0x0F)]); - } - } - catch (IOException ex) { - // Bla - } - return a; - } - - /** - * Parses a long from a hex encoded number. This method will skip all characters that are not 0-9, - * A-F and a-f. - *

          - * Returns 0 if the {@link CharSequence} does not contain any interesting characters. - * - * @param s the {@link CharSequence} to extract a long from, may not be null - * @return a long - * @throws NullPointerException if the {@link CharSequence} is null - */ - public static long parseLong(CharSequence s) { - long out = 0; - byte shifts = 0; - char c; - for (int i = 0; i < s.length() && shifts < 16; i++) { - c = s.charAt(i); - if ((c > 47) && (c < 58)) { - ++shifts; - out <<= 4; - out |= c - 48; - } - else if ((c > 64) && (c < 71)) { - ++shifts; - out <<= 4; - out |= c - 55; - } - else if ((c > 96) && (c < 103)) { - ++shifts; - out <<= 4; - out |= c - 87; - } - } - return out; - } - - /** - * Parses a short from a hex encoded number. This method will skip all characters that are not 0-9, - * A-F and a-f. - *

          - * Returns 0 if the {@link CharSequence} does not contain any interesting characters. - * - * @param s the {@link CharSequence} to extract a short from, may not be null - * @return a short - * @throws NullPointerException if the {@link CharSequence} is null - */ - public static short parseShort(String s) { - short out = 0; - byte shifts = 0; - char c; - for (int i = 0; i < s.length() && shifts < 4; i++) { - c = s.charAt(i); - if ((c > 47) && (c < 58)) { - ++shifts; - out <<= 4; - out |= c - 48; - } - else if ((c > 64) && (c < 71)) { - ++shifts; - out <<= 4; - out |= c - 55; - } - else if ((c > 96) && (c < 103)) { - ++shifts; - out <<= 4; - out |= c - 87; - } - } - return out; - } - -} diff --git a/test/files/presentation/akka/src/com/eaio/uuid/MACAddressParser.java b/test/files/presentation/akka/src/com/eaio/uuid/MACAddressParser.java deleted file mode 100644 index c077147470..0000000000 --- a/test/files/presentation/akka/src/com/eaio/uuid/MACAddressParser.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * MACAddressParserTest.java - * - * Created 30.01.2006. - * - * eaio: UUID - an implementation of the UUID specification - * Copyright (c) 2003-2009 Johann Burkard (jb@eaio.com) http://eaio.com. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN - * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ -package com.eaio.uuid; - -/** - * The MAC address parser attempts to find the following patterns: - *

            - *
          • .{1,2}:.{1,2}:.{1,2}:.{1,2}:.{1,2}:.{1,2}
          • - *
          • .{1,2}-.{1,2}-.{1,2}-.{1,2}-.{1,2}-.{1,2}
          • - *
          - * - * @see UUID - * @author Johann Burkard - * @version $Id: MACAddressParser.java 1888 2009-03-15 12:43:24Z johann $ - */ -class MACAddressParser { - - /** - * No instances needed. - */ - private MACAddressParser() { - super(); - } - - /** - * Attempts to find a pattern in the given String. - * - * @param in the String, may not be null - * @return the substring that matches this pattern or null - */ - static String parse(String in) { - - String out = in; - - // lanscan - - int hexStart = out.indexOf("0x"); - if (hexStart != -1 && out.indexOf("ETHER") != -1) { - int hexEnd = out.indexOf(' ', hexStart); - if (hexEnd > hexStart + 2) { - out = out.substring(hexStart, hexEnd); - } - } - - else { - - int octets = 0; - int lastIndex, old, end; - - if (out.indexOf('-') > -1) { - out = out.replace('-', ':'); - } - - lastIndex = out.lastIndexOf(':'); - - if (lastIndex > out.length() - 2) { - out = null; - } - else { - - end = Math.min(out.length(), lastIndex + 3); - - ++octets; - old = lastIndex; - while (octets != 5 && lastIndex != -1 && lastIndex > 1) { - lastIndex = out.lastIndexOf(':', --lastIndex); - if (old - lastIndex == 3 || old - lastIndex == 2) { - ++octets; - old = lastIndex; - } - } - - if (octets == 5 && lastIndex > 1) { - out = out.substring(lastIndex - 2, end).trim(); - } - else { - out = null; - } - - } - - } - - if (out != null && out.startsWith("0x")) { - out = out.substring(2); - } - - return out; - } - -} diff --git a/test/files/presentation/akka/src/com/eaio/uuid/UUID.java b/test/files/presentation/akka/src/com/eaio/uuid/UUID.java deleted file mode 100644 index 6c49bcd1c8..0000000000 --- a/test/files/presentation/akka/src/com/eaio/uuid/UUID.java +++ /dev/null @@ -1,311 +0,0 @@ -/* - * UUID.java - * - * Created 07.02.2003 - * - * eaio: UUID - an implementation of the UUID specification - * Copyright (c) 2003-2009 Johann Burkard (jb@eaio.com) http://eaio.com. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN - * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ -package com.eaio.uuid; - -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.Serializable; - -import org.omg.CORBA.portable.IDLEntity; - -import com.eaio.util.lang.Hex; - -/** - * Creates UUIDs according to the DCE Universal Token Identifier specification. - *

          - * All you need to know: - *

          - * UUID u = new UUID();
          - * 
          - * - * @see - * http://www.opengroup.org/onlinepubs/9629399/apdxa.htm - * - * @see - * http://www.uddi.org/pubs/draft-leach-uuids-guids-01.txt - * - * @see UUID - * @author Johann Burkard - * @version $Id: UUID.java 1888 2009-03-15 12:43:24Z johann $ - */ -public class UUID implements Comparable, Serializable, Cloneable, - IDLEntity { - - /** - * Hasn't ever changed between versions. - */ - static final long serialVersionUID = 7435962790062944603L; - - /** - * The time field of the UUID. - * - * @serial - */ - public long time; - - /** - * The clock sequence and node field of the UUID. - * - * @serial - */ - public long clockSeqAndNode; - - /** - * Constructor for UUID. Constructs a new, unique UUID. - * - * @see UUIDGen#newTime() - * @see UUIDGen#getClockSeqAndNode() - */ - public UUID() { - this(UUIDGen.newTime(), UUIDGen.getClockSeqAndNode()); - } - - /** - * Constructor for UUID. Constructs a UUID from two long values. - * - * @param time the upper 64 bits - * @param clockSeqAndNode the lower 64 bits - */ - public UUID(long time, long clockSeqAndNode) { - this.time = time; - this.clockSeqAndNode = clockSeqAndNode; - } - - /** - * Copy constructor for UUID. Values of the given UUID are copied. - * - * @param u the UUID, may not be null - */ - public UUID(UUID u) { - this(u.time, u.clockSeqAndNode); - } - - /** - * Parses a textual representation of a UUID. - *

          - * No validation is performed. If the {@link CharSequence} is shorter than 36 characters, - * {@link ArrayIndexOutOfBoundsException}s will be thrown. - * - * @param s the {@link CharSequence}, may not be null - */ - public UUID(CharSequence s) { - this(Hex.parseLong(s.subSequence(0, 18)), Hex.parseLong(s.subSequence( - 19, 36))); - } - - /** - * Compares this UUID to another Object. Throws a {@link ClassCastException} if - * the other Object is not an instance of the UUID class. Returns a value - * smaller than zero if the other UUID is "larger" than this UUID and a value - * larger than zero if the other UUID is "smaller" than this UUID. - * - * @param t the other UUID, may not be null - * @return a value < 0, 0 or a value > 0 - * @see java.lang.Comparable#compareTo(java.lang.Object) - * @throws ClassCastException - */ - public int compareTo(UUID t) { - if (this == t) { - return 0; - } - if (time > t.time) { - return 1; - } - if (time < t.time) { - return -1; - } - if (clockSeqAndNode > t.clockSeqAndNode) { - return 1; - } - if (clockSeqAndNode < t.clockSeqAndNode) { - return -1; - } - return 0; - } - - /** - * Tweaked Serialization routine. - * - * @param out the ObjectOutputStream - * @throws IOException - */ - private void writeObject(ObjectOutputStream out) throws IOException { - out.writeLong(time); - out.writeLong(clockSeqAndNode); - } - - /** - * Tweaked Serialization routine. - * - * @param in the ObjectInputStream - * @throws IOException - */ - private void readObject(ObjectInputStream in) throws IOException { - time = in.readLong(); - clockSeqAndNode = in.readLong(); - } - - /** - * Returns this UUID as a String. - * - * @return a String, never null - * @see java.lang.Object#toString() - * @see #toAppendable(Appendable) - */ - @Override - public final String toString() { - return toAppendable(null).toString(); - } - - /** - * Appends a String representation of this to the given {@link StringBuffer} or - * creates a new one if none is given. - * - * @param in the StringBuffer to append to, may be null - * @return a StringBuffer, never null - * @see #toAppendable(Appendable) - */ - public StringBuffer toStringBuffer(StringBuffer in) { - StringBuffer out = in; - if (out == null) { - out = new StringBuffer(36); - } - else { - out.ensureCapacity(out.length() + 36); - } - return (StringBuffer) toAppendable(out); - } - - /** - * Appends a String representation of this object to the given {@link Appendable} object. - *

          - * For reasons I'll probably never understand, Sun has decided to have a number of I/O classes implement - * Appendable which forced them to destroy an otherwise nice and simple interface with {@link IOException}s. - *

          - * I decided to ignore any possible IOExceptions in this method. - * - * @param a the Appendable object, may be null - * @return an Appendable object, defaults to a {@link StringBuilder} if a is null - */ - public Appendable toAppendable(Appendable a) { - Appendable out = a; - if (out == null) { - out = new StringBuilder(36); - } - try { - Hex.append(out, (int) (time >> 32)).append('-'); - Hex.append(out, (short) (time >> 16)).append('-'); - Hex.append(out, (short) time).append('-'); - Hex.append(out, (short) (clockSeqAndNode >> 48)).append('-'); - Hex.append(out, clockSeqAndNode, 12); - } - catch (IOException ex) { - // What were they thinking? - } - return out; - } - - /** - * Returns a hash code of this UUID. The hash code is calculated by XOR'ing the - * upper 32 bits of the time and clockSeqAndNode fields and the lower 32 bits of - * the time and clockSeqAndNode fields. - * - * @return an int representing the hash code - * @see java.lang.Object#hashCode() - */ - @Override - public int hashCode() { - return (int) ((time >> 32) ^ time ^ (clockSeqAndNode >> 32) ^ clockSeqAndNode); - } - - /** - * Clones this UUID. - * - * @return a new UUID with identical values, never null - */ - @Override - public Object clone() { - try { - return super.clone(); - } - catch (CloneNotSupportedException ex) { - // One of Sun's most epic fails. - return null; - } - } - - /** - * Returns the time field of the UUID (upper 64 bits). - * - * @return the time field - */ - public final long getTime() { - return time; - } - - /** - * Returns the clock and node field of the UUID (lower 64 bits). - * - * @return the clockSeqAndNode field - */ - public final long getClockSeqAndNode() { - return clockSeqAndNode; - } - - /** - * Compares two Objects for equality. - * - * @see java.lang.Object#equals(Object) - * @param obj the Object to compare this UUID with, may be null - * @return true if the other Object is equal to this UUID, - * false if not - */ - @Override - public boolean equals(Object obj) { - if (!(obj instanceof UUID)) { - return false; - } - return compareTo((UUID) obj) == 0; - } - - /** - * Returns the nil UUID (a UUID whose values are both set to zero). - *

          - * Starting with version 2.0, this method does return a new UUID instance every - * time it is called. Earlier versions returned one instance. This has now been - * changed because this UUID has public, non-final instance fields. Returning a - * new instance is therefore more safe. - * - * @return a nil UUID, never null - */ - public static UUID nilUUID() { - return new UUID(0, 0); - } - -} diff --git a/test/files/presentation/akka/src/com/eaio/uuid/UUIDGen.java b/test/files/presentation/akka/src/com/eaio/uuid/UUIDGen.java deleted file mode 100644 index 7b63f65447..0000000000 --- a/test/files/presentation/akka/src/com/eaio/uuid/UUIDGen.java +++ /dev/null @@ -1,364 +0,0 @@ -/* - * UUIDGen.java - * - * Created on 09.08.2003. - * - * eaio: UUID - an implementation of the UUID specification - * Copyright (c) 2003-2009 Johann Burkard (jb@eaio.com) http://eaio.com. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN - * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ -package com.eaio.uuid; - -import java.io.BufferedReader; -import java.io.File; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.InetAddress; -import java.net.InterfaceAddress; -import java.net.NetworkInterface; -import java.net.SocketException; -import java.net.UnknownHostException; -import java.util.Enumeration; - -import com.eaio.util.lang.Hex; - -/** - * This class contains methods to generate UUID fields. These methods have been - * refactored out of {@link com.eaio.uuid.UUID}. - *

          - * Starting with version 2, this implementation tries to obtain the MAC address - * of the network card. Under Microsoft Windows, the ifconfig - * command is used which may pop up a command window in Java Virtual Machines - * prior to 1.4 once this class is initialized. The command window is closed - * automatically. - *

          - * The MAC address code has been tested extensively in Microsoft Windows, - * Linux, Solaris 8, HP-UX 11, but should work in MacOS X and BSDs, too. - *

          - * If you use JDK 6 or later, the code in {@link InterfaceAddress} will be used. - * - * @see UUID - * @author Johann Burkard - * @version $Id: UUIDGen.java 2914 2010-04-23 11:35:00Z johann $ - * @see com.eaio.uuid.UUID - */ -public final class UUIDGen { - - /** - * No instances needed. - */ - private UUIDGen() { - super(); - } - - /** - * The last time value. Used to remove duplicate UUIDs. - */ - private static long lastTime = Long.MIN_VALUE; - - /** - * The cached MAC address. - */ - private static String macAddress = null; - - /** - * The current clock and node value. - */ - private static long clockSeqAndNode = 0x8000000000000000L; - - static { - - try { - Class.forName("java.net.InterfaceAddress"); - macAddress = Class.forName( - "com.eaio.uuid.UUIDGen$HardwareAddressLookup").newInstance().toString(); - } - catch (ExceptionInInitializerError err) { - // Ignored. - } - catch (ClassNotFoundException ex) { - // Ignored. - } - catch (LinkageError err) { - // Ignored. - } - catch (IllegalAccessException ex) { - // Ignored. - } - catch (InstantiationException ex) { - // Ignored. - } - catch (SecurityException ex) { - // Ignored. - } - - if (macAddress == null) { - - Process p = null; - BufferedReader in = null; - - try { - String osname = System.getProperty("os.name", ""); - - if (osname.startsWith("Windows")) { - p = Runtime.getRuntime().exec( - new String[] { "ipconfig", "/all" }, null); - } - // Solaris code must appear before the generic code - else if (osname.startsWith("Solaris") - || osname.startsWith("SunOS")) { - String hostName = getFirstLineOfCommand( - "uname", "-n" ); - if (hostName != null) { - p = Runtime.getRuntime().exec( - new String[] { "/usr/sbin/arp", hostName }, - null); - } - } - else if (new File("/usr/sbin/lanscan").exists()) { - p = Runtime.getRuntime().exec( - new String[] { "/usr/sbin/lanscan" }, null); - } - else if (new File("/sbin/ifconfig").exists()) { - p = Runtime.getRuntime().exec( - new String[] { "/sbin/ifconfig", "-a" }, null); - } - - if (p != null) { - in = new BufferedReader(new InputStreamReader( - p.getInputStream()), 128); - String l = null; - while ((l = in.readLine()) != null) { - macAddress = MACAddressParser.parse(l); - if (macAddress != null - && Hex.parseShort(macAddress) != 0xff) { - break; - } - } - } - - } - catch (SecurityException ex) { - // Ignore it. - } - catch (IOException ex) { - // Ignore it. - } - finally { - if (p != null) { - if (in != null) { - try { - in.close(); - } - catch (IOException ex) { - // Ignore it. - } - } - try { - p.getErrorStream().close(); - } - catch (IOException ex) { - // Ignore it. - } - try { - p.getOutputStream().close(); - } - catch (IOException ex) { - // Ignore it. - } - p.destroy(); - } - } - - } - - if (macAddress != null) { - clockSeqAndNode |= Hex.parseLong(macAddress); - } - else { - try { - byte[] local = InetAddress.getLocalHost().getAddress(); - clockSeqAndNode |= (local[0] << 24) & 0xFF000000L; - clockSeqAndNode |= (local[1] << 16) & 0xFF0000; - clockSeqAndNode |= (local[2] << 8) & 0xFF00; - clockSeqAndNode |= local[3] & 0xFF; - } - catch (UnknownHostException ex) { - clockSeqAndNode |= (long) (Math.random() * 0x7FFFFFFF); - } - } - - // Skip the clock sequence generation process and use random instead. - - clockSeqAndNode |= (long) (Math.random() * 0x3FFF) << 48; - - } - - /** - * Returns the current clockSeqAndNode value. - * - * @return the clockSeqAndNode value - * @see UUID#getClockSeqAndNode() - */ - public static long getClockSeqAndNode() { - return clockSeqAndNode; - } - - /** - * Generates a new time field. Each time field is unique and larger than the - * previously generated time field. - * - * @return a new time value - * @see UUID#getTime() - */ - public static long newTime() { - return createTime(System.currentTimeMillis()); - } - - /** - * Creates a new time field from the given timestamp. Note that even identical - * values of currentTimeMillis will produce different time fields. - * - * @param currentTimeMillis the timestamp - * @return a new time value - * @see UUID#getTime() - */ - public static synchronized long createTime(long currentTimeMillis) { - - long time; - - // UTC time - - long timeMillis = (currentTimeMillis * 10000) + 0x01B21DD213814000L; - - if (timeMillis > lastTime) { - lastTime = timeMillis; - } - else { - timeMillis = ++lastTime; - } - - // time low - - time = timeMillis << 32; - - // time mid - - time |= (timeMillis & 0xFFFF00000000L) >> 16; - - // time hi and version - - time |= 0x1000 | ((timeMillis >> 48) & 0x0FFF); // version 1 - - return time; - - } - - /** - * Returns the MAC address. Not guaranteed to return anything. - * - * @return the MAC address, may be null - */ - public static String getMACAddress() { - return macAddress; - } - - /** - * Returns the first line of the shell command. - * - * @param commands the commands to run - * @return the first line of the command - * @throws IOException - */ - static String getFirstLineOfCommand(String... commands) throws IOException { - - Process p = null; - BufferedReader reader = null; - - try { - p = Runtime.getRuntime().exec(commands); - reader = new BufferedReader(new InputStreamReader( - p.getInputStream()), 128); - - return reader.readLine(); - } - finally { - if (p != null) { - if (reader != null) { - try { - reader.close(); - } - catch (IOException ex) { - // Ignore it. - } - } - try { - p.getErrorStream().close(); - } - catch (IOException ex) { - // Ignore it. - } - try { - p.getOutputStream().close(); - } - catch (IOException ex) { - // Ignore it. - } - p.destroy(); - } - } - - } - - /** - * Scans MAC addresses for good ones. - */ - static class HardwareAddressLookup { - - /** - * @see java.lang.Object#toString() - */ - @Override - public String toString() { - String out = null; - try { - Enumeration ifs = NetworkInterface.getNetworkInterfaces(); - if (ifs != null) { - while (ifs.hasMoreElements()) { - NetworkInterface iface = ifs.nextElement(); - byte[] hardware = iface.getHardwareAddress(); - if (hardware != null && hardware.length == 6 - && hardware[1] != (byte) 0xff) { - out = Hex.append(new StringBuilder(36), hardware).toString(); - break; - } - } - } - } - catch (SocketException ex) { - // Ignore it. - } - return out; - } - - } - -} diff --git a/test/files/presentation/akka/src/com/eaio/uuid/UUIDHelper.java b/test/files/presentation/akka/src/com/eaio/uuid/UUIDHelper.java deleted file mode 100644 index 7abbe85895..0000000000 --- a/test/files/presentation/akka/src/com/eaio/uuid/UUIDHelper.java +++ /dev/null @@ -1,86 +0,0 @@ -package com.eaio.uuid; - - -/** -* com/eaio/uuid/UUIDHelper.java . -* Generated by the IDL-to-Java compiler (portable), version "3.1" -* from uuid.idl -* Sonntag, 7. März 2004 21.35 Uhr CET -*/ - - -/** - * The UUID struct. - */ -abstract public class UUIDHelper -{ - private static String _id = "IDL:com/eaio/uuid/UUID:1.0"; - - public static void insert (org.omg.CORBA.Any a, com.eaio.uuid.UUID that) - { - org.omg.CORBA.portable.OutputStream out = a.create_output_stream (); - a.type (type ()); - write (out, that); - a.read_value (out.create_input_stream (), type ()); - } - - public static com.eaio.uuid.UUID extract (org.omg.CORBA.Any a) - { - return read (a.create_input_stream ()); - } - - private static org.omg.CORBA.TypeCode __typeCode = null; - private static boolean __active = false; - synchronized public static org.omg.CORBA.TypeCode type () - { - if (__typeCode == null) - { - synchronized (org.omg.CORBA.TypeCode.class) - { - if (__typeCode == null) - { - if (__active) - { - return org.omg.CORBA.ORB.init().create_recursive_tc ( _id ); - } - __active = true; - org.omg.CORBA.StructMember[] _members0 = new org.omg.CORBA.StructMember [2]; - org.omg.CORBA.TypeCode _tcOf_members0 = null; - _tcOf_members0 = org.omg.CORBA.ORB.init ().get_primitive_tc (org.omg.CORBA.TCKind.tk_longlong); - _members0[0] = new org.omg.CORBA.StructMember ( - "time", - _tcOf_members0, - null); - _tcOf_members0 = org.omg.CORBA.ORB.init ().get_primitive_tc (org.omg.CORBA.TCKind.tk_longlong); - _members0[1] = new org.omg.CORBA.StructMember ( - "clockSeqAndNode", - _tcOf_members0, - null); - __typeCode = org.omg.CORBA.ORB.init ().create_struct_tc (com.eaio.uuid.UUIDHelper.id (), "UUID", _members0); - __active = false; - } - } - } - return __typeCode; - } - - public static String id () - { - return _id; - } - - public static com.eaio.uuid.UUID read (org.omg.CORBA.portable.InputStream istream) - { - com.eaio.uuid.UUID value = new com.eaio.uuid.UUID (); - value.time = istream.read_longlong (); - value.clockSeqAndNode = istream.read_longlong (); - return value; - } - - public static void write (org.omg.CORBA.portable.OutputStream ostream, com.eaio.uuid.UUID value) - { - ostream.write_longlong (value.time); - ostream.write_longlong (value.clockSeqAndNode); - } - -} diff --git a/test/files/presentation/akka/src/com/eaio/uuid/UUIDHolder.java b/test/files/presentation/akka/src/com/eaio/uuid/UUIDHolder.java deleted file mode 100644 index d5531f5e00..0000000000 --- a/test/files/presentation/akka/src/com/eaio/uuid/UUIDHolder.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.eaio.uuid; - -/** -* com/eaio/uuid/UUIDHolder.java . -* Generated by the IDL-to-Java compiler (portable), version "3.1" -* from uuid.idl -* Sonntag, 7. März 2004 21.35 Uhr CET -*/ - - -/** - * The UUID struct. - */ -public final class UUIDHolder implements org.omg.CORBA.portable.Streamable -{ - public com.eaio.uuid.UUID value = null; - - public UUIDHolder () - { - } - - public UUIDHolder (com.eaio.uuid.UUID initialValue) - { - value = initialValue; - } - - public void _read (org.omg.CORBA.portable.InputStream i) - { - value = com.eaio.uuid.UUIDHelper.read (i); - } - - public void _write (org.omg.CORBA.portable.OutputStream o) - { - com.eaio.uuid.UUIDHelper.write (o, value); - } - - public org.omg.CORBA.TypeCode _type () - { - return com.eaio.uuid.UUIDHelper.type (); - } - -} diff --git a/test/files/presentation/akka/src/pi.scala b/test/files/presentation/akka/src/pi.scala deleted file mode 100644 index b4c644052c..0000000000 --- a/test/files/presentation/akka/src/pi.scala +++ /dev/null @@ -1,108 +0,0 @@ - -import akka.actor.{Actor, PoisonPill} -import Actor._ -import akka.routing.{Routing, CyclicIterator} -import Routing._ - -import java.util.concurrent.CountDownLatch - -object Pi extends App { - - calculate/*#*/(nrOfWorkers = 4, nrOfElements = 10000, nrOfMessages = 10000) - - // ==================== - // ===== Messages ===== - // ==================== - sealed trait PiMessage - case object Calculate extends PiMessage/*#*/ - case class Work(start: Int, nrOfElements: Int) extends PiMessage - case class Result(value: Double) extends PiMessage - - // ================== - // ===== Worker ===== - // ================== - class Worker extends Actor/*#*/ { - - // define the work - def calculatePiFor(start: Int, nrOfElements: Int): Double = { - var acc = 0.0 - for (i <- start until (start + nrOfElements)) - acc += 4.0 * (1 - (i % 2) * 2) / (2 * i + 1) - acc - } - - def receive /*?*/ = { - case Work(start, nrOfElements) => - self reply/*#*/ Result(calculatePiFor(start, nrOfElements)) // perform the work // TODO: this currently returns wrong position for the symbol - } - } - - // ================== - // ===== Master ===== - // ================== - class Master( - nrOfWorkers: Int, nrOfMessages: Int, nrOfElements: Int, latch: CountDownLatch) - extends Actor { - - var pi: Double = _ - var nrOfResults: Int = _ - var start: Long = _ - - // create the workers - val workers = Vector.fill(nrOfWorkers)(actorOf[Worker]./*!*/start()) - - // wrap them with a load-balancing router - val router = Routing./*!*/loadBalancerActor(CyclicIterator(workers))./*!*/start() - - // message handler - def receive = { - case Calculate => - // schedule work - //for (start <- 0 until nrOfMessages) router ! Work(start, nrOfElements) - for (i <- 0 until nrOfMessages) router ! Work(i * nrOfElements, nrOfElements) - - // send a PoisonPill to all workers telling them to shut down themselves - router./*!*/!(Broadcast(PoisonPill)) - - // send a PoisonPill to the router, telling him to shut himself down - router ! PoisonPill - - case Result(value) => - // handle result from the worker - pi += value - nrOfResults/*#*/ += 1 - if (nrOfResults == nrOfMessages) self./*!*/stop() - } - - override def preStart() { - start = System.currentTimeMillis - } - - override def postStop() { - // tell the world that the calculation is complete - println( - "\n\tPi estimate: \t\t%s\n\tCalculation time: \t%s millis" - .format(pi, (System.currentTimeMillis - start))) - latch/*#*/.countDown() - } - } - - // ================== - // ===== Run it ===== - // ================== - 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) - - // create the master - val master = actorOf( - new Master(nrOfWorkers, nrOfMessages, nrOfElements, latch)).start() - - // start the calculation - master ! Calculate - - // wait for master to shut down - latch.await() - } -} diff --git a/test/files/presentation/timeofday.check b/test/files/presentation/timeofday.check deleted file mode 100644 index 2a09d0bcfc..0000000000 --- a/test/files/presentation/timeofday.check +++ /dev/null @@ -1,100 +0,0 @@ -reload: timeofday.scala - -askTypeCompletion at timeofday.scala(26,33) -================================================================================ -[response] aksTypeCompletion at (26,33) -retrieved 45 members -`method !=(x$1: Any)Boolean` -`method !=(x$1: AnyRef)Boolean` -`method ##()Int` -`method +(other: String)String` -`method ->[B](y: B)(timeofday.TimeOfDayVar, B)` -`method ==(x$1: Any)Boolean` -`method ==(x$1: AnyRef)Boolean` -`method asInstanceOf[T0]=> T0` -`method clone()Object` -`method ensuring(cond: Boolean)timeofday.TimeOfDayVar` -`method ensuring(cond: Boolean, msg: => Any)timeofday.TimeOfDayVar` -`method ensuring(cond: timeofday.TimeOfDayVar => Boolean)timeofday.TimeOfDayVar` -`method ensuring(cond: timeofday.TimeOfDayVar => Boolean, msg: => Any)timeofday.TimeOfDayVar` -`method eq(x$1: AnyRef)Boolean` -`method equals(x$1: Any)Boolean` -`method finalize()Unit` -`method formatted(fmtstr: String)String` -`method hashCode()Int` -`method hours=> Int` -`method hours_=(h: Int)Unit` -`method isInstanceOf[T0]=> Boolean` -`method minutes=> Int` -`method minutes_=(m: Int)Unit` -`method ne(x$1: AnyRef)Boolean` -`method notify()Unit` -`method notifyAll()Unit` -`method seconds=> Int` -`method seconds_=(s: Int)Unit` -`method synchronized[T0](x$1: T0)T0` -`method toString()String` -`method wait()Unit` -`method wait(x$1: Long)Unit` -`method wait(x$1: Long, x$2: Int)Unit` -`method x=> timeofday.TimeOfDayVar` -`method →[B](y: B)(timeofday.TimeOfDayVar, B)` -`value __leftOfArrowtimeofday.TimeOfDayVar` -`value __resultOfEnsuringtimeofday.TimeOfDayVar` -`value selfAny` -`variable hInt` -`variable mInt` -`variable sInt` -================================================================================ - -askTypeCompletion at timeofday.scala(32,19) -================================================================================ -[response] aksTypeCompletion at (32,19) -retrieved 45 members -`method !=(x$1: Any)Boolean` -`method !=(x$1: AnyRef)Boolean` -`method ##()Int` -`method +(other: String)String` -`method ->[B](y: B)(timeofday.TimeOfDayVar, B)` -`method ==(x$1: Any)Boolean` -`method ==(x$1: AnyRef)Boolean` -`method asInstanceOf[T0]=> T0` -`method clone()Object` -`method ensuring(cond: Boolean)timeofday.TimeOfDayVar` -`method ensuring(cond: Boolean, msg: => Any)timeofday.TimeOfDayVar` -`method ensuring(cond: timeofday.TimeOfDayVar => Boolean)timeofday.TimeOfDayVar` -`method ensuring(cond: timeofday.TimeOfDayVar => Boolean, msg: => Any)timeofday.TimeOfDayVar` -`method eq(x$1: AnyRef)Boolean` -`method equals(x$1: Any)Boolean` -`method finalize()Unit` -`method formatted(fmtstr: String)String` -`method hashCode()Int` -`method hours=> Int` -`method hours_=(h: Int)Unit` -`method isInstanceOf[T0]=> Boolean` -`method minutes=> Int` -`method minutes_=(m: Int)Unit` -`method ne(x$1: AnyRef)Boolean` -`method notify()Unit` -`method notifyAll()Unit` -`method seconds=> Int` -`method seconds_=(s: Int)Unit` -`method synchronized[T0](x$1: T0)T0` -`method toString()String` -`method wait()Unit` -`method wait(x$1: Long)Unit` -`method wait(x$1: Long, x$2: Int)Unit` -`method x=> timeofday.TimeOfDayVar` -`method →[B](y: B)(timeofday.TimeOfDayVar, B)` -`value __leftOfArrowtimeofday.TimeOfDayVar` -`value __resultOfEnsuringtimeofday.TimeOfDayVar` -`value selfAny` -`variable hInt` -`variable mInt` -`variable sInt` -================================================================================ - -askHyperlinkPos for `hours` at (33,11) timeofday.scala -================================================================================ -[response] found askHyperlinkPos for `hours` at (10,9) timeofday.scala -================================================================================ diff --git a/test/files/presentation/timeofday/Runner.scala b/test/files/presentation/timeofday/Runner.scala deleted file mode 100644 index 1c03e3d5ba..0000000000 --- a/test/files/presentation/timeofday/Runner.scala +++ /dev/null @@ -1,3 +0,0 @@ -import scala.tools.nsc.interactive.tests._ - -object Test extends InteractiveTest diff --git a/test/files/presentation/timeofday/src/timeofday.scala b/test/files/presentation/timeofday/src/timeofday.scala deleted file mode 100644 index d6355097f1..0000000000 --- a/test/files/presentation/timeofday/src/timeofday.scala +++ /dev/null @@ -1,35 +0,0 @@ -object timeofday { - class DateError extends Exception - - /** Simulating properties in Scala - * (example 4.2.1 in ScalaReference.pdf) - */ - class TimeOfDayVar { - private var h, m, s: Int = 0 - - def hours = h - - /** A method 'ident_=' is a setter for 'ident'. 'code.ident = ...' will - * be translated to a call to 'ident_=' - */ - def hours_= (h: Int) = - if (0 <= h && h < 24) this.h = h - else throw new DateError() - - def minutes = m - def minutes_= (m: Int) = - if (0 <= m && m < 60) this.m = m - else throw new DateError() - - def seconds = s - def seconds_= (s: Int) = - if (0 <= s && s < 60) this./*!*/s = s - else throw new DateError() - } - - def main(args: Array[String]) { - val d = new TimeOfDayVar - d.hours = 8; d./*!*/minutes = 30; d.seconds = 0 - d.hours/*#*/ = 25 // throws a DateError exception - } -} \ No newline at end of file -- cgit v1.2.3 From 7eb45e79b827dac8520f61ef500ec50020fa2a92 Mon Sep 17 00:00:00 2001 From: luajalla Date: Mon, 5 Dec 2011 22:44:12 +0200 Subject: -Ydump-classes: the option to dump the generated bytecode -Ydump-classes option is intended to dump the compiler generated bytecode to the .class files in given directory. It can be pretty useful for reflective compilation that utilizes in-memory classloaders, for example to check the files if compiler produces invalid bytecode. In this case the dump helps to understand what exactly is wrong with the emitted class. The option format is -Ydump-classes

          . --- .../tools/nsc/backend/jvm/BytecodeWriters.scala | 20 ++++++++++++++++++-- .../scala/tools/nsc/backend/jvm/GenJVM.scala | 7 ++++++- .../scala/tools/nsc/settings/ScalaSettings.scala | 1 + 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala b/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala index 70aa8ff54e..865bacffaa 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala @@ -7,7 +7,7 @@ package scala.tools.nsc package backend.jvm import ch.epfl.lamp.fjbg._ -import java.io.{ DataOutputStream, OutputStream, File => JFile } +import java.io.{ DataOutputStream, FileOutputStream, OutputStream, File => JFile } import scala.tools.nsc.io._ import scala.tools.nsc.util.ScalaClassLoader import scala.tools.util.JavapClass @@ -85,7 +85,7 @@ trait BytecodeWriters { emitJavap(bytes, javapFile) } } - + trait ClassBytecodeWriter extends BytecodeWriter { def writeClass(label: String, jclass: JClass, sym: Symbol) { val outfile = getFile(sym, jclass, ".class") @@ -96,4 +96,20 @@ trait BytecodeWriters { informProgress("wrote '" + label + "' to " + outfile) } } + + trait DumpBytecodeWriter extends BytecodeWriter { + val baseDir = Directory(settings.Ydumpclasses.value).createDirectory() + + abstract override def writeClass(label: String, jclass: JClass, sym: Symbol) { + super.writeClass(label, jclass, sym) + + val pathName = jclass.getName() + var dumpFile = pathName.split("[./]").foldLeft(baseDir: Path) (_ / _) changeExtension "class" toFile; + dumpFile.parent.createDirectory() + val outstream = new DataOutputStream(new FileOutputStream(dumpFile.path)) + + try jclass writeTo outstream + finally outstream.close() + } + } } diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala index 3fe5b83515..e55ceaa133 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala @@ -129,7 +129,12 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with new DirectToJarfileWriter(f.file) case _ => - if (settings.Ygenjavap.isDefault) new ClassBytecodeWriter { } + if (settings.Ygenjavap.isDefault) { + if(settings.Ydumpclasses.isDefault) + new ClassBytecodeWriter { } + else + new ClassBytecodeWriter with DumpBytecodeWriter { } + } else new ClassBytecodeWriter with JavapBytecodeWriter { } } diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index 6be15e4e98..7fcfb6fc6d 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -139,6 +139,7 @@ trait ScalaSettings extends AbsScalaSettings val Yshowsyms = BooleanSetting ("-Yshow-syms", "Print the AST symbol hierarchy after each phase.") val skip = PhasesSetting ("-Yskip", "Skip") val Ygenjavap = StringSetting ("-Ygen-javap", "dir", "Generate a parallel output directory of .javap files.", "") + val Ydumpclasses = StringSetting ("-Ydump-classes", "dir", "Dump the generated bytecode to .class files (useful for reflective compilation that utilizes in-memory classloaders).", "") val Ynosqueeze = BooleanSetting ("-Yno-squeeze", "Disable creation of compact code in matching.") val Ystatistics = BooleanSetting ("-Ystatistics", "Print compiler statistics.") . withPostSetHook(set => util.Statistics.enabled = set.value) -- cgit v1.2.3 From 526c086e121d8d6c15726c769edbf96efd882ae7 Mon Sep 17 00:00:00 2001 From: Josh Marcus Date: Tue, 6 Dec 2011 11:27:17 -0500 Subject: Update scaladoc links to collections overview. Change scaladoc links in collection classes to point at re-formatted Collections Overview on docs.scala-lang.org. Fix minor typo: s/Ummutable/Immutable --- src/library/scala/Array.scala | 2 +- src/library/scala/collection/immutable/BitSet.scala | 2 +- src/library/scala/collection/immutable/HashMap.scala | 2 +- src/library/scala/collection/immutable/List.scala | 6 +----- src/library/scala/collection/immutable/ListMap.scala | 2 +- src/library/scala/collection/immutable/Queue.scala | 4 ++-- src/library/scala/collection/immutable/Range.scala | 2 +- src/library/scala/collection/immutable/Stack.scala | 2 +- src/library/scala/collection/immutable/Stream.scala | 4 ++-- src/library/scala/collection/immutable/TreeMap.scala | 2 +- src/library/scala/collection/immutable/TreeSet.scala | 2 +- src/library/scala/collection/immutable/Vector.scala | 2 +- src/library/scala/collection/mutable/ArrayBuffer.scala | 4 ++-- src/library/scala/collection/mutable/ArraySeq.scala | 2 +- src/library/scala/collection/mutable/ArrayStack.scala | 2 +- src/library/scala/collection/mutable/BitSet.scala | 2 +- src/library/scala/collection/mutable/ConcurrentMap.scala | 2 +- src/library/scala/collection/mutable/DoubleLinkedList.scala | 2 +- src/library/scala/collection/mutable/HashMap.scala | 2 +- src/library/scala/collection/mutable/HashSet.scala | 2 +- src/library/scala/collection/mutable/LinearSeq.scala | 4 ++-- src/library/scala/collection/mutable/LinkedList.scala | 2 +- src/library/scala/collection/mutable/ListBuffer.scala | 2 +- src/library/scala/collection/mutable/MutableList.scala | 2 +- src/library/scala/collection/mutable/Queue.scala | 2 +- src/library/scala/collection/mutable/Stack.scala | 4 ++-- src/library/scala/collection/mutable/StringBuilder.scala | 2 +- src/library/scala/collection/mutable/WeakHashMap.scala | 4 ++-- 28 files changed, 34 insertions(+), 38 deletions(-) diff --git a/src/library/scala/Array.scala b/src/library/scala/Array.scala index ae0dd68dfd..7f85945c88 100644 --- a/src/library/scala/Array.scala +++ b/src/library/scala/Array.scala @@ -465,7 +465,7 @@ object Array extends FallbackArrayBuilding { * * @author Martin Odersky * @version 1.0 - * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_38.html "The Scala 2.8 Collections API"]] + * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_38.html#anchor "The Scala 2.8 Collections' API"]] * section on `Array` by Martin Odersky for more information. */ final class Array[T](_length: Int) extends java.io.Serializable with java.lang.Cloneable { diff --git a/src/library/scala/collection/immutable/BitSet.scala b/src/library/scala/collection/immutable/BitSet.scala index 4e2f5e45b5..abccd91f9c 100644 --- a/src/library/scala/collection/immutable/BitSet.scala +++ b/src/library/scala/collection/immutable/BitSet.scala @@ -17,7 +17,7 @@ import mutable.{ Builder, SetBuilder } /** A class for immutable bitsets. * $bitsetinfo - * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_21.html "The Scala 2.8 Collections API"]] + * @see [[http://docs.scala-lang.org/overviews/collections/concrete-immutable-collection-classes.html#immutable_bitsets "Scala's Collection Library overview"]] * section on `Immutable BitSets` for more information. * * @define Coll immutable.BitSet diff --git a/src/library/scala/collection/immutable/HashMap.scala b/src/library/scala/collection/immutable/HashMap.scala index 358a085e86..55ce8fa822 100644 --- a/src/library/scala/collection/immutable/HashMap.scala +++ b/src/library/scala/collection/immutable/HashMap.scala @@ -25,7 +25,7 @@ import parallel.immutable.ParHashMap * @author Tiark Rompf * @version 2.8 * @since 2.3 - * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_19.html "The Scala 2.8 Collections API"]] + * @see [[http://docs.scala-lang.org/overviews/collections/concrete-immutable-collection-classes.html#hash_tries "Scala's Collection Library overview"]] * section on `Hash Tries` for more information. * @define Coll immutable.HashMap * @define coll immutable hash map diff --git a/src/library/scala/collection/immutable/List.scala b/src/library/scala/collection/immutable/List.scala index b6714f9dde..531eac6c01 100644 --- a/src/library/scala/collection/immutable/List.scala +++ b/src/library/scala/collection/immutable/List.scala @@ -57,13 +57,9 @@ import annotation.tailrec * @author Martin Odersky and others * @version 2.8 * @since 1.0 - * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_13.html "The Scala 2..8 Collections API"]] + * @see [["http://docs.scala-lang.org/overviews/collections/concrete-immutable-collection-classes.html#lists" "Scala's Collection Library overview"]] * section on `Lists` for more information. - - * - * @tparam A the type of the list's elements * - * @define Coll List * @define coll list * @define thatinfo the class of the returned collection. In the standard library configuration, * `That` is always `List[B]` because an implicit of type `CanBuildFrom[List, B, That]` diff --git a/src/library/scala/collection/immutable/ListMap.scala b/src/library/scala/collection/immutable/ListMap.scala index 2231da510a..e008fb86e3 100644 --- a/src/library/scala/collection/immutable/ListMap.scala +++ b/src/library/scala/collection/immutable/ListMap.scala @@ -16,7 +16,7 @@ import annotation.{tailrec, bridge} /** $factoryInfo * @since 1 - * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_22.html "The Scala 2.8 Collections API"]] + * @see [[http://docs.scala-lang.org/overviews/collections/concrete-immutable-collection-classes.html#list_maps "Scala's Collection Library overview"]] * section on `List Maps` for more information. * * @define Coll immutable.ListMap diff --git a/src/library/scala/collection/immutable/Queue.scala b/src/library/scala/collection/immutable/Queue.scala index 53ed227e51..da04446281 100644 --- a/src/library/scala/collection/immutable/Queue.scala +++ b/src/library/scala/collection/immutable/Queue.scala @@ -27,8 +27,8 @@ import annotation.tailrec * @author Erik Stenman * @version 1.0, 08/07/2003 * @since 1 - * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_17.html "The Scala 2.8 Collections API"]] - * section on `Ummutable Queues` for more information. + * @see [[http://docs.scala-lang.org/overviews/collections/concrete-immutable-collection-classes.html#immutable_queues "Scala's Collection Library overview"]] + * section on `Immutable Queues` for more information. * * @define Coll immutable.Queue * @define coll immutable queue diff --git a/src/library/scala/collection/immutable/Range.scala b/src/library/scala/collection/immutable/Range.scala index f089298350..e891f8bec8 100644 --- a/src/library/scala/collection/immutable/Range.scala +++ b/src/library/scala/collection/immutable/Range.scala @@ -31,7 +31,7 @@ import annotation.bridge * @author Paul Phillips * @version 2.8 * @since 2.5 - * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_18.html "The Scala 2.8 Collections API"]] + * @see [[http://docs.scala-lang.org/overviews/collections/concrete-immutable-collection-classes.html#ranges "Scala's Collection Library overview"]] * section on `Ranges` for more information. * * @define Coll Range diff --git a/src/library/scala/collection/immutable/Stack.scala b/src/library/scala/collection/immutable/Stack.scala index 4de0f9e8f4..50fc2795c0 100644 --- a/src/library/scala/collection/immutable/Stack.scala +++ b/src/library/scala/collection/immutable/Stack.scala @@ -34,7 +34,7 @@ object Stack extends SeqFactory[Stack] { * @author Matthias Zenger * @version 1.0, 10/07/2003 * @since 1 - * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_16.html "The Scala 2.8 Collections API"]] + * @see [[http://docs.scala-lang.org/overviews/collections/concrete-immutable-collection-classes.html#immutable_stacks "Scala's Collection Library overview"]] * section on `Immutable stacks` for more information. * * @define Coll immutable.Stack diff --git a/src/library/scala/collection/immutable/Stream.scala b/src/library/scala/collection/immutable/Stream.scala index cb387c6316..e6587f9615 100644 --- a/src/library/scala/collection/immutable/Stream.scala +++ b/src/library/scala/collection/immutable/Stream.scala @@ -172,8 +172,8 @@ import Stream.cons * @author Martin Odersky, Matthias Zenger * @version 1.1 08/08/03 * @since 2.8 - * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_14.html "The Scala 2.8 Collections API"]] - * section on `Streams` for more information. + * @see [[http://docs.scala-lang.org/overviews/collections/concrete-immutable-collection-classes.html#streams "Scala's Collection Library overview"]] + * section on `Streams` for more information. * @define naturalsEx def naturalsFrom(i: Int): Stream[Int] = i #:: naturalsFrom(i + 1) * @define Coll Stream diff --git a/src/library/scala/collection/immutable/TreeMap.scala b/src/library/scala/collection/immutable/TreeMap.scala index 66f8763a8d..ef0eac3701 100644 --- a/src/library/scala/collection/immutable/TreeMap.scala +++ b/src/library/scala/collection/immutable/TreeMap.scala @@ -36,7 +36,7 @@ object TreeMap extends ImmutableSortedMapFactory[TreeMap] { * @author Matthias Zenger * @version 1.1, 03/05/2004 * @since 1 - * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_20.html "The Scala 2.8 Collections API"]] + * @see [[http://docs.scala-lang.org/overviews/collections/concrete-immutable-collection-classes.html#redblack_trees "Scala's Collection Library overview"]] * section on `Red-Black Trees` for more information. * * @define Coll immutable.TreeMap diff --git a/src/library/scala/collection/immutable/TreeSet.scala b/src/library/scala/collection/immutable/TreeSet.scala index 966e03b984..8b90ece143 100644 --- a/src/library/scala/collection/immutable/TreeSet.scala +++ b/src/library/scala/collection/immutable/TreeSet.scala @@ -36,7 +36,7 @@ object TreeSet extends ImmutableSortedSetFactory[TreeSet] { * @author Martin Odersky * @version 2.0, 02/01/2007 * @since 1 - * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_20.html "The Scala 2.8 Collections API"]] + * @see [[http://docs.scala-lang.org/overviews/collections/concrete-immutable-collection-classes.html#redblack_trees "Scala's Collection Library overview"]] * section on `Red-Black Trees` for more information. * * @define Coll immutable.TreeSet diff --git a/src/library/scala/collection/immutable/Vector.scala b/src/library/scala/collection/immutable/Vector.scala index 03cd98d20e..55c31feec2 100644 --- a/src/library/scala/collection/immutable/Vector.scala +++ b/src/library/scala/collection/immutable/Vector.scala @@ -35,7 +35,7 @@ object Vector extends SeqFactory[Vector] { * endian bit-mapped vector trie with a branching factor of 32. Locality is very good, but not * contiguous, which is good for very large sequences. * - * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_15.html "The Scala 2.8 Collections API"]] + * @see [[http://docs.scala-lang.org/overviews/collections/concrete-immutable-collection-classes.html#vectors "Scala's Collection Library overview"]] * section on `Vectors` for more information. * * @tparam A the element type diff --git a/src/library/scala/collection/mutable/ArrayBuffer.scala b/src/library/scala/collection/mutable/ArrayBuffer.scala index 503ada0153..bfdc08536c 100644 --- a/src/library/scala/collection/mutable/ArrayBuffer.scala +++ b/src/library/scala/collection/mutable/ArrayBuffer.scala @@ -23,8 +23,8 @@ import parallel.mutable.ParArray * @author Martin Odersky * @version 2.8 * @since 1 - * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_38.html "The Scala 2.8 Collections API"]] - * section on `Concrete Mutable Collection Classes` for more information. + * @see [[http://docs.scala-lang.org/overviews/collections/concrete-mutable-collection-classes.html#array_buffers "Scala's Collection Library overview"]] + * section on `Array Buffers` for more information. * * @tparam A the type of this arraybuffer's elements. diff --git a/src/library/scala/collection/mutable/ArraySeq.scala b/src/library/scala/collection/mutable/ArraySeq.scala index 3f7066b40f..cb86c416fe 100644 --- a/src/library/scala/collection/mutable/ArraySeq.scala +++ b/src/library/scala/collection/mutable/ArraySeq.scala @@ -21,7 +21,7 @@ import parallel.mutable.ParArray * @author Martin Odersky * @version 2.8 * @since 2.8 - * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_31.html "The Scala 2.8 Collections API"]] + * @see [[http://docs.scala-lang.org/overviews/collections/concrete-mutable-collection-classes.html#array_sequences "Scala's Collection Library overview"]] * section on `Array Sequences` for more information. * * @tparam A type of the elements contained in this array sequence. diff --git a/src/library/scala/collection/mutable/ArrayStack.scala b/src/library/scala/collection/mutable/ArrayStack.scala index faa22b948e..f5287312b9 100644 --- a/src/library/scala/collection/mutable/ArrayStack.scala +++ b/src/library/scala/collection/mutable/ArrayStack.scala @@ -46,7 +46,7 @@ object ArrayStack extends SeqFactory[ArrayStack] { * * @author David MacIver * @since 2.7 - * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_33.html "The Scala 2.8 Collections API"]] + * @see [[http://docs.scala-lang.org/overviews/collections/concrete-mutable-collection-classes.html#array_stacks "Scala's Collection Library overview"]] * section on `Array Stacks` for more information. * * @tparam T type of the elements contained in this array stack. diff --git a/src/library/scala/collection/mutable/BitSet.scala b/src/library/scala/collection/mutable/BitSet.scala index 03228f91b1..6b9673dae6 100644 --- a/src/library/scala/collection/mutable/BitSet.scala +++ b/src/library/scala/collection/mutable/BitSet.scala @@ -18,7 +18,7 @@ import BitSetLike.{LogWL, updateArray} * * $bitsetinfo * - * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_37.html "The Scala 2.8 Collections API"]] + * @see [[http://docs.scala-lang.org/overviews/collections/concrete-mutable-collection-classes.html#mutable_bitsets "Scala's Collection Library overview"]] * section on `Mutable Bitsets` for more information. * * @define Coll BitSet diff --git a/src/library/scala/collection/mutable/ConcurrentMap.scala b/src/library/scala/collection/mutable/ConcurrentMap.scala index be7718591b..fbb356ffb3 100644 --- a/src/library/scala/collection/mutable/ConcurrentMap.scala +++ b/src/library/scala/collection/mutable/ConcurrentMap.scala @@ -14,7 +14,7 @@ package mutable * $concurrentmapinfo * * @since 2.8 - * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_36.html "The Scala 2.8 Collections API"]] + * @see [[http://docs.scala-lang.org/overviews/collections/concrete-mutable-collection-classes.html#concurrent_maps "Scala's Collection Library overview"]] * section on `Concurrent Maps` for more information. * * @tparam A the key type of the map diff --git a/src/library/scala/collection/mutable/DoubleLinkedList.scala b/src/library/scala/collection/mutable/DoubleLinkedList.scala index 0934cfa081..49378a4f4e 100644 --- a/src/library/scala/collection/mutable/DoubleLinkedList.scala +++ b/src/library/scala/collection/mutable/DoubleLinkedList.scala @@ -20,7 +20,7 @@ import generic._ * @author Martin Odersky * @version 2.8 * @since 1 - * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_28.html "The Scala 2.8 Collections API"]] + * @see [[http://docs.scala-lang.org/overviews/collections/concrete-mutable-collection-classes.html#double_linked_lists "Scala's Collection Library overview"]] * section on `Double Linked Lists` for more information. * diff --git a/src/library/scala/collection/mutable/HashMap.scala b/src/library/scala/collection/mutable/HashMap.scala index 3c26ef0ab6..65a10f4ba9 100644 --- a/src/library/scala/collection/mutable/HashMap.scala +++ b/src/library/scala/collection/mutable/HashMap.scala @@ -15,7 +15,7 @@ import scala.collection.parallel.mutable.ParHashMap /** This class implements mutable maps using a hashtable. * * @since 1 - * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_34.html "The Scala 2.8 Collections API"]] + * @see [[http://docs.scala-lang.org/overviews/collections/concrete-mutable-collection-classes.html#hash_tables "Scala's Collection Library overview"]] * section on `Hash Tables` for more information. * * @tparam A the type of the keys contained in this hash map. diff --git a/src/library/scala/collection/mutable/HashSet.scala b/src/library/scala/collection/mutable/HashSet.scala index 7834c93ac4..8ed6b925aa 100644 --- a/src/library/scala/collection/mutable/HashSet.scala +++ b/src/library/scala/collection/mutable/HashSet.scala @@ -22,7 +22,7 @@ import collection.parallel.mutable.ParHashSet * @author Martin Odersky * @version 2.0, 31/12/2006 * @since 1 - * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_34.html "The Scala 2.8 Collections API"]] + * @see [[http://docs.scala-lang.org/overviews/collections/concrete-mutable-collection-classes.html#hash_tables "Scala's Collection Library overview"]] * section on `Hash Tables` for more information. * * @define Coll mutable.HashSet diff --git a/src/library/scala/collection/mutable/LinearSeq.scala b/src/library/scala/collection/mutable/LinearSeq.scala index 9f7443da0e..522ebfd277 100644 --- a/src/library/scala/collection/mutable/LinearSeq.scala +++ b/src/library/scala/collection/mutable/LinearSeq.scala @@ -19,8 +19,8 @@ import generic._ * * @define Coll LinearSeq * @define coll linear sequence - * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_29.html "The Scala 2.8 Collections API"]] - * section on `Mutable Lists` for more information. + * @see [[http://docs.scala-lang.org/overviews/collections/concrete-mutable-collection-classes.html#mutable_lists "Scala's Collection Library overview"]] + * section on `Mutable Lists` for more information. */ trait LinearSeq[A] extends Seq[A] with scala.collection.LinearSeq[A] diff --git a/src/library/scala/collection/mutable/LinkedList.scala b/src/library/scala/collection/mutable/LinkedList.scala index 6311a01b65..8510827697 100644 --- a/src/library/scala/collection/mutable/LinkedList.scala +++ b/src/library/scala/collection/mutable/LinkedList.scala @@ -33,7 +33,7 @@ import generic._ * @author Martin Odersky * @version 2.8 * @since 1 - * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_27.html "The Scala 2.8 Collections API"]] + * @see [[http://docs.scala-lang.org/overviews/collections/concrete-mutable-collection-classes.html#linked_lists "Scala's Collection Library overview"]] * section on `Linked Lists` for more information. * * @tparam A the type of the elements contained in this linked list. diff --git a/src/library/scala/collection/mutable/ListBuffer.scala b/src/library/scala/collection/mutable/ListBuffer.scala index 812b4010b4..131cdd0005 100644 --- a/src/library/scala/collection/mutable/ListBuffer.scala +++ b/src/library/scala/collection/mutable/ListBuffer.scala @@ -21,7 +21,7 @@ import immutable.{List, Nil, ::} * @author Martin Odersky * @version 2.8 * @since 1 - * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_25.html "The Scala 2.8 Collections API"]] + * @see [[http://docs.scala-lang.org/overviews/collections/concrete-mutable-collection-classes.html#list_buffers "Scala's Collection Library overview"]] * section on `List Buffers` for more information. * * @tparam A the type of this list buffer's elements. diff --git a/src/library/scala/collection/mutable/MutableList.scala b/src/library/scala/collection/mutable/MutableList.scala index de7f82095e..c9e44ac165 100644 --- a/src/library/scala/collection/mutable/MutableList.scala +++ b/src/library/scala/collection/mutable/MutableList.scala @@ -23,7 +23,7 @@ import immutable.{List, Nil} * @author Martin Odersky * @version 2.8 * @since 1 - * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_29.html "The Scala 2.8 Collections API"]] + * @see [[http://docs.scala-lang.org/overviews/collections/concrete-mutable-collection-classes.html#mutable_lists "Scala's Collection Library overview"]] * section on `Mutable Lists` for more information. */ @SerialVersionUID(5938451523372603072L) diff --git a/src/library/scala/collection/mutable/Queue.scala b/src/library/scala/collection/mutable/Queue.scala index 875ad12363..77b1ae21cb 100644 --- a/src/library/scala/collection/mutable/Queue.scala +++ b/src/library/scala/collection/mutable/Queue.scala @@ -20,7 +20,7 @@ import generic._ * @author Martin Odersky * @version 2.8 * @since 1 - * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_30.html "The Scala 2.8 Collections API"]] + * @see [[http://docs.scala-lang.org/overviews/collections/concrete-mutable-collection-classes.html#mutable_queues "Scala's Collection Library overview"]] * section on `Queues` for more information. * * @define Coll mutable.Queue diff --git a/src/library/scala/collection/mutable/Stack.scala b/src/library/scala/collection/mutable/Stack.scala index 0b4578dcc9..ffac3b78b7 100644 --- a/src/library/scala/collection/mutable/Stack.scala +++ b/src/library/scala/collection/mutable/Stack.scala @@ -44,8 +44,8 @@ object Stack extends SeqFactory[Stack] { * @author Martin Odersky * @version 2.8 * @since 1 - * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_32.html "The Scala 2.8 Collections API"]] - * section on `Array Sequences` for more information. + * @see [[http://docs.scala-lang.org/overviews/collections/concrete-mutable-collection-classes.html#stacks"Scala's Collection Library overview"]] + * section on `Stacks` for more information. * @define Coll Stack * @define coll stack * @define orderDependent diff --git a/src/library/scala/collection/mutable/StringBuilder.scala b/src/library/scala/collection/mutable/StringBuilder.scala index 27c1404e3e..603086d209 100644 --- a/src/library/scala/collection/mutable/StringBuilder.scala +++ b/src/library/scala/collection/mutable/StringBuilder.scala @@ -21,7 +21,7 @@ import immutable.StringLike * @author Martin Odersky * @version 2.8 * @since 2.7 - * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_26.html "The Scala 2.8 Collections API"]] + * @see [[http://docs.scala-lang.org/overviews/collections/concrete-mutable-collection-classes.html# "Scala's Collection Library overview"]] * section on `StringBuilders` for more information. */ @SerialVersionUID(0 - 8525408645367278351L) diff --git a/src/library/scala/collection/mutable/WeakHashMap.scala b/src/library/scala/collection/mutable/WeakHashMap.scala index 188cca2917..89d7c7a695 100644 --- a/src/library/scala/collection/mutable/WeakHashMap.scala +++ b/src/library/scala/collection/mutable/WeakHashMap.scala @@ -23,8 +23,8 @@ import generic._ * @tparam B type of values associated with the keys * * @since 2.8 - * @see [[http://www.scala-lang.org/docu/files/collections-api/collections_34.html "The Scala 2.8 Collections API"]] - * section on `Hash Tables` for more information. + * @see [[http://docs.scala-lang.org/overviews/collections/concrete-mutable-collection-classes.html#weak_hash_maps "Scala's Collection Library overview"]] + * section on `Weak Hash Maps` for more information. * * @define Coll WeakHashMap * @define coll weak hash map -- cgit v1.2.3 From 50e943fe5017d574439f7a2c5c7037d49f8952bc Mon Sep 17 00:00:00 2001 From: Blair Zajac Date: Tue, 6 Dec 2011 10:25:40 -0800 Subject: Fix documentation stutters. --- docs/examples/plugintemplate/src/plugintemplate/standalone/Main.scala | 2 +- project/build/ScalaSBTBuilder.scala | 2 +- src/compiler/scala/reflect/internal/pickling/UnPickler.scala | 2 +- src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala | 2 +- src/compiler/scala/tools/nsc/backend/icode/Linearizers.scala | 2 +- src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala | 2 +- src/compiler/scala/tools/nsc/doc/model/Entity.scala | 2 +- src/compiler/scala/tools/nsc/interactive/CompilerControl.scala | 2 +- src/compiler/scala/tools/nsc/io/Lexer.scala | 2 +- src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala | 2 +- src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala | 2 +- src/library/scala/Array.scala | 2 +- src/library/scala/collection/SeqLike.scala | 2 +- src/library/scala/sys/process/ProcessBuilder.scala | 2 +- src/library/scala/util/parsing/combinator/RegexParsers.scala | 2 +- src/library/scala/util/parsing/json/JSON.scala | 2 +- src/msil/ch/epfl/lamp/compiler/msil/emit/OpCode.scala | 4 ++-- src/msil/ch/epfl/lamp/compiler/msil/emit/OpCodes.scala | 4 ++-- test/disabled/presentation/akka/src/akka/actor/ActorRef.scala | 2 +- test/disabled/presentation/akka/src/akka/routing/Pool.scala | 2 +- .../disabled/presentation/akka/src/akka/util/ListenerManagement.scala | 4 ++-- test/files/run/adding-growing-set.scala | 2 +- 22 files changed, 25 insertions(+), 25 deletions(-) diff --git a/docs/examples/plugintemplate/src/plugintemplate/standalone/Main.scala b/docs/examples/plugintemplate/src/plugintemplate/standalone/Main.scala index 19d2613649..0bfcbf53c7 100644 --- a/docs/examples/plugintemplate/src/plugintemplate/standalone/Main.scala +++ b/docs/examples/plugintemplate/src/plugintemplate/standalone/Main.scala @@ -16,7 +16,7 @@ object Main { val settings = new Settings val command = new CompilerCommand(args.toList, settings) { - /** The command name that will be printed in in the usage message. + /** The command name that will be printed in the usage message. * This is automatically set to the value of 'plugin.commandname' in the * file build.properties. */ diff --git a/project/build/ScalaSBTBuilder.scala b/project/build/ScalaSBTBuilder.scala index 81c7860020..881e8c8452 100644 --- a/project/build/ScalaSBTBuilder.scala +++ b/project/build/ScalaSBTBuilder.scala @@ -351,7 +351,7 @@ object ScalaSBTBuilder { val stabilityTestTaskDescription = "run stability testing. It is required to use a clean build (for example, execute the clean-all action) in order to ensure correctness of the result." val paloTaskDescription = "create palo" val pastaTaskDescription = "create all the jar needed to make a new starr from quick (pasta = packed starr). It does not replace the current library and compiler jars in the libs folder, but the products of the task are instead located in target/pasta" - val newStarrTaskDescription = "create a new starr and replace the library and compiler jars in the libs folder. It will keep locker locker locked, meaning that if you want to update locker after updating starr, you must run the 'new-locker' command. It will not automatically run partest and stability testing before replacing." + val newStarrTaskDescription = "create a new starr and replace the library and compiler jars in the libs folder. It will keep locker locked, meaning that if you want to update locker after updating starr, you must run the 'new-locker' command. It will not automatically run partest and stability testing before replacing." val newLockerTaskDescription = "replace locker. It will build a new locker. It does not automatically rebuild quick." val buildForkjoinTaskDescription = "create all the jar needed to make a new forkjoin. It does not replace the current library and compiler jars in the libs folder, but the products of the task are instead located in target/libs." val newForkjoinTaskDescription = "create a new forkjoin and replace the corresponding jar in the libs folder." diff --git a/src/compiler/scala/reflect/internal/pickling/UnPickler.scala b/src/compiler/scala/reflect/internal/pickling/UnPickler.scala index 00dc04de80..9aa3d8a2c3 100644 --- a/src/compiler/scala/reflect/internal/pickling/UnPickler.scala +++ b/src/compiler/scala/reflect/internal/pickling/UnPickler.scala @@ -509,7 +509,7 @@ abstract class UnPickler /*extends reflect.generic.UnPickler*/ { val tpe = if (tag == EMPTYtree) NoType else readTypeRef() // Set by the three functions to follow. If symbol is non-null - // after the the new tree 't' has been created, t has its Symbol + // after the new tree 't' has been created, t has its Symbol // set to symbol; and it always has its Type set to tpe. var symbol: Symbol = null var mods: Modifiers = null diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala index f65481e29a..13f608ed4e 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala @@ -310,7 +310,7 @@ abstract class TreeBuilder { * for (P <- G) E ==> G.foreach (P => E) * * Here and in the following (P => E) is interpreted as the function (P => E) - * if P is a a variable pattern and as the partial function { case P => E } otherwise. + * if P is a variable pattern and as the partial function { case P => E } otherwise. * * 2. * diff --git a/src/compiler/scala/tools/nsc/backend/icode/Linearizers.scala b/src/compiler/scala/tools/nsc/backend/icode/Linearizers.scala index 8130c99978..1978a23d90 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/Linearizers.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/Linearizers.scala @@ -284,7 +284,7 @@ trait Linearizers { handler.startBlock +=: lb } - // The first block emitted after a try-catch must be the the one that the try / catch + // The first block emitted after a try-catch must be the one that the try / catch // blocks jump to (because in msil, these jumps cannot be emitted manually) var firstAfter: Option[BasicBlock] = None diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala index 78fab859a3..e80927f620 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala @@ -486,7 +486,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with // push the class jcode emitPUSH javaType(c.symbol).asInstanceOf[JReferenceType] - // push the the string array of field information + // push the string array of field information jcode emitPUSH fieldList.length jcode emitANEWARRAY strKind push(fieldList) diff --git a/src/compiler/scala/tools/nsc/doc/model/Entity.scala b/src/compiler/scala/tools/nsc/doc/model/Entity.scala index 266b9294dd..6eb14a4907 100644 --- a/src/compiler/scala/tools/nsc/doc/model/Entity.scala +++ b/src/compiler/scala/tools/nsc/doc/model/Entity.scala @@ -376,7 +376,7 @@ trait ParameterEntity extends Entity { /** A type parameter to a class, trait, or method. */ trait TypeParam extends ParameterEntity with HigherKinded { - /** The variance of this type type parameter. Valid values are "+", "-", and the empty string. */ + /** The variance of this type parameter. Valid values are "+", "-", and the empty string. */ def variance: String /** The lower bound for this type parameter, if it has been defined. */ diff --git a/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala b/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala index c2e27cd205..f2d59206e0 100644 --- a/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala +++ b/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala @@ -128,7 +128,7 @@ trait CompilerControl { self: Global => } /** Sets sync var `response` to the smallest fully attributed tree that encloses position `pos`. - * Note: Unlike for most other ask... operations, the source file belonging to `pos` needs not be be loaded. + * Note: Unlike for most other ask... operations, the source file belonging to `pos` needs not be loaded. */ def askTypeAt(pos: Position, response: Response[Tree]) = postWorkItem(new AskTypeAtItem(pos, response)) diff --git a/src/compiler/scala/tools/nsc/io/Lexer.scala b/src/compiler/scala/tools/nsc/io/Lexer.scala index 8f103f9b98..5ffb5b4d4f 100644 --- a/src/compiler/scala/tools/nsc/io/Lexer.scala +++ b/src/compiler/scala/tools/nsc/io/Lexer.scala @@ -281,7 +281,7 @@ class Lexer(rd: Reader) { /** The current token is a delimiter consisting of given character, reads next token, * otherwise raises an error. * @param c the given delimiter character to compare current token with - * @throws MalformedInput if the the current token `token` is not a delimiter, or + * @throws MalformedInput if the current token `token` is not a delimiter, or * consists of a character different from `c`. */ def accept(ch: Char) { diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala index cc88f471ab..e4ebe13217 100644 --- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala +++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala @@ -227,7 +227,7 @@ trait NamesDefaults { self: Analyzer => // super constructor calls case Select(sp @ Super(_, _), _) if isConstr => // 'moduleQual' fixes #3207. selection of the companion module of the - // superclass needs to have the same prefix as the the superclass. + // superclass needs to have the same prefix as the superclass. blockWithoutQualifier(moduleQual(baseFun.pos, sp.symbol.tpe.parents.head)) // self constructor calls (in secondary constructors) diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala index 3c72dc8413..c9991614e4 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala @@ -284,7 +284,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT } /** Add a protected accessor, if needed, and return a tree that calls - * the accessor and returns the the same member. The result is already + * the accessor and returns the same member. The result is already * typed. */ private def makeAccessor(tree: Select, targs: List[Tree]): Tree = { diff --git a/src/library/scala/Array.scala b/src/library/scala/Array.scala index 7f85945c88..99c54ce58c 100644 --- a/src/library/scala/Array.scala +++ b/src/library/scala/Array.scala @@ -24,7 +24,7 @@ class FallbackArrayBuilding { * Called instead of `Array.newBuilder` if the element type of an array * does not have a class manifest. Note that fallbackBuilder factory * needs an implicit parameter (otherwise it would not be dominated in - * implicit search by `Array.canBuildFrom`). We make sure that that + * implicit search by `Array.canBuildFrom`). We make sure that * implicit search is always successful. */ implicit def fallbackCanBuildFrom[T](implicit m: DummyImplicit): CanBuildFrom[Array[_], T, ArraySeq[T]] = diff --git a/src/library/scala/collection/SeqLike.scala b/src/library/scala/collection/SeqLike.scala index 8a4f2ff31a..b6b4bfb96d 100644 --- a/src/library/scala/collection/SeqLike.scala +++ b/src/library/scala/collection/SeqLike.scala @@ -21,7 +21,7 @@ import scala.math.Ordering * @define seqInfo * Sequences are special cases of iterable collections of class `Iterable`. * Unlike iterables, sequences always have a defined order of elements. - * Sequences provide a method `apply` for indexing. Indices range from `0` up the the `length` of + * Sequences provide a method `apply` for indexing. Indices range from `0` up to the `length` of * a sequence. Sequences support a number to find occurrences of elements or subsequences, including * `segmentLength`, `prefixLength`, `indexWhere`, `indexOf`, `lastIndexWhere`, `lastIndexOf`, * `startsWith`, `endsWith`, `indexOfSlice`. diff --git a/src/library/scala/sys/process/ProcessBuilder.scala b/src/library/scala/sys/process/ProcessBuilder.scala index 9acdc59094..214d908012 100644 --- a/src/library/scala/sys/process/ProcessBuilder.scala +++ b/src/library/scala/sys/process/ProcessBuilder.scala @@ -42,7 +42,7 @@ import ProcessBuilder._ * 2. `#&&` conditionally executes the second command if the previous one finished with * exit value 0. It mirrors shell's `&&`. * 3. `#||` conditionally executes the third command if the exit value of the previous - * command is is different than zero. It mirrors shell's `&&`. + * command is different than zero. It mirrors shell's `&&`. * * Not shown here, the equivalent of a shell's `;` would be `###`. The reason for this name is * that `;` is a reserved token in Scala. diff --git a/src/library/scala/util/parsing/combinator/RegexParsers.scala b/src/library/scala/util/parsing/combinator/RegexParsers.scala index a06b9d59ce..86eecd03c4 100644 --- a/src/library/scala/util/parsing/combinator/RegexParsers.scala +++ b/src/library/scala/util/parsing/combinator/RegexParsers.scala @@ -23,7 +23,7 @@ import scala.collection.immutable.PagedSeq * - There's an implicit conversion from [[scala.util.matching.Regex]] to `Parser[String]`, * so that regex expressions can be used as parser combinators. * - The parsing methods call the method `skipWhitespace` (defaults to `true`) and, if true, - * skip any whitespace before before each parser is called. + * skip any whitespace before each parser is called. * - Protected val `whiteSpace` returns a regex that identifies whitespace. * * For example, this creates a very simple calculator receiving `String` input: diff --git a/src/library/scala/util/parsing/json/JSON.scala b/src/library/scala/util/parsing/json/JSON.scala index 1464f80e3f..15d43cf2af 100644 --- a/src/library/scala/util/parsing/json/JSON.scala +++ b/src/library/scala/util/parsing/json/JSON.scala @@ -45,7 +45,7 @@ object JSON extends Parser { /** * Parse the given `JSON` string and return a list of elements. If the * string is a `JSON` object it will be a `JSONObject`. If it's a `JSON` - * array it will be be a `JSONArray`. + * array it will be a `JSONArray`. * * @param input the given `JSON` string. * @return an optional `JSONType` element. diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/OpCode.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/OpCode.scala index fbcdbf893f..b0c26884af 100644 --- a/src/msil/ch/epfl/lamp/compiler/msil/emit/OpCode.scala +++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/OpCode.scala @@ -887,7 +887,7 @@ opcode(Readonly, CEE_READONLY , "readonly." , 0xFFFFFE1E, POP_NONE, PUSH_NONE opcode(Bne_Un_S, CEE_BNE_UN_S, "bne.un.s", 0xFFFFFF33, POP_1_1 , PUSH_NONE, INLINE_TARGET_S, FLOW_COND_BRANCH) /** - * Transfers control to a target instruction (short form) if if the the first value is greather + * Transfers control to a target instruction (short form) if the first value is greather * than the second value, when comparing unsigned integer values or unordered float values. */ final val Bge_Un_S = new OpCode() @@ -973,7 +973,7 @@ opcode(Readonly, CEE_READONLY , "readonly." , 0xFFFFFE1E, POP_NONE, PUSH_NONE opcode(Bne_Un, CEE_BNE_UN , "bne.un", 0xFFFFFF40, POP_1_1 , PUSH_NONE, INLINE_TARGET, FLOW_COND_BRANCH) /** - * Transfers control to a target instruction if the the first value is greather than + * Transfers control to a target instruction if the first value is greather than * the second value, when comparing unsigned integer values or unordered float values. */ final val Bge_Un = new OpCode() diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/OpCodes.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/OpCodes.scala index d486c31af0..80e4267436 100644 --- a/src/msil/ch/epfl/lamp/compiler/msil/emit/OpCodes.scala +++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/OpCodes.scala @@ -307,7 +307,7 @@ object OpCodes { final val Bne_Un_S = OpCode.Bne_Un_S /** - * Transfers control to a target instruction (short form) if if the the first value is greather + * Transfers control to a target instruction (short form) if the first value is greather * than the second value, when comparing unsigned integer values or unordered float values. */ final val Bge_Un_S = OpCode.Bge_Un_S @@ -380,7 +380,7 @@ object OpCodes { final val Bne_Un = OpCode.Bne_Un /** - * Transfers control to a target instruction if the the first value is greather than + * Transfers control to a target instruction if the first value is greather than * the second value, when comparing unsigned integer values or unordered float values. */ final val Bge_Un = OpCode.Bge_Un diff --git a/test/disabled/presentation/akka/src/akka/actor/ActorRef.scala b/test/disabled/presentation/akka/src/akka/actor/ActorRef.scala index 07fa358744..ff67c9468e 100644 --- a/test/disabled/presentation/akka/src/akka/actor/ActorRef.scala +++ b/test/disabled/presentation/akka/src/akka/actor/ActorRef.scala @@ -471,7 +471,7 @@ trait ActorRef extends ActorRefShared with java.lang.Comparable[ActorRef] { scal *

          * To be invoked from within the actor itself. */ - @deprecated("Will be removed after 1.1, use use Actor.remote.actorOf instead and then link on success", "1.1") + @deprecated("Will be removed after 1.1, use Actor.remote.actorOf instead and then link on success", "1.1") def spawnLink(clazz: Class[_ <: Actor]): ActorRef /** diff --git a/test/disabled/presentation/akka/src/akka/routing/Pool.scala b/test/disabled/presentation/akka/src/akka/routing/Pool.scala index 0fd1bc8f49..d972bb84c8 100644 --- a/test/disabled/presentation/akka/src/akka/routing/Pool.scala +++ b/test/disabled/presentation/akka/src/akka/routing/Pool.scala @@ -220,7 +220,7 @@ trait BoundedCapacityStrategy extends CapacityStrategy with BoundedCapacitor */ /** - * The basic filter trait that composes ramp-up and and back-off subfiltering. + * The basic filter trait that composes ramp-up and back-off subfiltering. */ trait Filter { def rampup(pressure: Int, capacity: Int): Int diff --git a/test/disabled/presentation/akka/src/akka/util/ListenerManagement.scala b/test/disabled/presentation/akka/src/akka/util/ListenerManagement.scala index 7065397a45..863e905d59 100644 --- a/test/disabled/presentation/akka/src/akka/util/ListenerManagement.scala +++ b/test/disabled/presentation/akka/src/akka/util/ListenerManagement.scala @@ -22,7 +22,7 @@ trait ListenerManagement { protected def manageLifeCycleOfListeners: Boolean = true /** - * Adds the listener this this registry's listener list. + * Adds the listener this registry's listener list. * The listener is started by this method if manageLifeCycleOfListeners yields true. */ def addListener(listener: ActorRef) { @@ -31,7 +31,7 @@ trait ListenerManagement { } /** - * Removes the listener this this registry's listener list. + * Removes the listener this registry's listener list. * The listener is stopped by this method if manageLifeCycleOfListeners yields true. */ def removeListener(listener: ActorRef) { diff --git a/test/files/run/adding-growing-set.scala b/test/files/run/adding-growing-set.scala index 5903813ed1..ab94b893b2 100644 --- a/test/files/run/adding-growing-set.scala +++ b/test/files/run/adding-growing-set.scala @@ -1,4 +1,4 @@ -/** This will run a a loooong time if Set's builder copies a +/** This will run a loooong time if Set's builder copies a * complete new Set for every element. */ object Test { -- cgit v1.2.3 From c477839307eefd3925c44b5067d3eddad3ba5e6f Mon Sep 17 00:00:00 2001 From: Blair Zajac Date: Tue, 6 Dec 2011 10:29:13 -0800 Subject: Fix documentation typo. --- test/files/run/json.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/files/run/json.scala b/test/files/run/json.scala index 7d3b635006..a81f12564c 100644 --- a/test/files/run/json.scala +++ b/test/files/run/json.scala @@ -3,7 +3,7 @@ import scala.collection.immutable.TreeMap object Test extends App { /* This method converts parsed JSON back into real JSON notation with objects in - * sorted-key order. Not required by the spec, but it allows us to to a stable + * sorted-key order. Not required by the spec, but it allows us to do a stable * toString comparison. */ def jsonToString(in : Any) : String = in match { case l : List[_] => "[" + l.map(jsonToString).mkString(", ") + "]" -- cgit v1.2.3 From 001710d73eedbe3f23b7d704c772a8616ddf2f10 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Tue, 6 Dec 2011 14:25:49 -0800 Subject: Gave Option its own nonEmpty. A bit further down Option's slippery slope of collections methods, but those sudden implicit conversions to Iterable are legitimately annoying. --- src/library/scala/Option.scala | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/library/scala/Option.scala b/src/library/scala/Option.scala index c1b64808b0..bd498de847 100644 --- a/src/library/scala/Option.scala +++ b/src/library/scala/Option.scala @@ -162,6 +162,11 @@ sealed abstract class Option[+A] extends Product with Serializable { @inline final def filterNot(p: A => Boolean): Option[A] = if (isEmpty || !p(this.get)) this else None + /** Returns false if the option is $none, true otherwise. + * @note Implemented here to avoid the implicit conversion to Iterable. + */ + final def nonEmpty = isDefined + /** Necessary to keep $option from being implicitly converted to * [[scala.collection.Iterable]] in `for` comprehensions. */ -- cgit v1.2.3 From 7dd56671c0afbb9e94497a47b99230ce2814fc8d Mon Sep 17 00:00:00 2001 From: Simon Ochsenreither Date: Fri, 2 Dec 2011 12:01:27 +0100 Subject: Fixes the annoying spaces between name, type params and params in ScalaDoc. --- src/compiler/scala/tools/nsc/doc/html/page/Template.scala | 7 +++---- test/scaladoc/scala/html/HtmlFactoryTest.scala | 14 +++++++------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/compiler/scala/tools/nsc/doc/html/page/Template.scala b/src/compiler/scala/tools/nsc/doc/html/page/Template.scala index 813958af85..5e5320ca9a 100644 --- a/src/compiler/scala/tools/nsc/doc/html/page/Template.scala +++ b/src/compiler/scala/tools/nsc/doc/html/page/Template.scala @@ -563,8 +563,7 @@ class Template(tpl: DocTemplateEntity) extends HtmlPage { if (!nameLink.isEmpty) {nameHtml} else nameHtml - } - { + }{ def tparamsToHtml(mbr: Entity): NodeSeq = mbr match { case hk: HigherKinded => val tpss = hk.typeParams @@ -580,8 +579,8 @@ class Template(tpl: DocTemplateEntity) extends HtmlPage { case _ => NodeSeq.Empty } tparamsToHtml(mbr) - } - { if (isReduced) NodeSeq.Empty else { + }{ + if (isReduced) NodeSeq.Empty else { def paramsToHtml(vlsss: List[List[ValueParam]]): NodeSeq = { def param0(vl: ValueParam): NodeSeq = // notice the }{ in the next lines, they are necessary to avoid a undesired withspace in output diff --git a/test/scaladoc/scala/html/HtmlFactoryTest.scala b/test/scaladoc/scala/html/HtmlFactoryTest.scala index adad3b6053..c8dad4cf48 100644 --- a/test/scaladoc/scala/html/HtmlFactoryTest.scala +++ b/test/scaladoc/scala/html/HtmlFactoryTest.scala @@ -141,8 +141,8 @@ object Test extends Properties("HtmlFactory") { createTemplate("Trac4372.scala") match { case node: scala.xml.Node => { val html = node.toString - html.contains("+:\n") && - html.contains("-:\n") && + html.contains("+:") && + html.contains("-:") && html.contains("""(n: Int): Int""") } case _ => false @@ -247,11 +247,11 @@ object Test extends Properties("HtmlFactory") { val lines = """ |type Bar = AnyRef { type Dingus <: T forSome { type T <: String } } |type Foo = AnyRef { ... /* 3 definitions in type refinement */ } - |def g (x: T forSome { type T <: String }): String - |def h (x: Float): AnyRef { def quux(x: Int,y: Int): Int } - |def hh (x: Float): AnyRef { def quux(x: Int,y: Int): Int } - |def j (x: Int): Bar - |def k (): AnyRef { type Dingus <: T forSome { type T <: String } } + |def g(x: T forSome { type T <: String }): String + |def h(x: Float): AnyRef { def quux(x: Int,y: Int): Int } + |def hh(x: Float): AnyRef { def quux(x: Int,y: Int): Int } + |def j(x: Int): Bar + |def k(): AnyRef { type Dingus <: T forSome { type T <: String } } """.stripMargin.trim.lines map (_.trim) files("RefinementAndExistentials.html") match { -- cgit v1.2.3