Merge remote-tracking branch 'origin/master' into wip-remote-supervision-rk

This commit is contained in:
Roland 2011-12-13 16:59:43 +01:00
commit 92e7693203
247 changed files with 7896 additions and 4703 deletions

2
.gitignore vendored
View file

@ -16,6 +16,7 @@ reports
dist
target
deploy/*.jar
.history
data
out
logs
@ -58,3 +59,4 @@ akka.sublime-project
akka.sublime-workspace
.target
.multi-jvm
_mb

View file

@ -1,4 +0,0 @@
update
reload
projects
exit

View file

@ -26,7 +26,7 @@ public class JavaAPI {
@Test
public void mustBeAbleToCreateActorRefFromClass() {
ActorRef ref = system.actorOf(JavaAPITestActor.class);
ActorRef ref = system.actorOf(new Props(JavaAPITestActor.class));
assertNotNull(ref);
}
@ -42,7 +42,7 @@ public class JavaAPI {
@Test
public void mustAcceptSingleArgTell() {
ActorRef ref = system.actorOf(JavaAPITestActor.class);
ActorRef ref = system.actorOf(new Props(JavaAPITestActor.class));
ref.tell("hallo");
ref.tell("hallo", ref);
}

View file

@ -63,16 +63,16 @@ class ActorFireForgetRequestReplySpec extends AkkaSpec with BeforeAndAfterEach w
"An Actor" must {
"reply to bang message using reply" in {
val replyActor = system.actorOf[ReplyActor]
val senderActor = system.actorOf(new SenderActor(replyActor))
val replyActor = system.actorOf(Props[ReplyActor])
val senderActor = system.actorOf(Props(new SenderActor(replyActor)))
senderActor ! "Init"
state.finished.await
state.s must be("Reply")
}
"reply to bang message using implicit sender" in {
val replyActor = system.actorOf[ReplyActor]
val senderActor = system.actorOf(new SenderActor(replyActor))
val replyActor = system.actorOf(Props[ReplyActor])
val senderActor = system.actorOf(Props(new SenderActor(replyActor)))
senderActor ! "InitImplicit"
state.finished.await
state.s must be("ReplyImplicit")

View file

@ -123,7 +123,8 @@ class ActorLookupSpec extends AkkaSpec with DefaultTimeout {
a ! 42
f.isCompleted must be === true
f.get must be === 42
system.actorFor(a.path) must be === system.deadLetters
// clean-up is run as onComplete callback, i.e. dispatched on another thread
awaitCond(system.actorFor(a.path) == system.deadLetters, 1 second)
}
}
@ -229,7 +230,8 @@ class ActorLookupSpec extends AkkaSpec with DefaultTimeout {
a ! 42
f.isCompleted must be === true
f.get must be === 42
(c2 ? LookupPath(a.path)).get must be === system.deadLetters
// clean-up is run as onComplete callback, i.e. dispatched on another thread
awaitCond((c2 ? LookupPath(a.path)).get == system.deadLetters, 1 second)
}
}

View file

@ -145,82 +145,82 @@ class ActorRefSpec extends AkkaSpec with DefaultTimeout {
filterException[akka.actor.ActorInitializationException] {
intercept[akka.actor.ActorInitializationException] {
wrap(result
actorOf(new Actor {
actorOf(Props(new Actor {
val nested = promiseIntercept(new Actor { def receive = { case _ } })(result)
def receive = { case _ }
}))
})))
}
contextStackMustBeEmpty
intercept[akka.actor.ActorInitializationException] {
wrap(result
actorOf(promiseIntercept(new FailingOuterActor(actorOf(new InnerActor)))(result)))
actorOf(Props(promiseIntercept(new FailingOuterActor(actorOf(Props(new InnerActor))))(result))))
}
contextStackMustBeEmpty
intercept[akka.actor.ActorInitializationException] {
wrap(result
actorOf(new OuterActor(actorOf(promiseIntercept(new FailingInnerActor)(result)))))
actorOf(Props(new OuterActor(actorOf(Props(promiseIntercept(new FailingInnerActor)(result)))))))
}
contextStackMustBeEmpty
intercept[akka.actor.ActorInitializationException] {
wrap(result
actorOf(promiseIntercept(new FailingInheritingOuterActor(actorOf(new InnerActor)))(result)))
actorOf(Props(promiseIntercept(new FailingInheritingOuterActor(actorOf(Props(new InnerActor))))(result))))
}
contextStackMustBeEmpty
intercept[akka.actor.ActorInitializationException] {
wrap(result
actorOf(new FailingOuterActor(actorOf(promiseIntercept(new FailingInheritingInnerActor)(result)))))
actorOf(Props(new FailingOuterActor(actorOf(Props(promiseIntercept(new FailingInheritingInnerActor)(result)))))))
}
contextStackMustBeEmpty
intercept[akka.actor.ActorInitializationException] {
wrap(result
actorOf(new FailingInheritingOuterActor(actorOf(promiseIntercept(new FailingInheritingInnerActor)(result)))))
actorOf(Props(new FailingInheritingOuterActor(actorOf(Props(promiseIntercept(new FailingInheritingInnerActor)(result)))))))
}
contextStackMustBeEmpty
intercept[akka.actor.ActorInitializationException] {
wrap(result
actorOf(new FailingInheritingOuterActor(actorOf(promiseIntercept(new FailingInnerActor)(result)))))
actorOf(Props(new FailingInheritingOuterActor(actorOf(Props(promiseIntercept(new FailingInnerActor)(result)))))))
}
contextStackMustBeEmpty
intercept[akka.actor.ActorInitializationException] {
wrap(result
actorOf(new OuterActor(actorOf(new InnerActor {
actorOf(Props(new OuterActor(actorOf(Props(new InnerActor {
val a = promiseIntercept(new InnerActor)(result)
}))))
}))))))
}
contextStackMustBeEmpty
intercept[akka.actor.ActorInitializationException] {
wrap(result
actorOf(new FailingOuterActor(actorOf(promiseIntercept(new FailingInheritingInnerActor)(result)))))
actorOf(Props(new FailingOuterActor(actorOf(Props(promiseIntercept(new FailingInheritingInnerActor)(result)))))))
}
contextStackMustBeEmpty
intercept[akka.actor.ActorInitializationException] {
wrap(result
actorOf(new OuterActor(actorOf(promiseIntercept(new FailingInheritingInnerActor)(result)))))
actorOf(Props(new OuterActor(actorOf(Props(promiseIntercept(new FailingInheritingInnerActor)(result)))))))
}
contextStackMustBeEmpty
intercept[akka.actor.ActorInitializationException] {
wrap(result
actorOf(new OuterActor(actorOf(promiseIntercept({ new InnerActor; new InnerActor })(result)))))
actorOf(Props(new OuterActor(actorOf(Props(promiseIntercept({ new InnerActor; new InnerActor })(result)))))))
}
contextStackMustBeEmpty
@ -229,7 +229,7 @@ class ActorRefSpec extends AkkaSpec with DefaultTimeout {
filterException[java.lang.IllegalStateException] {
(intercept[java.lang.IllegalStateException] {
wrap(result
actorOf(new OuterActor(actorOf(promiseIntercept({ throw new IllegalStateException("Ur state be b0rked"); new InnerActor })(result)))))
actorOf(Props(new OuterActor(actorOf(Props(promiseIntercept({ throw new IllegalStateException("Ur state be b0rked"); new InnerActor })(result)))))))
}).getMessage must be === "Ur state be b0rked"
contextStackMustBeEmpty
@ -237,7 +237,7 @@ class ActorRefSpec extends AkkaSpec with DefaultTimeout {
}
"be serializable using Java Serialization on local node" in {
val a = system.actorOf[InnerActor]
val a = system.actorOf(Props[InnerActor])
import java.io._
@ -260,7 +260,7 @@ class ActorRefSpec extends AkkaSpec with DefaultTimeout {
}
"throw an exception on deserialize if no system in scope" in {
val a = system.actorOf[InnerActor]
val a = system.actorOf(Props[InnerActor])
import java.io._
@ -301,10 +301,10 @@ class ActorRefSpec extends AkkaSpec with DefaultTimeout {
}
"support nested actorOfs" in {
val a = system.actorOf(new Actor {
val nested = system.actorOf(new Actor { def receive = { case _ } })
val a = system.actorOf(Props(new Actor {
val nested = system.actorOf(Props(new Actor { def receive = { case _ } }))
def receive = { case _ sender ! nested }
})
}))
val nested = (a ? "any").as[ActorRef].get
a must not be null

View file

@ -76,7 +76,7 @@ object Chameneos {
var numFaded = 0
override def preStart() = {
for (i 0 until numChameneos) context.actorOf(new Chameneo(self, colours(i % 3), i))
for (i 0 until numChameneos) context.actorOf(Props(new Chameneo(self, colours(i % 3), i)))
}
def receive = {
@ -107,7 +107,7 @@ object Chameneos {
def run {
// System.setProperty("akka.config", "akka.conf")
Chameneos.start = System.currentTimeMillis
val system = ActorSystem().actorOf(new Mall(1000000, 4))
val system = ActorSystem().actorOf(Props(new Mall(1000000, 4)))
Thread.sleep(10000)
println("Elapsed: " + (end - start))
system.stop()

View file

@ -112,14 +112,14 @@ class FSMActorSpec extends AkkaSpec(Map("akka.actor.debug.fsm" -> true)) with Im
import latches._
// lock that locked after being open for 1 sec
val lock = system.actorOf(new Lock("33221", 1 second, latches))
val lock = system.actorOf(Props(new Lock("33221", 1 second, latches)))
val transitionTester = system.actorOf(new Actor {
val transitionTester = system.actorOf(Props(new Actor {
def receive = {
case Transition(_, _, _) transitionCallBackLatch.open
case CurrentState(_, Locked) initialStateLatch.open
}
})
}))
lock ! SubscribeTransitionCallBack(transitionTester)
initialStateLatch.await
@ -143,13 +143,13 @@ class FSMActorSpec extends AkkaSpec(Map("akka.actor.debug.fsm" -> true)) with Im
val answerLatch = TestLatch()
object Hello
object Bye
val tester = system.actorOf(new Actor {
val tester = system.actorOf(Props(new Actor {
protected def receive = {
case Hello lock ! "hello"
case "world" answerLatch.open
case Bye lock ! "bye"
}
})
}))
tester ! Hello
answerLatch.await
@ -185,7 +185,7 @@ class FSMActorSpec extends AkkaSpec(Map("akka.actor.debug.fsm" -> true)) with Im
case x testActor ! x
}
}
val ref = system.actorOf(fsm)
val ref = system.actorOf(Props(fsm))
started.await
ref.stop()
expectMsg(1 second, fsm.StopEvent(Shutdown, 1, null))

View file

@ -14,7 +14,7 @@ class FSMTimingSpec extends AkkaSpec with ImplicitSender {
import FSMTimingSpec._
import FSM._
val fsm = system.actorOf(new StateMachine(testActor))
val fsm = system.actorOf(Props(new StateMachine(testActor)))
fsm ! SubscribeTransitionCallBack(testActor)
expectMsg(1 second, CurrentState(fsm, Initial))

View file

@ -56,7 +56,7 @@ class FSMTransitionSpec extends AkkaSpec with ImplicitSender {
"A FSM transition notifier" must {
"notify listeners" in {
val fsm = system.actorOf(new MyFSM(testActor))
val fsm = system.actorOf(Props(new MyFSM(testActor)))
within(1 second) {
fsm ! SubscribeTransitionCallBack(testActor)
expectMsg(CurrentState(fsm, 0))
@ -68,8 +68,8 @@ class FSMTransitionSpec extends AkkaSpec with ImplicitSender {
}
"not fail when listener goes away" in {
val forward = system.actorOf(new Forwarder(testActor))
val fsm = system.actorOf(new MyFSM(testActor))
val forward = system.actorOf(Props(new Forwarder(testActor)))
val fsm = system.actorOf(Props(new MyFSM(testActor)))
val sup = system.actorOf(Props(new Actor {
context.watch(fsm)
def receive = { case _ }
@ -88,7 +88,7 @@ class FSMTransitionSpec extends AkkaSpec with ImplicitSender {
"A FSM" must {
"make previous and next state data available in onTransition" in {
val fsm = system.actorOf(new OtherFSM(testActor))
val fsm = system.actorOf(Props(new OtherFSM(testActor)))
within(300 millis) {
fsm ! "tick"
expectMsg((0, 1))

View file

@ -13,14 +13,14 @@ object ForwardActorSpec {
val ExpectedMessage = "FOO"
def createForwardingChain(system: ActorSystem): ActorRef = {
val replier = system.actorOf(new Actor {
val replier = system.actorOf(Props(new Actor {
def receive = { case x sender ! x }
})
}))
def mkforwarder(forwardTo: ActorRef) = system.actorOf(
def mkforwarder(forwardTo: ActorRef) = system.actorOf(Props(
new Actor {
def receive = { case x forwardTo forward x }
})
}))
mkforwarder(mkforwarder(mkforwarder(replier)))
}
@ -35,7 +35,7 @@ class ForwardActorSpec extends AkkaSpec {
"forward actor reference when invoking forward on bang" in {
val latch = new TestLatch(1)
val replyTo = system.actorOf(new Actor { def receive = { case ExpectedMessage latch.countDown() } })
val replyTo = system.actorOf(Props(new Actor { def receive = { case ExpectedMessage latch.countDown() } }))
val chain = createForwardingChain(system)

View file

@ -11,22 +11,13 @@ class HotSwapSpec extends AkkaSpec with ImplicitSender {
"An Actor" must {
"be able to hotswap its behavior with HotSwap(..)" in {
val a = system.actorOf(new Actor {
def receive = { case _ sender ! "default" }
})
a ! HotSwap(context { case _ context.sender ! "swapped" })
a ! "swapped"
expectMsg("swapped")
}
"be able to hotswap its behavior with become(..)" in {
val a = system.actorOf(new Actor {
val a = system.actorOf(Props(new Actor {
def receive = {
case "init" sender ! "init"
case "swap" context.become({ case x: String context.sender ! x })
}
})
}))
a ! "init"
expectMsg("init")
@ -35,34 +26,8 @@ class HotSwapSpec extends AkkaSpec with ImplicitSender {
expectMsg("swapped")
}
"be able to revert hotswap its behavior with RevertHotSwap(..)" in {
val a = system.actorOf(new Actor {
def receive = {
case "init" sender ! "init"
}
})
a ! "init"
expectMsg("init")
a ! HotSwap(context { case "swapped" context.sender ! "swapped" })
a ! "swapped"
expectMsg("swapped")
a ! RevertHotSwap
a ! "init"
expectMsg("init")
// try to revert hotswap below the bottom of the stack
a ! RevertHotSwap
a ! "init"
expectMsg("init")
}
"be able to revert hotswap its behavior with unbecome" in {
val a = system.actorOf(new Actor {
val a = system.actorOf(Props(new Actor {
def receive = {
case "init" sender ! "init"
case "swap"
@ -73,7 +38,7 @@ class HotSwapSpec extends AkkaSpec with ImplicitSender {
context.unbecome()
})
}
})
}))
a ! "init"
expectMsg("init")
@ -89,7 +54,7 @@ class HotSwapSpec extends AkkaSpec with ImplicitSender {
"revert to initial state on restart" in {
val a = system.actorOf(new Actor {
val a = system.actorOf(Props(new Actor {
def receive = {
case "state" sender ! "0"
case "swap"
@ -100,7 +65,7 @@ class HotSwapSpec extends AkkaSpec with ImplicitSender {
})
sender ! "swapped"
}
})
}))
a ! "state"
expectMsg("0")
a ! "swap"

View file

@ -46,7 +46,7 @@ object IOActorSpec {
class SimpleEchoClient(host: String, port: Int, ioManager: ActorRef) extends Actor with IO {
lazy val socket: SocketHandle = connect(ioManager, host, port)(reader)
lazy val reader: ActorRef = context.actorOf {
lazy val reader: ActorRef = context.actorOf(Props({
new Actor with IO {
def receiveIO = {
case length: Int
@ -54,7 +54,7 @@ object IOActorSpec {
sender ! bytes
}
}
}
}))
def receiveIO = {
case bytes: ByteString
@ -186,10 +186,10 @@ class IOActorSpec extends AkkaSpec with BeforeAndAfterEach with DefaultTimeout {
"an IO Actor" must {
"run echo server" in {
val started = TestLatch(1)
val ioManager = system.actorOf(new IOManager(2)) // teeny tiny buffer
val server = system.actorOf(new SimpleEchoServer("localhost", 8064, ioManager, started))
val ioManager = system.actorOf(Props(new IOManager(2))) // teeny tiny buffer
val server = system.actorOf(Props(new SimpleEchoServer("localhost", 8064, ioManager, started)))
started.await
val client = system.actorOf(new SimpleEchoClient("localhost", 8064, ioManager))
val client = system.actorOf(Props(new SimpleEchoClient("localhost", 8064, ioManager)))
val f1 = client ? ByteString("Hello World!1")
val f2 = client ? ByteString("Hello World!2")
val f3 = client ? ByteString("Hello World!3")
@ -203,10 +203,10 @@ class IOActorSpec extends AkkaSpec with BeforeAndAfterEach with DefaultTimeout {
"run echo server under high load" in {
val started = TestLatch(1)
val ioManager = system.actorOf(new IOManager())
val server = system.actorOf(new SimpleEchoServer("localhost", 8065, ioManager, started))
val ioManager = system.actorOf(Props(new IOManager()))
val server = system.actorOf(Props(new SimpleEchoServer("localhost", 8065, ioManager, started)))
started.await
val client = system.actorOf(new SimpleEchoClient("localhost", 8065, ioManager))
val client = system.actorOf(Props(new SimpleEchoClient("localhost", 8065, ioManager)))
val list = List.range(0, 1000)
val f = Future.traverse(list)(i client ? ByteString(i.toString))
assert(f.get.size === 1000)
@ -217,10 +217,10 @@ class IOActorSpec extends AkkaSpec with BeforeAndAfterEach with DefaultTimeout {
"run echo server under high load with small buffer" in {
val started = TestLatch(1)
val ioManager = system.actorOf(new IOManager(2))
val server = system.actorOf(new SimpleEchoServer("localhost", 8066, ioManager, started))
val ioManager = system.actorOf(Props(new IOManager(2)))
val server = system.actorOf(Props(new SimpleEchoServer("localhost", 8066, ioManager, started)))
started.await
val client = system.actorOf(new SimpleEchoClient("localhost", 8066, ioManager))
val client = system.actorOf(Props(new SimpleEchoClient("localhost", 8066, ioManager)))
val list = List.range(0, 1000)
val f = Future.traverse(list)(i client ? ByteString(i.toString))
assert(f.get.size === 1000)
@ -231,11 +231,11 @@ class IOActorSpec extends AkkaSpec with BeforeAndAfterEach with DefaultTimeout {
"run key-value store" in {
val started = TestLatch(1)
val ioManager = system.actorOf(new IOManager(2)) // teeny tiny buffer
val server = system.actorOf(new KVStore("localhost", 8067, ioManager, started))
val ioManager = system.actorOf(Props(new IOManager(2))) // teeny tiny buffer
val server = system.actorOf(Props(new KVStore("localhost", 8067, ioManager, started)))
started.await
val client1 = system.actorOf(new KVClient("localhost", 8067, ioManager))
val client2 = system.actorOf(new KVClient("localhost", 8067, ioManager))
val client1 = system.actorOf(Props(new KVClient("localhost", 8067, ioManager)))
val client2 = system.actorOf(Props(new KVClient("localhost", 8067, ioManager)))
val f1 = client1 ? (('set, "hello", ByteString("World")))
val f2 = client1 ? (('set, "test", ByteString("No one will read me")))
val f3 = client1 ? (('get, "hello"))

View file

@ -42,12 +42,12 @@ class LocalActorRefProviderSpec extends AkkaSpec {
}
"only create one instance of an actor from within the same message invocation" in {
val supervisor = system.actorOf(new Actor {
val supervisor = system.actorOf(Props(new Actor {
def receive = {
case ""
val a, b = context.actorOf(Props.empty, "duplicate")
}
})
}))
EventFilter[InvalidActorNameException](occurrences = 1) intercept {
supervisor ! ""
}

View file

@ -17,53 +17,30 @@ class ReceiveTimeoutSpec extends AkkaSpec {
"get timeout" in {
val timeoutLatch = TestLatch()
val timeoutActor = system.actorOf(new Actor {
context.receiveTimeout = Some(500 milliseconds)
val timeoutActor = system.actorOf(Props(new Actor {
context.setReceiveTimeout(500 milliseconds)
protected def receive = {
case ReceiveTimeout timeoutLatch.open
}
})
}))
timeoutLatch.await
timeoutActor.stop()
}
"get timeout when swapped" in {
val timeoutLatch = TestLatch()
val timeoutActor = system.actorOf(new Actor {
context.receiveTimeout = Some(500 milliseconds)
protected def receive = {
case ReceiveTimeout timeoutLatch.open
}
})
timeoutLatch.await
val swappedLatch = TestLatch()
timeoutActor ! HotSwap(context {
case ReceiveTimeout swappedLatch.open
})
swappedLatch.await
timeoutActor.stop()
}
"reschedule timeout after regular receive" in {
val timeoutLatch = TestLatch()
case object Tick
val timeoutActor = system.actorOf(new Actor {
context.receiveTimeout = Some(500 milliseconds)
val timeoutActor = system.actorOf(Props(new Actor {
context.setReceiveTimeout(500 milliseconds)
protected def receive = {
case Tick ()
case ReceiveTimeout timeoutLatch.open
}
})
}))
timeoutActor ! Tick
@ -76,17 +53,17 @@ class ReceiveTimeoutSpec extends AkkaSpec {
val timeoutLatch = TestLatch()
case object Tick
val timeoutActor = system.actorOf(new Actor {
context.receiveTimeout = Some(500 milliseconds)
val timeoutActor = system.actorOf(Props(new Actor {
context.setReceiveTimeout(500 milliseconds)
protected def receive = {
case Tick ()
case ReceiveTimeout
count.incrementAndGet
timeoutLatch.open
context.receiveTimeout = None
context.resetReceiveTimeout()
}
})
}))
timeoutActor ! Tick
@ -98,11 +75,11 @@ class ReceiveTimeoutSpec extends AkkaSpec {
"not receive timeout message when not specified" in {
val timeoutLatch = TestLatch()
val timeoutActor = system.actorOf(new Actor {
val timeoutActor = system.actorOf(Props(new Actor {
protected def receive = {
case ReceiveTimeout timeoutLatch.open
}
})
}))
timeoutLatch.awaitTimeout(1 second) // timeout expected
timeoutActor.stop()

View file

@ -26,9 +26,9 @@ class SchedulerSpec extends AkkaSpec with BeforeAndAfterEach with DefaultTimeout
"schedule more than once" in {
case object Tick
val countDownLatch = new CountDownLatch(3)
val tickActor = system.actorOf(new Actor {
val tickActor = system.actorOf(Props(new Actor {
def receive = { case Tick countDownLatch.countDown() }
})
}))
// run every 50 milliseconds
collectCancellable(system.scheduler.schedule(0 milliseconds, 50 milliseconds, tickActor, Tick))
@ -56,9 +56,9 @@ class SchedulerSpec extends AkkaSpec with BeforeAndAfterEach with DefaultTimeout
"schedule once" in {
case object Tick
val countDownLatch = new CountDownLatch(3)
val tickActor = system.actorOf(new Actor {
val tickActor = system.actorOf(Props(new Actor {
def receive = { case Tick countDownLatch.countDown() }
})
}))
// run after 300 millisec
collectCancellable(system.scheduler.scheduleOnce(300 milliseconds, tickActor, Tick))
@ -81,9 +81,9 @@ class SchedulerSpec extends AkkaSpec with BeforeAndAfterEach with DefaultTimeout
object Ping
val ticks = new CountDownLatch(1)
val actor = system.actorOf(new Actor {
val actor = system.actorOf(Props(new Actor {
def receive = { case Ping ticks.countDown() }
})
}))
(1 to 10).foreach { i
val timeout = collectCancellable(system.scheduler.scheduleOnce(1 second, actor, Ping))
@ -131,7 +131,7 @@ class SchedulerSpec extends AkkaSpec with BeforeAndAfterEach with DefaultTimeout
case class Msg(ts: Long)
val actor = system.actorOf(new Actor {
val actor = system.actorOf(Props(new Actor {
def receive = {
case Msg(ts)
val now = System.nanoTime
@ -139,7 +139,7 @@ class SchedulerSpec extends AkkaSpec with BeforeAndAfterEach with DefaultTimeout
if (now - ts < 10000000) throw new RuntimeException("Interval is too small: " + (now - ts))
ticks.countDown()
}
})
}))
(1 to 300).foreach { i
collectCancellable(system.scheduler.scheduleOnce(10 milliseconds, actor, Msg(System.nanoTime)))
@ -154,11 +154,11 @@ class SchedulerSpec extends AkkaSpec with BeforeAndAfterEach with DefaultTimeout
case object Msg
val actor = system.actorOf(new Actor {
val actor = system.actorOf(Props(new Actor {
def receive = {
case Msg ticks.countDown()
}
})
}))
val startTime = System.nanoTime()
val cancellable = system.scheduler.schedule(1 second, 100 milliseconds, actor, Msg)

View file

@ -334,7 +334,7 @@ class TypedActorSpec extends AkkaSpec with BeforeAndAfterEach with BeforeAndAfte
mustStop(t)
}
"be able to use work-stealing dispatcher" in {
"be able to use balancing dispatcher" in {
val props = Props(
timeout = Timeout(6600),
dispatcher = system.dispatcherFactory.newBalancingDispatcher("pooled-dispatcher")

View file

@ -1,13 +1,11 @@
package akka.actor.dispatch
import java.util.concurrent.CountDownLatch
import akka.actor.Actor
import akka.actor._
import akka.testkit.AkkaSpec
/**
* Tests the behavior of the executor based event driven dispatcher when multiple actors are being dispatched on it.
*
* @author Jan Van Besien
*/
@org.junit.runner.RunWith(classOf[org.scalatest.junit.JUnitRunner])
class DispatcherActorsSpec extends AkkaSpec {
@ -33,8 +31,8 @@ class DispatcherActorsSpec extends AkkaSpec {
"not block fast actors by slow actors" in {
val sFinished = new CountDownLatch(50)
val fFinished = new CountDownLatch(10)
val s = system.actorOf(new SlowActor(sFinished))
val f = system.actorOf(new FastActor(fFinished))
val s = system.actorOf(Props(new SlowActor(sFinished)))
val f = system.actorOf(Props(new FastActor(fFinished)))
// send a lot of stuff to s
for (i 1 to 50) {

View file

@ -10,8 +10,18 @@ import akka.testkit.AkkaSpec
import scala.collection.JavaConverters._
import com.typesafe.config.ConfigFactory
object DispatchersSpec {
val config = """
myapp {
mydispatcher {
throughput = 17
}
}
"""
}
@org.junit.runner.RunWith(classOf[org.scalatest.junit.JUnitRunner])
class DispatchersSpec extends AkkaSpec {
class DispatchersSpec extends AkkaSpec(DispatchersSpec.config) {
val df = system.dispatcherFactory
import df._
@ -34,14 +44,6 @@ class DispatchersSpec extends AkkaSpec {
val defaultDispatcherConfig = settings.config.getConfig("akka.actor.default-dispatcher")
val dispatcherConf = ConfigFactory.parseString("""
myapp {
mydispatcher {
throughput = 17
}
}
""")
lazy val allDispatchers: Map[String, Option[MessageDispatcher]] = {
validTypes.map(t (t, from(ConfigFactory.parseMap(Map(tipe -> t).asJava).withFallback(defaultDispatcherConfig)))).toMap
}
@ -58,16 +60,21 @@ class DispatchersSpec extends AkkaSpec {
dispatcher.map(_.throughput) must be(Some(17))
}
"use defined properties when fromConfig" in {
val dispatcher = fromConfig("myapp.mydispatcher", cfg = dispatcherConf)
"use defined properties when newFromConfig" in {
val dispatcher = newFromConfig("myapp.mydispatcher")
dispatcher.throughput must be(17)
}
"use specific name when fromConfig" in {
val dispatcher = fromConfig("myapp.mydispatcher", cfg = dispatcherConf)
"use specific name when newFromConfig" in {
val dispatcher = newFromConfig("myapp.mydispatcher")
dispatcher.name must be("mydispatcher")
}
"use default dispatcher when not configured" in {
val dispatcher = newFromConfig("myapp.other-dispatcher")
dispatcher must be === defaultGlobalDispatcher
}
"throw IllegalArgumentException if type does not exist" in {
intercept[IllegalArgumentException] {
from(ConfigFactory.parseMap(Map(tipe -> "typedoesntexist").asJava).withFallback(defaultDispatcherConfig))
@ -81,6 +88,13 @@ class DispatchersSpec extends AkkaSpec {
assert(typesAndValidators.forall(tuple tuple._2(allDispatchers(tuple._1).get)))
}
"provide lookup of dispatchers by key" in {
val d1 = lookup("myapp.mydispatcher")
val d2 = lookup("myapp.mydispatcher")
d1 must be === d2
d1.name must be("mydispatcher")
}
}
}

View file

@ -16,13 +16,13 @@ class ListenerSpec extends AkkaSpec {
val barLatch = TestLatch(2)
val barCount = new AtomicInteger(0)
val broadcast = system.actorOf(new Actor with Listeners {
val broadcast = system.actorOf(Props(new Actor with Listeners {
def receive = listenerManagement orElse {
case "foo" gossip("bar")
}
})
}))
def newListener = system.actorOf(new Actor {
def newListener = system.actorOf(Props(new Actor {
def receive = {
case "bar"
barCount.incrementAndGet
@ -30,7 +30,7 @@ class ListenerSpec extends AkkaSpec {
case "foo"
fooLatch.countDown()
}
})
}))
val a1 = newListener
val a2 = newListener

View file

@ -6,7 +6,7 @@ import org.scalacheck._
import org.scalacheck.Arbitrary._
import org.scalacheck.Prop._
import org.scalacheck.Gen._
import akka.actor.{ Actor, ActorRef, Status }
import akka.actor._
import akka.testkit.{ EventFilter, filterEvents, filterException }
import akka.util.duration._
import org.multiverse.api.latches.StandardLatch
@ -116,7 +116,7 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa
"from an Actor" that {
"returns a result" must {
behave like futureWithResult { test
val actor = system.actorOf[TestActor]
val actor = system.actorOf(Props[TestActor])
val future = actor ? "Hello"
future.await
test(future, "World")
@ -126,7 +126,7 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa
"throws an exception" must {
behave like futureWithException[RuntimeException] { test
filterException[RuntimeException] {
val actor = system.actorOf[TestActor]
val actor = system.actorOf(Props[TestActor])
val future = actor ? "Failure"
future.await
test(future, "Expected exception; to test fault-tolerance")
@ -139,8 +139,8 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa
"using flatMap with an Actor" that {
"will return a result" must {
behave like futureWithResult { test
val actor1 = system.actorOf[TestActor]
val actor2 = system.actorOf(new Actor { def receive = { case s: String sender ! s.toUpperCase } })
val actor1 = system.actorOf(Props[TestActor])
val actor2 = system.actorOf(Props(new Actor { def receive = { case s: String sender ! s.toUpperCase } }))
val future = actor1 ? "Hello" flatMap { case s: String actor2 ? s }
future.await
test(future, "WORLD")
@ -151,8 +151,8 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa
"will throw an exception" must {
behave like futureWithException[ArithmeticException] { test
filterException[ArithmeticException] {
val actor1 = system.actorOf[TestActor]
val actor2 = system.actorOf(new Actor { def receive = { case s: String sender ! Status.Failure(new ArithmeticException("/ by zero")) } })
val actor1 = system.actorOf(Props[TestActor])
val actor2 = system.actorOf(Props(new Actor { def receive = { case s: String sender ! Status.Failure(new ArithmeticException("/ by zero")) } }))
val future = actor1 ? "Hello" flatMap { case s: String actor2 ? s }
future.await
test(future, "/ by zero")
@ -164,8 +164,8 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa
"will throw a MatchError when matching wrong type" must {
behave like futureWithException[MatchError] { test
filterException[MatchError] {
val actor1 = system.actorOf[TestActor]
val actor2 = system.actorOf(new Actor { def receive = { case s: String sender ! s.toUpperCase } })
val actor1 = system.actorOf(Props[TestActor])
val actor2 = system.actorOf(Props(new Actor { def receive = { case s: String sender ! s.toUpperCase } }))
val future = actor1 ? "Hello" flatMap { case i: Int actor2 ? i }
future.await
test(future, "World (of class java.lang.String)")
@ -180,12 +180,12 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa
"compose with for-comprehensions" in {
filterException[ClassCastException] {
val actor = system.actorOf(new Actor {
val actor = system.actorOf(Props(new Actor {
def receive = {
case s: String sender ! s.length
case i: Int sender ! (i * 2).toString
}
})
}))
val future0 = actor ? "Hello"
@ -212,12 +212,12 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa
filterException[MatchError] {
case class Req[T](req: T)
case class Res[T](res: T)
val actor = system.actorOf(new Actor {
val actor = system.actorOf(Props(new Actor {
def receive = {
case Req(s: String) sender ! Res(s.length)
case Req(i: Int) sender ! Res((i * 2).toString)
}
})
}))
val future1 = for {
Res(a: Int) actor ? Req("Hello")
@ -257,7 +257,7 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa
val future7 = future3 recover { case e: ArithmeticException "You got ERROR" }
val actor = system.actorOf[TestActor]
val actor = system.actorOf(Props[TestActor])
val future8 = actor ? "Failure"
val future9 = actor ? "Failure" recover {
@ -300,9 +300,9 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa
"fold" in {
val actors = (1 to 10).toList map { _
system.actorOf(new Actor {
system.actorOf(Props(new Actor {
def receive = { case (add: Int, wait: Int) Thread.sleep(wait); sender.tell(add) }
})
}))
}
val timeout = 10000
def futures = actors.zipWithIndex map { case (actor: ActorRef, idx: Int) actor.?((idx, idx * 200), timeout).mapTo[Int] }
@ -311,9 +311,9 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa
"fold by composing" in {
val actors = (1 to 10).toList map { _
system.actorOf(new Actor {
system.actorOf(Props(new Actor {
def receive = { case (add: Int, wait: Int) Thread.sleep(wait); sender.tell(add) }
})
}))
}
def futures = actors.zipWithIndex map { case (actor: ActorRef, idx: Int) actor.?((idx, idx * 200), 10000).mapTo[Int] }
futures.foldLeft(Future(0))((fr, fa) for (r fr; a fa) yield (r + a)).get must be(45)
@ -322,14 +322,14 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa
"fold with an exception" in {
filterException[IllegalArgumentException] {
val actors = (1 to 10).toList map { _
system.actorOf(new Actor {
system.actorOf(Props(new Actor {
def receive = {
case (add: Int, wait: Int)
Thread.sleep(wait)
if (add == 6) sender ! Status.Failure(new IllegalArgumentException("shouldFoldResultsWithException: expected"))
else sender.tell(add)
}
})
}))
}
val timeout = 10000
def futures = actors.zipWithIndex map { case (actor: ActorRef, idx: Int) actor.?((idx, idx * 100), timeout).mapTo[Int] }
@ -358,9 +358,9 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa
"shouldReduceResults" in {
val actors = (1 to 10).toList map { _
system.actorOf(new Actor {
system.actorOf(Props(new Actor {
def receive = { case (add: Int, wait: Int) Thread.sleep(wait); sender.tell(add) }
})
}))
}
val timeout = 10000
def futures = actors.zipWithIndex map { case (actor: ActorRef, idx: Int) actor.?((idx, idx * 200), timeout).mapTo[Int] }
@ -370,14 +370,14 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa
"shouldReduceResultsWithException" in {
filterException[IllegalArgumentException] {
val actors = (1 to 10).toList map { _
system.actorOf(new Actor {
system.actorOf(Props(new Actor {
def receive = {
case (add: Int, wait: Int)
Thread.sleep(wait)
if (add == 6) sender ! Status.Failure(new IllegalArgumentException("shouldFoldResultsWithException: expected"))
else sender.tell(add)
}
})
}))
}
val timeout = 10000
def futures = actors.zipWithIndex map { case (actor: ActorRef, idx: Int) actor.?((idx, idx * 100), timeout).mapTo[Int] }
@ -393,21 +393,21 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa
"receiveShouldExecuteOnComplete" in {
val latch = new StandardLatch
val actor = system.actorOf[TestActor]
val actor = system.actorOf(Props[TestActor])
actor ? "Hello" onResult { case "World" latch.open }
assert(latch.tryAwait(5, TimeUnit.SECONDS))
actor.stop()
}
"shouldTraverseFutures" in {
val oddActor = system.actorOf(new Actor {
val oddActor = system.actorOf(Props(new Actor {
var counter = 1
def receive = {
case 'GetNext
sender ! counter
counter += 2
}
})
}))
val oddFutures = List.fill(100)(oddActor ? 'GetNext mapTo manifest[Int])
assert(Future.sequence(oddFutures).get.sum === 10000)
@ -461,7 +461,7 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa
"futureComposingWithContinuations" in {
import Future.flow
val actor = system.actorOf[TestActor]
val actor = system.actorOf(Props[TestActor])
val x = Future("Hello")
val y = x flatMap (actor ? _) mapTo manifest[String]
@ -490,7 +490,7 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa
filterException[ClassCastException] {
import Future.flow
val actor = system.actorOf[TestActor]
val actor = system.actorOf(Props[TestActor])
val x = Future(3)
val y = (actor ? "Hello").mapTo[Int]
@ -505,7 +505,7 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa
filterException[ClassCastException] {
import Future.flow
val actor = system.actorOf[TestActor]
val actor = system.actorOf(Props[TestActor])
val x = Future("Hello")
val y = actor ? "Hello" mapTo manifest[Nothing]

View file

@ -13,7 +13,6 @@ import scala.collection.JavaConverters._
import java.util.Properties
import akka.actor.Actor
import akka.actor.ActorSystem
import akka.actor.HotSwap
import akka.actor.UnhandledMessageException
import akka.actor.PoisonPill
import akka.actor.ActorSystemImpl
@ -77,22 +76,27 @@ class LoggingReceiveSpec extends WordSpec with BeforeAndAfterEach with BeforeAnd
ignoreMute(this)
system.eventStream.subscribe(testActor, classOf[Logging.Debug])
system.eventStream.subscribe(testActor, classOf[Logging.Error])
val r: Actor.Receive = {
case null
}
val actor = TestActorRef(new Actor {
def receive = LoggingReceive(this) {
case x
sender ! "x"
def switch: Actor.Receive = { case "becomenull" context.become(r, false) }
def receive = switch orElse LoggingReceive(this) {
case x sender ! "x"
}
})
val name = actor.path.toString
actor ! "buh"
within(1 second) {
expectMsg(Logging.Debug(name, "received handled message buh"))
expectMsg("x")
}
val r: Actor.Receive = {
case null
}
actor ! HotSwap(_ r, false)
actor ! "becomenull"
EventFilter[UnhandledMessageException](pattern = "does not handle", occurrences = 1) intercept {
within(500 millis) {
actor ! "bah"

View file

@ -58,11 +58,11 @@ class TellLatencyPerformanceSpec extends PerformanceSpec {
val latch = new CountDownLatch(numberOfClients)
val repeatsPerClient = repeat / numberOfClients
val clients = (for (i 0 until numberOfClients) yield {
val destination = system.actorOf[Destination]
val w4 = system.actorOf(new Waypoint(destination))
val w3 = system.actorOf(new Waypoint(w4))
val w2 = system.actorOf(new Waypoint(w3))
val w1 = system.actorOf(new Waypoint(w2))
val destination = system.actorOf(Props[Destination])
val w4 = system.actorOf(Props(new Waypoint(destination)))
val w3 = system.actorOf(Props(new Waypoint(w4)))
val w2 = system.actorOf(Props(new Waypoint(w3)))
val w1 = system.actorOf(Props(new Waypoint(w2)))
Props(new Client(w1, latch, repeatsPerClient, clientDelay.toMicros.intValue, stat)).withDispatcher(clientDispatcher)
}).toList.map(system.actorOf(_))

View file

@ -82,11 +82,11 @@ class ActorPoolSpec extends AkkaSpec with DefaultTimeout {
}).withFaultHandler(faultHandler))
val successes = TestLatch(2)
val successCounter = system.actorOf(new Actor {
val successCounter = system.actorOf(Props(new Actor {
def receive = {
case "success" successes.countDown()
}
})
}))
implicit val replyTo = successCounter
pool ! "a"

View file

@ -109,12 +109,12 @@ class RoutingSpec extends AkkaSpec with DefaultTimeout with ImplicitSender {
for (i 0 until connectionCount) {
counters = counters :+ new AtomicInteger()
val actor = system.actorOf(new Actor {
val actor = system.actorOf(Props(new Actor {
def receive = {
case "end" doneLatch.countDown()
case msg: Int counters.get(i).get.addAndGet(msg)
}
})
}))
actors = actors :+ actor
}
@ -141,20 +141,20 @@ class RoutingSpec extends AkkaSpec with DefaultTimeout with ImplicitSender {
val doneLatch = new CountDownLatch(2)
val counter1 = new AtomicInteger
val actor1 = system.actorOf(new Actor {
val actor1 = system.actorOf(Props(new Actor {
def receive = {
case "end" doneLatch.countDown()
case msg: Int counter1.addAndGet(msg)
}
})
}))
val counter2 = new AtomicInteger
val actor2 = system.actorOf(new Actor {
val actor2 = system.actorOf(Props(new Actor {
def receive = {
case "end" doneLatch.countDown()
case msg: Int counter2.addAndGet(msg)
}
})
}))
val routedActor = system.actorOf(Props(new TestActor).withRouter(RoundRobinRouter(targets = List(actor1, actor2))))
@ -179,20 +179,20 @@ class RoutingSpec extends AkkaSpec with DefaultTimeout with ImplicitSender {
val doneLatch = new CountDownLatch(2)
val counter1 = new AtomicInteger
val actor1 = system.actorOf(new Actor {
val actor1 = system.actorOf(Props(new Actor {
def receive = {
case "end" doneLatch.countDown()
case msg: Int counter1.addAndGet(msg)
}
})
}))
val counter2 = new AtomicInteger
val actor2 = system.actorOf(new Actor {
val actor2 = system.actorOf(Props(new Actor {
def receive = {
case "end" doneLatch.countDown()
case msg: Int counter2.addAndGet(msg)
}
})
}))
val routedActor = system.actorOf(Props(new TestActor).withRouter(RandomRouter(targets = List(actor1, actor2))))
@ -216,20 +216,20 @@ class RoutingSpec extends AkkaSpec with DefaultTimeout with ImplicitSender {
val doneLatch = new CountDownLatch(2)
val counter1 = new AtomicInteger
val actor1 = system.actorOf(new Actor {
val actor1 = system.actorOf(Props(new Actor {
def receive = {
case "end" doneLatch.countDown()
case msg: Int counter1.addAndGet(msg)
}
})
}))
val counter2 = new AtomicInteger
val actor2 = system.actorOf(new Actor {
val actor2 = system.actorOf(Props(new Actor {
def receive = {
case "end" doneLatch.countDown()
case msg: Int counter2.addAndGet(msg)
}
})
}))
val routedActor = system.actorOf(Props(new TestActor).withRouter(BroadcastRouter(targets = List(actor1, actor2))))
routedActor ! 1
@ -245,22 +245,22 @@ class RoutingSpec extends AkkaSpec with DefaultTimeout with ImplicitSender {
val doneLatch = new CountDownLatch(2)
val counter1 = new AtomicInteger
val actor1 = system.actorOf(new Actor {
val actor1 = system.actorOf(Props(new Actor {
def receive = {
case "end" doneLatch.countDown()
case msg: Int
counter1.addAndGet(msg)
sender ! "ack"
}
})
}))
val counter2 = new AtomicInteger
val actor2 = system.actorOf(new Actor {
val actor2 = system.actorOf(Props(new Actor {
def receive = {
case "end" doneLatch.countDown()
case msg: Int counter2.addAndGet(msg)
}
})
}))
val routedActor = system.actorOf(Props(new TestActor).withRouter(BroadcastRouter(targets = List(actor1, actor2))))
routedActor ? 1
@ -284,20 +284,20 @@ class RoutingSpec extends AkkaSpec with DefaultTimeout with ImplicitSender {
val doneLatch = new TestLatch(2)
val counter1 = new AtomicInteger
val actor1 = system.actorOf(new Actor {
val actor1 = system.actorOf(Props(new Actor {
def receive = {
case "end" doneLatch.countDown()
case msg: Int counter1.addAndGet(msg)
}
})
}))
val counter2 = new AtomicInteger
val actor2 = system.actorOf(new Actor {
val actor2 = system.actorOf(Props(new Actor {
def receive = {
case "end" doneLatch.countDown()
case msg: Int counter2.addAndGet(msg)
}
})
}))
val routedActor = system.actorOf(Props(new TestActor).withRouter(ScatterGatherFirstCompletedRouter(targets = List(actor1, actor2))))
routedActor ! Broadcast(1)

View file

@ -7,10 +7,9 @@ package akka.serialization
import akka.serialization.Serialization._
import scala.reflect._
import akka.testkit.AkkaSpec
import akka.actor.{ ActorSystem, ActorSystemImpl }
import java.io.{ ObjectInputStream, ByteArrayInputStream, ByteArrayOutputStream, ObjectOutputStream }
import akka.actor.DeadLetterActorRef
import com.typesafe.config.ConfigFactory
import akka.actor._
import java.io._
object SerializeSpec {
@ -94,6 +93,22 @@ class SerializeSpec extends AkkaSpec(SerializeSpec.serializationConf) {
}
}
"not serialize ActorCell" in {
val a = system.actorOf(Props(new Actor {
def receive = {
case o: ObjectOutputStream
try {
o.writeObject(this)
} catch {
case _: NotSerializableException testActor ! "pass"
}
}
}))
a ! new ObjectOutputStream(new ByteArrayOutputStream())
expectMsg("pass")
a.stop()
}
"serialize DeadLetterActorRef" in {
val outbuf = new ByteArrayOutputStream()
val out = new ObjectOutputStream(outbuf)

View file

@ -40,6 +40,16 @@ class DurationSpec extends WordSpec with MustMatchers {
(minf + minf) must be(minf)
}
"support fromNow" in {
val dead = 2.seconds.fromNow
val dead2 = 2 seconds fromNow
dead.timeLeft must be > 1.second
dead2.timeLeft must be > 1.second
1.second.sleep
dead.timeLeft must be < 1.second
dead2.timeLeft must be < 1.second
}
}
}

View file

@ -4,6 +4,8 @@
package com.typesafe.config;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* An immutable map from config paths to config values.
@ -32,6 +34,10 @@ import java.util.List;
* {@code ConfigObject} is a tree of nested maps from <em>keys</em> to values.
*
* <p>
* Use {@link ConfigUtil#joinPath} and {@link ConfigUtil#splitPath} to convert
* between path expressions and individual path elements (keys).
*
* <p>
* Another difference between {@code Config} and {@code ConfigObject} is that
* conceptually, {@code ConfigValue}s with a {@link ConfigValue#valueType()
* valueType()} of {@link ConfigValueType#NULL NULL} exist in a
@ -54,10 +60,11 @@ import java.util.List;
* are performed for you though.
*
* <p>
* If you want to iterate over the contents of a {@code Config}, you have to get
* its {@code ConfigObject} with {@link #root()}, and then iterate over the
* {@code ConfigObject}.
*
* If you want to iterate over the contents of a {@code Config}, you can get its
* {@code ConfigObject} with {@link #root()}, and then iterate over the
* {@code ConfigObject} (which implements <code>java.util.Map</code>). Or, you
* can use {@link #entrySet()} which recurses the object tree for you and builds
* up a <code>Set</code> of all path-value pairs where the value is not null.
*
* <p>
* <em>Do not implement {@code Config}</em>; it should only be implemented by
@ -256,6 +263,17 @@ public interface Config extends ConfigMergeable {
*/
boolean isEmpty();
/**
* Returns the set of path-value pairs, excluding any null values, found by
* recursing {@link #root() the root object}. Note that this is very
* different from <code>root().entrySet()</code> which returns the set of
* immediate-child keys in the root object and includes null values.
*
* @return set of paths with non-null values, built up by recursing the
* entire tree of {@link ConfigObject}
*/
Set<Map.Entry<String, ConfigValue>> entrySet();
/**
*
* @param path

View file

@ -11,7 +11,7 @@ import java.util.Map;
import java.util.Properties;
import com.typesafe.config.impl.ConfigImpl;
import com.typesafe.config.impl.ConfigUtil;
import com.typesafe.config.impl.ConfigImplUtil;
import com.typesafe.config.impl.Parseable;
/**
@ -179,7 +179,7 @@ public final class ConfigFactory {
try {
return DefaultConfigHolder.defaultConfig;
} catch (ExceptionInInitializerError e) {
throw ConfigUtil.extractInitializerError(e);
throw ConfigImplUtil.extractInitializerError(e);
}
}

View file

@ -37,6 +37,10 @@ import java.util.Map;
* {@code ConfigObject} is a one-level map from paths to values.
*
* <p>
* Use {@link ConfigUtil#joinPath} and {@link ConfigUtil#splitPath} to convert
* between path expressions and individual path elements (keys).
*
* <p>
* A {@code ConfigObject} may contain null values, which will have
* {@link ConfigValue#valueType()} equal to {@link ConfigValueType#NULL}. If
* {@code get()} returns Java's null then the key was not present in the parsed

View file

@ -0,0 +1,70 @@
package com.typesafe.config;
import java.util.List;
import com.typesafe.config.impl.ConfigImplUtil;
public final class ConfigUtil {
private ConfigUtil() {
}
/**
* Quotes and escapes a string, as in the JSON specification.
*
* @param s
* a string
* @return the string quoted and escaped
*/
public static String quoteString(String s) {
return ConfigImplUtil.renderJsonString(s);
}
/**
* Converts a list of keys to a path expression, by quoting the path
* elements as needed and then joining them separated by a period. A path
* expression is usable with a {@link Config}, while individual path
* elements are usable with a {@link ConfigObject}.
*
* @param elements
* the keys in the path
* @return a path expression
* @throws ConfigException
* if there are no elements
*/
public static String joinPath(String... elements) {
return ConfigImplUtil.joinPath(elements);
}
/**
* Converts a list of strings to a path expression, by quoting the path
* elements as needed and then joining them separated by a period. A path
* expression is usable with a {@link Config}, while individual path
* elements are usable with a {@link ConfigObject}.
*
* @param elements
* the keys in the path
* @return a path expression
* @throws ConfigException
* if the list is empty
*/
public static String joinPath(List<String> elements) {
return ConfigImplUtil.joinPath(elements);
}
/**
* Converts a path expression into a list of keys, by splitting on period
* and unquoting the individual path elements. A path expression is usable
* with a {@link Config}, while individual path elements are usable with a
* {@link ConfigObject}.
*
* @param path
* a path expression
* @return the individual keys in the path
* @throws ConfigException
* if the path expression is invalid
*/
public static List<String> splitPath(String path) {
return ConfigImplUtil.splitPath(path);
}
}

View file

@ -144,7 +144,7 @@ abstract class AbstractConfigValue implements ConfigValue, MergeableValue {
return canEqual(other)
&& (this.valueType() ==
((ConfigValue) other).valueType())
&& ConfigUtil.equalsHandlingNull(this.unwrapped(),
&& ConfigImplUtil.equalsHandlingNull(this.unwrapped(),
((ConfigValue) other).unwrapped());
} else {
return false;
@ -178,7 +178,7 @@ abstract class AbstractConfigValue implements ConfigValue, MergeableValue {
protected void render(StringBuilder sb, int indent, String atKey, boolean formatted) {
if (atKey != null) {
sb.append(ConfigUtil.renderJsonString(atKey));
sb.append(ConfigImplUtil.renderJsonString(atKey));
sb.append(" : ");
}
render(sb, indent, formatted);

View file

@ -189,7 +189,7 @@ final class ConfigDelayedMerge extends AbstractConfigValue implements
indent(sb, indent);
if (atKey != null) {
sb.append("# unmerged value " + i + " for key "
+ ConfigUtil.renderJsonString(atKey) + " from ");
+ ConfigImplUtil.renderJsonString(atKey) + " from ");
} else {
sb.append("# unmerged value " + i + " from ");
}
@ -200,7 +200,7 @@ final class ConfigDelayedMerge extends AbstractConfigValue implements
}
if (atKey != null) {
sb.append(ConfigUtil.renderJsonString(atKey));
sb.append(ConfigImplUtil.renderJsonString(atKey));
sb.append(" : ");
}
v.render(sb, indent, formatted);

View file

@ -40,47 +40,66 @@ public class ConfigImpl {
|| name.endsWith(".properties")) {
ConfigParseable p = source.nameToParseable(name);
if (p != null) {
obj = p.parse(p.options().setAllowMissing(
options.getAllowMissing()));
} else {
obj = SimpleConfigObject.emptyMissing(SimpleConfigOrigin.newSimple(name));
}
obj = p.parse(p.options().setAllowMissing(options.getAllowMissing()));
} else {
ConfigParseable confHandle = source.nameToParseable(name + ".conf");
ConfigParseable jsonHandle = source.nameToParseable(name + ".json");
ConfigParseable propsHandle = source.nameToParseable(name
+ ".properties");
if (!options.getAllowMissing() && confHandle == null
&& jsonHandle == null && propsHandle == null) {
throw new ConfigException.IO(SimpleConfigOrigin.newSimple(name),
"No config files {.conf,.json,.properties} found");
}
boolean gotSomething = false;
List<String> failMessages = new ArrayList<String>();
ConfigSyntax syntax = options.getSyntax();
obj = SimpleConfigObject.empty(SimpleConfigOrigin.newSimple(name));
if (confHandle != null
&& (syntax == null || syntax == ConfigSyntax.CONF)) {
obj = confHandle.parse(confHandle.options()
.setAllowMissing(true).setSyntax(ConfigSyntax.CONF));
if (syntax == null || syntax == ConfigSyntax.CONF) {
try {
obj = confHandle.parse(confHandle.options().setAllowMissing(false)
.setSyntax(ConfigSyntax.CONF));
gotSomething = true;
} catch (ConfigException.IO e) {
failMessages.add(e.getMessage());
}
}
if (jsonHandle != null
&& (syntax == null || syntax == ConfigSyntax.JSON)) {
ConfigObject parsed = jsonHandle.parse(jsonHandle
.options().setAllowMissing(true)
.setSyntax(ConfigSyntax.JSON));
if (syntax == null || syntax == ConfigSyntax.JSON) {
try {
ConfigObject parsed = jsonHandle.parse(jsonHandle.options()
.setAllowMissing(false).setSyntax(ConfigSyntax.JSON));
obj = obj.withFallback(parsed);
gotSomething = true;
} catch (ConfigException.IO e) {
failMessages.add(e.getMessage());
}
}
if (propsHandle != null
&& (syntax == null || syntax == ConfigSyntax.PROPERTIES)) {
if (syntax == null || syntax == ConfigSyntax.PROPERTIES) {
try {
ConfigObject parsed = propsHandle.parse(propsHandle.options()
.setAllowMissing(true)
.setSyntax(ConfigSyntax.PROPERTIES));
.setAllowMissing(false).setSyntax(ConfigSyntax.PROPERTIES));
obj = obj.withFallback(parsed);
gotSomething = true;
} catch (ConfigException.IO e) {
failMessages.add(e.getMessage());
}
}
if (!options.getAllowMissing() && !gotSomething) {
String failMessage;
if (failMessages.isEmpty()) {
// this should not happen
throw new ConfigException.BugOrBroken(
"should not be reached: nothing found but no exceptions thrown");
} else {
StringBuilder sb = new StringBuilder();
for (String msg : failMessages) {
sb.append(msg);
sb.append(", ");
}
sb.setLength(sb.length() - 2);
failMessage = sb.toString();
}
throw new ConfigException.IO(SimpleConfigOrigin.newSimple(name), failMessage);
}
}
@ -269,7 +288,14 @@ public class ConfigImpl {
NameSource source = new NameSource() {
@Override
public ConfigParseable nameToParseable(String name) {
return context.relativeTo(name);
ConfigParseable p = context.relativeTo(name);
if (p == null) {
// avoid returning null
return Parseable.newNotFound(name, "include was not found: '" + name + "'",
ConfigParseOptions.defaults());
} else {
return p;
}
}
};
@ -308,7 +334,7 @@ public class ConfigImpl {
try {
return DefaultIncluderHolder.defaultIncluder;
} catch (ExceptionInInitializerError e) {
throw ConfigUtil.extractInitializerError(e);
throw ConfigImplUtil.extractInitializerError(e);
}
}
@ -326,7 +352,7 @@ public class ConfigImpl {
try {
return SystemPropertiesHolder.systemProperties;
} catch (ExceptionInInitializerError e) {
throw ConfigUtil.extractInitializerError(e);
throw ConfigImplUtil.extractInitializerError(e);
}
}
@ -362,7 +388,7 @@ public class ConfigImpl {
try {
return EnvVariablesHolder.envVariables;
} catch (ExceptionInInitializerError e) {
throw ConfigUtil.extractInitializerError(e);
throw ConfigImplUtil.extractInitializerError(e);
}
}
@ -384,7 +410,7 @@ public class ConfigImpl {
try {
return ReferenceHolder.referenceConfig;
} catch (ExceptionInInitializerError e) {
throw ConfigUtil.extractInitializerError(e);
throw ConfigImplUtil.extractInitializerError(e);
}
}
}

View file

@ -6,12 +6,14 @@ package com.typesafe.config.impl;
import java.io.File;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import com.typesafe.config.ConfigException;
/** This is public just for the "config" package to use, don't touch it */
final public class ConfigUtil {
final public class ConfigImplUtil {
static boolean equalsHandlingNull(Object a, Object b) {
if (a == null && b != null)
return false;
@ -23,7 +25,11 @@ final public class ConfigUtil {
return a.equals(b);
}
static String renderJsonString(String s) {
/**
* This is public ONLY for use by the "config" package, DO NOT USE this ABI
* may change.
*/
public static String renderJsonString(String s) {
StringBuilder sb = new StringBuilder();
sb.append('"');
for (int i = 0; i < s.length(); ++i) {
@ -146,4 +152,34 @@ final public class ConfigUtil {
return new File(url.getPath());
}
}
/**
* This is public ONLY for use by the "config" package, DO NOT USE this ABI
* may change. You can use the version in ConfigUtil instead.
*/
public static String joinPath(String... elements) {
return (new Path(elements)).render();
}
/**
* This is public ONLY for use by the "config" package, DO NOT USE this ABI
* may change. You can use the version in ConfigUtil instead.
*/
public static String joinPath(List<String> elements) {
return joinPath(elements.toArray(new String[0]));
}
/**
* This is public ONLY for use by the "config" package, DO NOT USE this ABI
* may change. You can use the version in ConfigUtil instead.
*/
public static List<String> splitPath(String path) {
Path p = Path.newPath(path);
List<String> elements = new ArrayList<String>();
while (p != null) {
elements.add(p.first());
p = p.remainder();
}
return elements;
}
}

View file

@ -32,6 +32,6 @@ final class ConfigString extends AbstractConfigValue {
@Override
protected void render(StringBuilder sb, int indent, boolean formatted) {
sb.append(ConfigUtil.renderJsonString(value));
sb.append(ConfigImplUtil.renderJsonString(value));
}
}

View file

@ -266,7 +266,7 @@ final class ConfigSubstitution extends AbstractConfigValue implements
if (p instanceof SubstitutionExpression) {
sb.append(p.toString());
} else {
sb.append(ConfigUtil.renderJsonString((String) p));
sb.append(ConfigImplUtil.renderJsonString((String) p));
}
}
}

View file

@ -6,6 +6,7 @@ package com.typesafe.config.impl;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FilterReader;
import java.io.IOException;
import java.io.InputStream;
@ -261,6 +262,34 @@ public abstract class Parseable implements ConfigParseable {
return new File(parent, filename);
}
// this is a parseable that doesn't exist and just throws when you try to
// parse it
private final static class ParseableNotFound extends Parseable {
final private String what;
final private String message;
ParseableNotFound(String what, String message, ConfigParseOptions options) {
this.what = what;
this.message = message;
postConstruct(options);
}
@Override
protected Reader reader() throws IOException {
throw new FileNotFoundException(message);
}
@Override
protected ConfigOrigin createOrigin() {
return SimpleConfigOrigin.newSimple(what);
}
}
public static Parseable newNotFound(String whatNotFound, String message,
ConfigParseOptions options) {
return new ParseableNotFound(whatNotFound, message, options);
}
private final static class ParseableReader extends Parseable {
final private Reader reader;
@ -355,7 +384,7 @@ public abstract class Parseable implements ConfigParseable {
// we want file: URLs and files to always behave the same, so switch
// to a file if it's a file: URL
if (input.getProtocol().equals("file")) {
return newFile(ConfigUtil.urlToFile(input), options);
return newFile(ConfigImplUtil.urlToFile(input), options);
} else {
return new ParseableURL(input, options);
}

View file

@ -41,6 +41,10 @@ final class Parser {
final private ConfigSyntax flavor;
final private ConfigOrigin baseOrigin;
final private LinkedList<Path> pathStack;
// this is the number of "equals" we are inside,
// used to modify the error message to reflect that
// someone may think this is .properties format.
int equalsCount;
ParseContext(ConfigSyntax flavor, ConfigOrigin origin,
Iterator<Token> tokens, ConfigIncluder includer,
@ -53,6 +57,7 @@ final class Parser {
this.includer = includer;
this.includeContext = includeContext;
this.pathStack = new LinkedList<Path>();
this.equalsCount = 0;
}
private Token nextToken() {
@ -63,12 +68,25 @@ final class Parser {
t = buffer.pop();
}
if (Tokens.isProblem(t)) {
ConfigOrigin origin = t.origin();
String message = Tokens.getProblemMessage(t);
Throwable cause = Tokens.getProblemCause(t);
boolean suggestQuotes = Tokens.getProblemSuggestQuotes(t);
if (suggestQuotes) {
message = addQuoteSuggestion(t.toString(), message);
} else {
message = addKeyName(message);
}
throw new ConfigException.Parse(origin, message, cause);
}
if (flavor == ConfigSyntax.JSON) {
if (Tokens.isUnquotedText(t)) {
throw parseError("Token not allowed in valid JSON: '"
+ Tokens.getUnquotedText(t) + "'");
throw parseError(addKeyName("Token not allowed in valid JSON: '"
+ Tokens.getUnquotedText(t) + "'"));
} else if (Tokens.isSubstitution(t)) {
throw parseError("Substitutions (${} syntax) not allowed in JSON");
throw parseError(addKeyName("Substitutions (${} syntax) not allowed in JSON"));
}
}
@ -84,7 +102,7 @@ final class Parser {
while (Tokens.isNewline(t)) {
// line number tokens have the line that was _ended_ by the
// newline, so we have to add one.
lineNumber = Tokens.getLineNumber(t) + 1;
lineNumber = t.lineNumber() + 1;
t = nextToken();
}
return t;
@ -111,7 +129,7 @@ final class Parser {
while (true) {
if (Tokens.isNewline(t)) {
// newline number is the line just ended, so add one
lineNumber = Tokens.getLineNumber(t) + 1;
lineNumber = t.lineNumber() + 1;
sawSeparatorOrNewline = true;
// we want to continue to also eat
// a comma if there is one.
@ -172,11 +190,11 @@ final class Parser {
} else if (Tokens.isUnquotedText(valueToken)) {
String text = Tokens.getUnquotedText(valueToken);
if (firstOrigin == null)
firstOrigin = Tokens.getUnquotedTextOrigin(valueToken);
firstOrigin = valueToken.origin();
sb.append(text);
} else if (Tokens.isSubstitution(valueToken)) {
if (firstOrigin == null)
firstOrigin = Tokens.getSubstitutionOrigin(valueToken);
firstOrigin = valueToken.origin();
if (sb.length() > 0) {
// save string so far
@ -186,8 +204,7 @@ final class Parser {
// now save substitution
List<Token> expression = Tokens
.getSubstitutionPathExpression(valueToken);
Path path = parsePathExpression(expression.iterator(),
Tokens.getSubstitutionOrigin(valueToken));
Path path = parsePathExpression(expression.iterator(), valueToken.origin());
boolean optional = Tokens.getSubstitutionOptional(valueToken);
minimized.add(new SubstitutionExpression(path, optional));
@ -233,6 +250,65 @@ final class Parser {
return new ConfigException.Parse(lineOrigin(), message, cause);
}
private String previousFieldName(Path lastPath) {
if (lastPath != null) {
return lastPath.render();
} else if (pathStack.isEmpty())
return null;
else
return pathStack.peek().render();
}
private String previousFieldName() {
return previousFieldName(null);
}
private String addKeyName(String message) {
String previousFieldName = previousFieldName();
if (previousFieldName != null) {
return "in value for key '" + previousFieldName + "': " + message;
} else {
return message;
}
}
private String addQuoteSuggestion(String badToken, String message) {
return addQuoteSuggestion(null, equalsCount > 0, badToken, message);
}
private String addQuoteSuggestion(Path lastPath, boolean insideEquals, String badToken,
String message) {
String previousFieldName = previousFieldName(lastPath);
String part;
if (badToken.equals(Tokens.END.toString())) {
// EOF requires special handling for the error to make sense.
if (previousFieldName != null)
part = message + " (if you intended '" + previousFieldName
+ "' to be part of a value, instead of a key, "
+ "try adding double quotes around the whole value";
else
return message;
} else {
if (previousFieldName != null) {
part = message + " (if you intended " + badToken
+ " to be part of the value for '" + previousFieldName + "', "
+ "try enclosing the value in double quotes";
} else {
part = message + " (if you intended " + badToken
+ " to be part of a key or string value, "
+ "try enclosing the key or value in double quotes";
}
}
if (insideEquals)
return part
+ ", or you may be able to rename the file .properties rather than .conf)";
else
return part + ")";
}
private AbstractConfigValue parseValue(Token token) {
if (Tokens.isValue(token)) {
return Tokens.getValue(token);
@ -241,8 +317,8 @@ final class Parser {
} else if (token == Tokens.OPEN_SQUARE) {
return parseArray();
} else {
throw parseError("Expecting a value but got wrong token: "
+ token);
throw parseError(addQuoteSuggestion(token.toString(),
"Expecting a value but got wrong token: " + token));
}
}
@ -283,8 +359,8 @@ final class Parser {
String key = (String) Tokens.getValue(token).unwrapped();
return Path.newKey(key);
} else {
throw parseError("Expecting close brace } or a field name, got "
+ token);
throw parseError(addKeyName("Expecting close brace } or a field name here, got "
+ token));
}
} else {
List<Token> expression = new ArrayList<Token>();
@ -293,6 +369,12 @@ final class Parser {
expression.add(t);
t = nextToken(); // note: don't cross a newline
}
if (expression.isEmpty()) {
throw parseError(addKeyName("expecting a close brace or a field name here, got "
+ t));
}
putBack(t); // put back the token we ended with
return parsePathExpression(expression.iterator(), lineOrigin());
}
@ -311,7 +393,7 @@ final class Parser {
for (int i = 0; i < s.length(); ++i) {
char c = s.charAt(i);
if (!ConfigUtil.isWhitespace(c))
if (!ConfigImplUtil.isWhitespace(c))
return false;
}
return true;
@ -362,13 +444,18 @@ final class Parser {
Map<String, AbstractConfigValue> values = new HashMap<String, AbstractConfigValue>();
ConfigOrigin objectOrigin = lineOrigin();
boolean afterComma = false;
Path lastPath = null;
boolean lastInsideEquals = false;
while (true) {
Token t = nextTokenIgnoringNewline();
if (t == Tokens.CLOSE_CURLY) {
if (flavor == ConfigSyntax.JSON && afterComma) {
throw parseError("expecting a field name after comma, got a close brace }");
throw parseError(addQuoteSuggestion(t.toString(),
"expecting a field name after a comma, got a close brace } instead"));
} else if (!hadOpenCurly) {
throw parseError("unbalanced close brace '}' with no open brace");
throw parseError(addQuoteSuggestion(t.toString(),
"unbalanced close brace '}' with no open brace"));
}
break;
} else if (t == Tokens.END && !hadOpenCurly) {
@ -381,6 +468,7 @@ final class Parser {
} else {
Path path = parseKey(t);
Token afterKey = nextTokenIgnoringNewline();
boolean insideEquals = false;
// path must be on-stack while we parse the value
pathStack.push(path);
@ -394,8 +482,14 @@ final class Parser {
newValue = parseObject(true);
} else {
if (!isKeyValueSeparatorToken(afterKey)) {
throw parseError("Key may not be followed by token: "
+ afterKey);
throw parseError(addQuoteSuggestion(afterKey.toString(),
"Key '" + path.render() + "' may not be followed by token: "
+ afterKey));
}
if (afterKey == Tokens.EQUALS) {
insideEquals = true;
equalsCount += 1;
}
consolidateValueTokens();
@ -403,7 +497,11 @@ final class Parser {
newValue = parseValue(valueToken);
}
pathStack.pop();
lastPath = pathStack.pop();
if (insideEquals) {
equalsCount -= 1;
}
lastInsideEquals = insideEquals;
String key = path.first();
Path remaining = path.remainder();
@ -451,25 +549,25 @@ final class Parser {
t = nextTokenIgnoringNewline();
if (t == Tokens.CLOSE_CURLY) {
if (!hadOpenCurly) {
throw parseError("unbalanced close brace '}' with no open brace");
throw parseError(addQuoteSuggestion(lastPath, lastInsideEquals,
t.toString(), "unbalanced close brace '}' with no open brace"));
}
break;
} else if (hadOpenCurly) {
throw parseError("Expecting close brace } or a comma, got "
+ t);
throw parseError(addQuoteSuggestion(lastPath, lastInsideEquals,
t.toString(), "Expecting close brace } or a comma, got " + t));
} else {
if (t == Tokens.END) {
putBack(t);
break;
} else {
throw parseError("Expecting end of input or a comma, got "
+ t);
throw parseError(addQuoteSuggestion(lastPath, lastInsideEquals,
t.toString(), "Expecting end of input or a comma, got " + t));
}
}
}
}
return new SimpleConfigObject(objectOrigin,
values);
return new SimpleConfigObject(objectOrigin, values);
}
private SimpleConfigList parseArray() {
@ -492,8 +590,11 @@ final class Parser {
} else if (t == Tokens.OPEN_SQUARE) {
values.add(parseArray());
} else {
throw parseError("List should have ] or a first element after the open [, instead had token: "
+ t);
throw parseError(addKeyName("List should have ] or a first element after the open [, instead had token: "
+ t
+ " (if you want "
+ t
+ " to be part of a string value, then double-quote it)"));
}
// now remaining elements
@ -506,8 +607,11 @@ final class Parser {
if (t == Tokens.CLOSE_SQUARE) {
return new SimpleConfigList(arrayOrigin, values);
} else {
throw parseError("List should have ended with ] or had a comma, instead had token: "
+ t);
throw parseError(addKeyName("List should have ended with ] or had a comma, instead had token: "
+ t
+ " (if you want "
+ t
+ " to be part of a string value, then double-quote it)"));
}
}
@ -526,8 +630,11 @@ final class Parser {
// we allow one trailing comma
putBack(t);
} else {
throw parseError("List should have had new element after a comma, instead had token: "
+ t);
throw parseError(addKeyName("List should have had new element after a comma, instead had token: "
+ t
+ " (if you want the comma or "
+ t
+ " to be part of a string value, then double-quote it)"));
}
}
}
@ -659,9 +766,12 @@ final class Parser {
} else if (Tokens.isUnquotedText(t)) {
text = Tokens.getUnquotedText(t);
} else {
throw new ConfigException.BadPath(origin, originalText,
throw new ConfigException.BadPath(
origin,
originalText,
"Token not allowed in path expression: "
+ t);
+ t
+ " (you can double-quote this token if you really want it here)");
}
addPathText(buf, false, text);
@ -728,7 +838,7 @@ final class Parser {
// do something much faster than the full parser if
// we just have something like "foo" or "foo.bar"
private static Path speculativeFastParsePath(String path) {
String s = ConfigUtil.unicodeTrim(path);
String s = ConfigImplUtil.unicodeTrim(path);
if (s.isEmpty())
return null;
if (hasUnsafeChars(s))

View file

@ -125,7 +125,7 @@ final class Path {
if (other instanceof Path) {
Path that = (Path) other;
return this.first.equals(that.first)
&& ConfigUtil.equalsHandlingNull(this.remainder,
&& ConfigImplUtil.equalsHandlingNull(this.remainder,
that.remainder);
} else {
return false;
@ -167,7 +167,7 @@ final class Path {
private void appendToStringBuilder(StringBuilder sb) {
if (hasFunkyChars(first) || first.isEmpty())
sb.append(ConfigUtil.renderJsonString(first));
sb.append(ConfigImplUtil.renderJsonString(first));
else
sb.append(first);
if (remainder != null) {

View file

@ -3,10 +3,13 @@
*/
package com.typesafe.config.impl;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import com.typesafe.config.Config;
@ -20,12 +23,10 @@ import com.typesafe.config.ConfigValue;
import com.typesafe.config.ConfigValueType;
/**
* One thing to keep in mind in the future: if any Collection-like APIs are
* added here, including iterators or size() or anything, then we'd have to
* grapple with whether ConfigNull values are "in" the Config (probably not) and
* we'd probably want to make the collection look flat - not like a tree. So the
* key-value pairs would be all the tree's leaf values, in a big flat list with
* their full paths.
* One thing to keep in mind in the future: as Collection-like APIs are added
* here, including iterators or size() or anything, they should be consistent
* with a one-level java.util.Map from paths to non-null values. Null values are
* not "in" the map.
*/
final class SimpleConfig implements Config, MergeableValue {
@ -73,6 +74,31 @@ final class SimpleConfig implements Config, MergeableValue {
return object.isEmpty();
}
private static void findPaths(Set<Map.Entry<String, ConfigValue>> entries, Path parent,
AbstractConfigObject obj) {
for (Map.Entry<String, ConfigValue> entry : obj.entrySet()) {
String elem = entry.getKey();
ConfigValue v = entry.getValue();
Path path = Path.newKey(elem);
if (parent != null)
path = path.prepend(parent);
if (v instanceof AbstractConfigObject) {
findPaths(entries, path, (AbstractConfigObject) v);
} else if (v instanceof ConfigNull) {
// nothing; nulls are conceptually not in a Config
} else {
entries.add(new AbstractMap.SimpleImmutableEntry<String, ConfigValue>(path.render(), v));
}
}
}
@Override
public Set<Map.Entry<String, ConfigValue>> entrySet() {
Set<Map.Entry<String, ConfigValue>> entries = new HashSet<Map.Entry<String, ConfigValue>>();
findPaths(entries, null, object);
return entries;
}
static private AbstractConfigValue find(AbstractConfigObject self,
String pathExpression, ConfigValueType expected, String originalPath) {
Path path = Path.newPath(pathExpression);
@ -440,10 +466,10 @@ final class SimpleConfig implements Config, MergeableValue {
*/
public static long parseDuration(String input,
ConfigOrigin originForException, String pathForException) {
String s = ConfigUtil.unicodeTrim(input);
String s = ConfigImplUtil.unicodeTrim(input);
String originalUnitString = getUnits(s);
String unitString = originalUnitString;
String numberString = ConfigUtil.unicodeTrim(s.substring(0, s.length()
String numberString = ConfigImplUtil.unicodeTrim(s.substring(0, s.length()
- unitString.length()));
TimeUnit units = null;
@ -592,9 +618,9 @@ final class SimpleConfig implements Config, MergeableValue {
*/
public static long parseBytes(String input, ConfigOrigin originForException,
String pathForException) {
String s = ConfigUtil.unicodeTrim(input);
String s = ConfigImplUtil.unicodeTrim(input);
String unitString = getUnits(s);
String numberString = ConfigUtil.unicodeTrim(s.substring(0,
String numberString = ConfigImplUtil.unicodeTrim(s.substring(0,
s.length() - unitString.length()));
// this would be caught later anyway, but the error message

View file

@ -97,7 +97,7 @@ final class SimpleConfigOrigin implements ConfigOrigin {
&& this.lineNumber == otherOrigin.lineNumber
&& this.endLineNumber == otherOrigin.endLineNumber
&& this.originType == otherOrigin.originType
&& ConfigUtil.equalsHandlingNull(this.urlOrNull, otherOrigin.urlOrNull);
&& ConfigImplUtil.equalsHandlingNull(this.urlOrNull, otherOrigin.urlOrNull);
} else {
return false;
}
@ -227,7 +227,7 @@ final class SimpleConfigOrigin implements ConfigOrigin {
}
String mergedURL;
if (ConfigUtil.equalsHandlingNull(a.urlOrNull, b.urlOrNull)) {
if (ConfigImplUtil.equalsHandlingNull(a.urlOrNull, b.urlOrNull)) {
mergedURL = a.urlOrNull;
} else {
mergedURL = null;
@ -252,7 +252,7 @@ final class SimpleConfigOrigin implements ConfigOrigin {
count += 1;
if (a.endLineNumber == b.endLineNumber)
count += 1;
if (ConfigUtil.equalsHandlingNull(a.urlOrNull, b.urlOrNull))
if (ConfigImplUtil.equalsHandlingNull(a.urlOrNull, b.urlOrNull))
count += 1;
}

View file

@ -3,19 +3,56 @@
*/
package com.typesafe.config.impl;
import com.typesafe.config.ConfigException;
import com.typesafe.config.ConfigOrigin;
class Token {
final private TokenType tokenType;
final private String debugString;
final private ConfigOrigin origin;
Token(TokenType tokenType) {
this.tokenType = tokenType;
Token(TokenType tokenType, ConfigOrigin origin) {
this(tokenType, origin, null);
}
public TokenType tokenType() {
Token(TokenType tokenType, ConfigOrigin origin, String debugString) {
this.tokenType = tokenType;
this.origin = origin;
this.debugString = debugString;
}
// this is used for singleton tokens like COMMA or OPEN_CURLY
static Token newWithoutOrigin(TokenType tokenType, String debugString) {
return new Token(tokenType, null, debugString);
}
final TokenType tokenType() {
return tokenType;
}
// this is final because we don't always use the origin() accessor,
// and we don't because it throws if origin is null
final ConfigOrigin origin() {
// code is only supposed to call origin() on token types that are
// expected to have an origin.
if (origin == null)
throw new ConfigException.BugOrBroken(
"tried to get origin from token that doesn't have one: " + this);
return origin;
}
final int lineNumber() {
if (origin != null)
return origin.lineNumber();
else
return -1;
}
@Override
public String toString() {
if (debugString != null)
return debugString;
else
return tokenType.name();
}
@ -26,6 +63,7 @@ class Token {
@Override
public boolean equals(Object other) {
if (other instanceof Token) {
// origin is deliberately left out
return canEqual(other)
&& this.tokenType == ((Token) other).tokenType;
} else {
@ -35,6 +73,7 @@ class Token {
@Override
public int hashCode() {
// origin is deliberately left out
return tokenType.hashCode();
}
}

View file

@ -4,5 +4,18 @@
package com.typesafe.config.impl;
enum TokenType {
START, END, COMMA, EQUALS, COLON, OPEN_CURLY, CLOSE_CURLY, OPEN_SQUARE, CLOSE_SQUARE, VALUE, NEWLINE, UNQUOTED_TEXT, SUBSTITUTION;
START,
END,
COMMA,
EQUALS,
COLON,
OPEN_CURLY,
CLOSE_CURLY,
OPEN_SQUARE,
CLOSE_SQUARE,
VALUE,
NEWLINE,
UNQUOTED_TEXT,
SUBSTITUTION,
PROBLEM;
}

View file

@ -16,6 +16,34 @@ import com.typesafe.config.ConfigOrigin;
import com.typesafe.config.ConfigSyntax;
final class Tokenizer {
// this exception should not leave this file
private static class ProblemException extends Exception {
private static final long serialVersionUID = 1L;
final private Token problem;
ProblemException(Token problem) {
this.problem = problem;
}
Token problem() {
return problem;
}
}
private static String asString(int codepoint) {
if (codepoint == '\n')
return "newline";
else if (codepoint == '\t')
return "tab";
else if (codepoint == -1)
return "end of file";
else if (Character.isISOControl(codepoint))
return String.format("control character 0x%x", codepoint);
else
return String.format("%c", codepoint);
}
/**
* Tokenizes a Reader. Does not close the reader; you have to arrange to do
* that after you're done with the returned iterator.
@ -85,20 +113,22 @@ final class Tokenizer {
}
}
final private ConfigOrigin origin;
final private SimpleConfigOrigin origin;
final private Reader input;
final private LinkedList<Integer> buffer;
private int lineNumber;
private ConfigOrigin lineOrigin;
final private Queue<Token> tokens;
final private WhitespaceSaver whitespaceSaver;
final private boolean allowComments;
TokenIterator(ConfigOrigin origin, Reader input, boolean allowComments) {
this.origin = origin;
this.origin = (SimpleConfigOrigin) origin;
this.input = input;
this.allowComments = allowComments;
this.buffer = new LinkedList<Integer>();
lineNumber = 1;
lineOrigin = this.origin.setLineNumber(lineNumber);
tokens = new LinkedList<Token>();
tokens.add(Tokens.START);
whitespaceSaver = new WhitespaceSaver();
@ -131,11 +161,11 @@ final class Tokenizer {
}
static boolean isWhitespace(int c) {
return ConfigUtil.isWhitespace(c);
return ConfigImplUtil.isWhitespace(c);
}
static boolean isWhitespaceNotNewline(int c) {
return c != '\n' && ConfigUtil.isWhitespace(c);
return c != '\n' && ConfigImplUtil.isWhitespace(c);
}
private int slurpComment() {
@ -194,27 +224,44 @@ final class Tokenizer {
}
}
private ConfigException parseError(String message) {
return parseError(message, null);
private ProblemException problem(String message) {
return problem("", message, null);
}
private ConfigException parseError(String message, Throwable cause) {
return parseError(lineOrigin(), message, cause);
private ProblemException problem(String what, String message) {
return problem(what, message, null);
}
private static ConfigException parseError(ConfigOrigin origin,
private ProblemException problem(String what, String message, boolean suggestQuotes) {
return problem(what, message, suggestQuotes, null);
}
private ProblemException problem(String what, String message, Throwable cause) {
return problem(lineOrigin, what, message, cause);
}
private ProblemException problem(String what, String message, boolean suggestQuotes,
Throwable cause) {
return problem(lineOrigin, what, message, suggestQuotes, cause);
}
private static ProblemException problem(ConfigOrigin origin, String what,
String message,
Throwable cause) {
return new ConfigException.Parse(origin, message, cause);
return problem(origin, what, message, false, cause);
}
private static ConfigException parseError(ConfigOrigin origin,
String message) {
return parseError(origin, message, null);
private static ProblemException problem(ConfigOrigin origin, String what, String message,
boolean suggestQuotes, Throwable cause) {
if (what == null || message == null)
throw new ConfigException.BugOrBroken(
"internal error, creating bad ProblemException");
return new ProblemException(Tokens.newProblem(origin, what, message, suggestQuotes,
cause));
}
private ConfigOrigin lineOrigin() {
return lineOrigin(origin, lineNumber);
private static ProblemException problem(ConfigOrigin origin, String message) {
return problem(origin, "", message, null);
}
private static ConfigOrigin lineOrigin(ConfigOrigin baseOrigin,
@ -234,7 +281,7 @@ final class Tokenizer {
// that parses as JSON is treated the JSON way and otherwise
// we assume it's a string and let the parser sort it out.
private Token pullUnquotedText() {
ConfigOrigin origin = lineOrigin();
ConfigOrigin origin = lineOrigin;
StringBuilder sb = new StringBuilder();
int c = nextCharSkippingComments();
while (true) {
@ -273,7 +320,7 @@ final class Tokenizer {
return Tokens.newUnquotedText(origin, s);
}
private Token pullNumber(int firstChar) {
private Token pullNumber(int firstChar) throws ProblemException {
StringBuilder sb = new StringBuilder();
sb.appendCodePoint(firstChar);
boolean containedDecimalOrE = false;
@ -291,23 +338,20 @@ final class Tokenizer {
try {
if (containedDecimalOrE) {
// force floating point representation
return Tokens.newDouble(lineOrigin(),
Double.parseDouble(s), s);
return Tokens.newDouble(lineOrigin, Double.parseDouble(s), s);
} else {
// this should throw if the integer is too large for Long
return Tokens.newLong(lineOrigin(), Long.parseLong(s), s);
return Tokens.newLong(lineOrigin, Long.parseLong(s), s);
}
} catch (NumberFormatException e) {
throw parseError("Invalid number: '" + s
+ "' (if this is in a path, try quoting it with double quotes)",
e);
throw problem(s, "Invalid number: '" + s + "'", true /* suggestQuotes */, e);
}
}
private void pullEscapeSequence(StringBuilder sb) {
private void pullEscapeSequence(StringBuilder sb) throws ProblemException {
int escaped = nextCharRaw();
if (escaped == -1)
throw parseError("End of input but backslash in string had nothing after it");
throw problem("End of input but backslash in string had nothing after it");
switch (escaped) {
case '"':
@ -340,67 +384,57 @@ final class Tokenizer {
for (int i = 0; i < 4; ++i) {
int c = nextCharSkippingComments();
if (c == -1)
throw parseError("End of input but expecting 4 hex digits for \\uXXXX escape");
throw problem("End of input but expecting 4 hex digits for \\uXXXX escape");
a[i] = (char) c;
}
String digits = new String(a);
try {
sb.appendCodePoint(Integer.parseInt(digits, 16));
} catch (NumberFormatException e) {
throw parseError(
String.format(
"Malformed hex digits after \\u escape in string: '%s'",
digits), e);
throw problem(digits, String.format(
"Malformed hex digits after \\u escape in string: '%s'", digits), e);
}
}
break;
default:
throw parseError(String
.format("backslash followed by '%c', this is not a valid escape sequence",
escaped));
throw problem(
asString(escaped),
String.format(
"backslash followed by '%s', this is not a valid escape sequence (quoted strings use JSON escaping, so use double-backslash \\\\ for literal backslash)",
asString(escaped)));
}
}
private ConfigException controlCharacterError(int c) {
String asString;
if (c == '\n')
asString = "newline";
else if (c == '\t')
asString = "tab";
else
asString = String.format("control character 0x%x", c);
return parseError("JSON does not allow unescaped " + asString
+ " in quoted strings, use a backslash escape");
}
private Token pullQuotedString() {
private Token pullQuotedString() throws ProblemException {
// the open quote has already been consumed
StringBuilder sb = new StringBuilder();
int c = '\0'; // value doesn't get used
do {
c = nextCharRaw();
if (c == -1)
throw parseError("End of input but string quote was still open");
throw problem("End of input but string quote was still open");
if (c == '\\') {
pullEscapeSequence(sb);
} else if (c == '"') {
// end the loop, done!
} else if (Character.isISOControl(c)) {
throw controlCharacterError(c);
throw problem(asString(c), "JSON does not allow unescaped " + asString(c)
+ " in quoted strings, use a backslash escape");
} else {
sb.appendCodePoint(c);
}
} while (c != '"');
return Tokens.newString(lineOrigin(), sb.toString());
return Tokens.newString(lineOrigin, sb.toString());
}
private Token pullSubstitution() {
private Token pullSubstitution() throws ProblemException {
// the initial '$' has already been consumed
ConfigOrigin origin = lineOrigin();
ConfigOrigin origin = lineOrigin;
int c = nextCharSkippingComments();
if (c != '{') {
throw parseError("'$' not followed by {");
throw problem(asString(c), "'$' not followed by {, '" + asString(c)
+ "' not allowed after '$'", true /* suggestQuotes */);
}
boolean optional = false;
@ -425,7 +459,7 @@ final class Tokenizer {
// end the loop, done!
break;
} else if (t == Tokens.END) {
throw parseError(origin,
throw problem(origin,
"Substitution ${ was not closed with a }");
} else {
Token whitespace = saver.check(t, origin, lineNumber);
@ -438,14 +472,16 @@ final class Tokenizer {
return Tokens.newSubstitution(origin, optional, expression);
}
private Token pullNextToken(WhitespaceSaver saver) {
private Token pullNextToken(WhitespaceSaver saver) throws ProblemException {
int c = nextCharAfterWhitespace(saver);
if (c == -1) {
return Tokens.END;
} else if (c == '\n') {
// newline tokens have the just-ended line number
Token line = Tokens.newLine(lineOrigin);
lineNumber += 1;
return Tokens.newLine(lineNumber - 1);
lineOrigin = origin.setLineNumber(lineNumber);
return line;
} else {
Token t = null;
switch (c) {
@ -482,9 +518,8 @@ final class Tokenizer {
if (firstNumberChars.indexOf(c) >= 0) {
t = pullNumber(c);
} else if (notInUnquotedText.indexOf(c) >= 0) {
throw parseError(String
.format("Character '%c' is not the start of any valid token",
c));
throw problem(asString(c), "Reserved character '" + asString(c)
+ "' is not allowed outside quotes", true /* suggestQuotes */);
} else {
putBack(c);
t = pullUnquotedText();
@ -508,7 +543,7 @@ final class Tokenizer {
}
}
private void queueNextToken() {
private void queueNextToken() throws ProblemException {
Token t = pullNextToken(whitespaceSaver);
Token whitespace = whitespaceSaver.check(t, origin, lineNumber);
if (whitespace != null)
@ -525,7 +560,11 @@ final class Tokenizer {
public Token next() {
Token t = tokens.remove();
if (tokens.isEmpty() && t != Tokens.END) {
try {
queueNextToken();
} catch (ProblemException e) {
tokens.add(e.problem());
}
if (tokens.isEmpty())
throw new ConfigException.BugOrBroken(
"bug: tokens queue should not be empty here");

View file

@ -9,13 +9,14 @@ import com.typesafe.config.ConfigException;
import com.typesafe.config.ConfigOrigin;
import com.typesafe.config.ConfigValueType;
/* FIXME the way the subclasses of Token are private with static isFoo and accessors is kind of ridiculous. */
final class Tokens {
static private class Value extends Token {
final private AbstractConfigValue value;
Value(AbstractConfigValue value) {
super(TokenType.VALUE);
super(TokenType.VALUE, value.origin());
this.value = value;
}
@ -25,10 +26,7 @@ final class Tokens {
@Override
public String toString() {
String s = tokenType().name() + "(" + value.valueType().name()
+ ")";
return s + "='" + value().unwrapped() + "'";
return "'" + value().unwrapped() + "' (" + value.valueType().name() + ")";
}
@Override
@ -48,20 +46,13 @@ final class Tokens {
}
static private class Line extends Token {
final private int lineNumber;
Line(int lineNumber) {
super(TokenType.NEWLINE);
this.lineNumber = lineNumber;
}
int lineNumber() {
return lineNumber;
Line(ConfigOrigin origin) {
super(TokenType.NEWLINE, origin);
}
@Override
public String toString() {
return "NEWLINE@" + lineNumber;
return "'\n'@" + lineNumber();
}
@Override
@ -71,38 +62,31 @@ final class Tokens {
@Override
public boolean equals(Object other) {
return super.equals(other)
&& ((Line) other).lineNumber == lineNumber;
return super.equals(other) && ((Line) other).lineNumber() == lineNumber();
}
@Override
public int hashCode() {
return 41 * (41 + super.hashCode()) + lineNumber;
return 41 * (41 + super.hashCode()) + lineNumber();
}
}
// This is not a Value, because it requires special processing
static private class UnquotedText extends Token {
final private ConfigOrigin origin;
final private String value;
UnquotedText(ConfigOrigin origin, String s) {
super(TokenType.UNQUOTED_TEXT);
this.origin = origin;
super(TokenType.UNQUOTED_TEXT, origin);
this.value = s;
}
ConfigOrigin origin() {
return origin;
}
String value() {
return value;
}
@Override
public String toString() {
return tokenType().name() + "(" + value + ")";
return "'" + value + "'";
}
@Override
@ -122,23 +106,78 @@ final class Tokens {
}
}
static private class Problem extends Token {
final private String what;
final private String message;
final private boolean suggestQuotes;
final private Throwable cause;
Problem(ConfigOrigin origin, String what, String message, boolean suggestQuotes,
Throwable cause) {
super(TokenType.PROBLEM, origin);
this.what = what;
this.message = message;
this.suggestQuotes = suggestQuotes;
this.cause = cause;
}
String message() {
return message;
}
boolean suggestQuotes() {
return suggestQuotes;
}
Throwable cause() {
return cause;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append('\'');
sb.append(what);
sb.append('\'');
return sb.toString();
}
@Override
protected boolean canEqual(Object other) {
return other instanceof Problem;
}
@Override
public boolean equals(Object other) {
return super.equals(other) && ((Problem) other).what.equals(what)
&& ((Problem) other).message.equals(message)
&& ((Problem) other).suggestQuotes == suggestQuotes
&& ConfigImplUtil.equalsHandlingNull(((Problem) other).cause, cause);
}
@Override
public int hashCode() {
int h = 41 * (41 + super.hashCode());
h = 41 * (h + what.hashCode());
h = 41 * (h + message.hashCode());
h = 41 * (h + Boolean.valueOf(suggestQuotes).hashCode());
if (cause != null)
h = 41 * (h + cause.hashCode());
return h;
}
}
// This is not a Value, because it requires special processing
static private class Substitution extends Token {
final private ConfigOrigin origin;
final private boolean optional;
final private List<Token> value;
Substitution(ConfigOrigin origin, boolean optional, List<Token> expression) {
super(TokenType.SUBSTITUTION);
this.origin = origin;
super(TokenType.SUBSTITUTION, origin);
this.optional = optional;
this.value = expression;
}
ConfigOrigin origin() {
return origin;
}
boolean optional() {
return optional;
}
@ -149,7 +188,11 @@ final class Tokens {
@Override
public String toString() {
return tokenType().name() + "(" + value.toString() + ")";
StringBuilder sb = new StringBuilder();
for (Token t : value) {
sb.append(t.toString());
}
return "'${" + sb.toString() + "}'";
}
@Override
@ -190,12 +233,32 @@ final class Tokens {
return token instanceof Line;
}
static int getLineNumber(Token token) {
if (token instanceof Line) {
return ((Line) token).lineNumber();
static boolean isProblem(Token token) {
return token instanceof Problem;
}
static String getProblemMessage(Token token) {
if (token instanceof Problem) {
return ((Problem) token).message();
} else {
throw new ConfigException.BugOrBroken(
"tried to get line number from non-newline " + token);
throw new ConfigException.BugOrBroken("tried to get problem message from " + token);
}
}
static boolean getProblemSuggestQuotes(Token token) {
if (token instanceof Problem) {
return ((Problem) token).suggestQuotes();
} else {
throw new ConfigException.BugOrBroken("tried to get problem suggestQuotes from "
+ token);
}
}
static Throwable getProblemCause(Token token) {
if (token instanceof Problem) {
return ((Problem) token).cause();
} else {
throw new ConfigException.BugOrBroken("tried to get problem cause from " + token);
}
}
@ -212,15 +275,6 @@ final class Tokens {
}
}
static ConfigOrigin getUnquotedTextOrigin(Token token) {
if (token instanceof UnquotedText) {
return ((UnquotedText) token).origin();
} else {
throw new ConfigException.BugOrBroken(
"tried to get unquoted text from " + token);
}
}
static boolean isSubstitution(Token token) {
return token instanceof Substitution;
}
@ -234,15 +288,6 @@ final class Tokens {
}
}
static ConfigOrigin getSubstitutionOrigin(Token token) {
if (token instanceof Substitution) {
return ((Substitution) token).origin();
} else {
throw new ConfigException.BugOrBroken(
"tried to get substitution origin from " + token);
}
}
static boolean getSubstitutionOptional(Token token) {
if (token instanceof Substitution) {
return ((Substitution) token).optional();
@ -252,18 +297,23 @@ final class Tokens {
}
}
final static Token START = new Token(TokenType.START);
final static Token END = new Token(TokenType.END);
final static Token COMMA = new Token(TokenType.COMMA);
final static Token EQUALS = new Token(TokenType.EQUALS);
final static Token COLON = new Token(TokenType.COLON);
final static Token OPEN_CURLY = new Token(TokenType.OPEN_CURLY);
final static Token CLOSE_CURLY = new Token(TokenType.CLOSE_CURLY);
final static Token OPEN_SQUARE = new Token(TokenType.OPEN_SQUARE);
final static Token CLOSE_SQUARE = new Token(TokenType.CLOSE_SQUARE);
final static Token START = Token.newWithoutOrigin(TokenType.START, "start of file");
final static Token END = Token.newWithoutOrigin(TokenType.END, "end of file");
final static Token COMMA = Token.newWithoutOrigin(TokenType.COMMA, "','");
final static Token EQUALS = Token.newWithoutOrigin(TokenType.EQUALS, "'='");
final static Token COLON = Token.newWithoutOrigin(TokenType.COLON, "':'");
final static Token OPEN_CURLY = Token.newWithoutOrigin(TokenType.OPEN_CURLY, "'{'");
final static Token CLOSE_CURLY = Token.newWithoutOrigin(TokenType.CLOSE_CURLY, "'}'");
final static Token OPEN_SQUARE = Token.newWithoutOrigin(TokenType.OPEN_SQUARE, "'['");
final static Token CLOSE_SQUARE = Token.newWithoutOrigin(TokenType.CLOSE_SQUARE, "']'");
static Token newLine(int lineNumberJustEnded) {
return new Line(lineNumberJustEnded);
static Token newLine(ConfigOrigin origin) {
return new Line(origin);
}
static Token newProblem(ConfigOrigin origin, String what, String message,
boolean suggestQuotes, Throwable cause) {
return new Problem(origin, what, message, suggestQuotes, cause);
}
static Token newUnquotedText(ConfigOrigin origin, String s) {

View file

@ -482,10 +482,10 @@ public class HashedWheelTimer implements Timer {
buf.append("deadline: ");
if (remaining > 0) {
buf.append(remaining);
buf.append(" ms later, ");
buf.append(" ns later, ");
} else if (remaining < 0) {
buf.append(-remaining);
buf.append(" ms ago, ");
buf.append(" ns ago, ");
} else {
buf.append("now, ");
}

View file

@ -79,7 +79,7 @@ akka {
type = "Dispatcher" # Must be one of the following
# Dispatcher, (BalancingDispatcher, only valid when all actors using it are of the same type),
# A FQCN to a class inheriting MessageDispatcherConfigurator with a no-arg visible constructor
name = "DefaultDispatcher" # Optional, will be a generated UUID if omitted
name = "DefaultDispatcher" # Name used in log messages and thread names.
keep-alive-time = 60s # Keep alive time for threads
core-pool-size-min = 8 # minimum number of threads to cap factor-based core number to
core-pool-size-factor = 8.0 # No of core threads ... ceil(available processors * factor)
@ -91,7 +91,8 @@ akka {
task-queue-size = -1 # Specifies the bounded capacity of the task queue (< 1 == unbounded)
task-queue-type = "linked" # Specifies which type of task queue will be used, can be "array" or "linked" (default)
allow-core-timeout = on # Allow core threads to time out
throughput = 5 # Throughput for Dispatcher, set to 1 for complete fairness
throughput = 5 # Throughput defines the number of messages that are processed in a batch before the
# thread is returned to the pool. Set to 1 for as fair as possible.
throughput-deadline-time = 0ms # Throughput deadline for Dispatcher, set to 0 or negative for no deadline
mailbox-capacity = -1 # If negative (or zero) then an unbounded mailbox is used (default)
# If positive then a bounded mailbox is used and the capacity is set using the property

View file

@ -14,8 +14,6 @@ import java.net.{ InetAddress, UnknownHostException }
* <li>toString that includes exception name, message and uuid</li>
* <li>toLongString which also includes the stack trace</li>
* </ul>
*
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
class AkkaException(message: String = "", cause: Throwable = null) extends RuntimeException(message, cause) with Serializable {
val uuid = "%s_%s".format(AkkaException.hostname, newUuid)

View file

@ -28,29 +28,8 @@ trait AutoReceivedMessage extends Serializable
trait PossiblyHarmful
case class HotSwap(code: ActorContext Actor.Receive, discardOld: Boolean = true) extends AutoReceivedMessage {
/**
* Java API
*/
def this(code: akka.japi.Function[ActorContext, Procedure[Any]], discardOld: Boolean) = {
this((context: ActorContext) {
val behavior = code(context)
val result: Actor.Receive = { case msg behavior(msg) }
result
}, discardOld)
}
/**
* Java API with default non-stacking behavior
*/
def this(code: akka.japi.Function[ActorContext, Procedure[Any]]) = this(code, true)
}
case class Failed(cause: Throwable) extends AutoReceivedMessage with PossiblyHarmful
case object RevertHotSwap extends AutoReceivedMessage with PossiblyHarmful
case object PoisonPill extends AutoReceivedMessage with PossiblyHarmful
case object Kill extends AutoReceivedMessage with PossiblyHarmful
@ -112,7 +91,7 @@ case class ActorInterruptedException private[akka] (cause: Throwable)
/**
* This message is thrown by default when an Actors behavior doesn't match a message
*/
case class UnhandledMessageException(msg: Any, ref: ActorRef = null) extends Exception {
case class UnhandledMessageException(msg: Any, ref: ActorRef = null) extends RuntimeException {
def this(msg: String) = this(msg, null)
@ -186,8 +165,6 @@ object Actor {
*
* <p/>
* The Actor's own ActorRef is available in the 'self' member variable.
*
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
trait Actor {
@ -204,18 +181,17 @@ trait Actor {
* [[akka.actor.UntypedActorContext]], which is the Java API of the actor
* context.
*/
@transient
protected[akka] implicit val context: ActorContext = {
val contextStack = ActorCell.contextStack.get
def noContextError =
throw new ActorInitializationException(
"\n\tYou cannot create an instance of " + getClass.getName + " explicitly using the constructor (new)." +
"\n\tYou cannot create an instance of [" + getClass.getName + "] explicitly using the constructor (new)." +
"\n\tYou have to use one of the factory methods to create a new actor. Either use:" +
"\n\t\t'val actor = context.actorOf[MyActor]' (to create a supervised child actor from within an actor), or" +
"\n\t\t'val actor = system.actorOf(new MyActor(..))' (to create a top level actor from the ActorSystem), or" +
"\n\t\t'val actor = context.actorOf[MyActor]' (to create a supervised child actor from within an actor), or" +
"\n\t\t'val actor = system.actorOf(new MyActor(..))' (to create a top level actor from the ActorSystem)")
"\n\t\t'val actor = context.actorOf(Props[MyActor])' (to create a supervised child actor from within an actor), or" +
"\n\t\t'val actor = system.actorOf(Props(new MyActor(..)))' (to create a top level actor from the ActorSystem), or" +
"\n\t\t'val actor = context.actorOf(Props[MyActor])' (to create a supervised child actor from within an actor), or" +
"\n\t\t'val actor = system.actorOf(Props(new MyActor(..)))' (to create a top level actor from the ActorSystem)")
if (contextStack.isEmpty) noContextError
val c = contextStack.head
@ -267,14 +243,17 @@ trait Actor {
/**
* User overridable callback.
* <p/>
* Is called when an Actor is started by invoking 'actor'.
* Is called when an Actor is started.
* Actors are automatically started asynchronously when created.
* Empty default implementation.
*/
def preStart() {}
/**
* User overridable callback.
* <p/>
* Is called when 'actor.stop()' is invoked.
* Is called asynchronously after 'actor.stop()' is invoked.
* Empty default implementation.
*/
def postStop() {}

View file

@ -12,6 +12,7 @@ import java.util.concurrent.TimeUnit.MILLISECONDS
import akka.event.Logging.{ Debug, Warning, Error }
import akka.util.{ Duration, Helpers }
import akka.japi.Procedure
import java.io.{ NotSerializableException, ObjectOutputStream }
/**
* The actor context - the view of the actor cell from the actor.
@ -27,16 +28,16 @@ import akka.japi.Procedure
* context.actorOf(props)
*
* // Scala
* context.actorOf[MyActor]("name")
* context.actorOf[MyActor]
* context.actorOf(new MyActor(...))
* context.actorOf(Props[MyActor]("name")
* context.actorOf(Props[MyActor]
* context.actorOf(Props(new MyActor(...))
*
* // Java
* context.actorOf(classOf[MyActor]);
* context.actorOf(new Creator<MyActor>() {
* context.actorOf(Props(new Creator<MyActor>() {
* public MyActor create() { ... }
* });
* context.actorOf(new Creator<MyActor>() {
* context.actorOf(Props(new Creator<MyActor>() {
* public MyActor create() { ... }
* }, "name");
* }}}
@ -63,7 +64,12 @@ trait ActorContext extends ActorRefFactory {
* When specified, the receive function should be able to handle a 'ReceiveTimeout' message.
* 1 millisecond is the minimum supported timeout.
*/
def receiveTimeout_=(timeout: Option[Duration]): Unit
def setReceiveTimeout(timeout: Duration): Unit
/**
* Resets the current receive timeout.
*/
def resetReceiveTimeout(): Unit
/**
* Changes the Actor's behavior to become the new 'Receive' (PartialFunction[Any, Unit]) handler.
@ -72,19 +78,29 @@ trait ActorContext extends ActorRefFactory {
*/
def become(behavior: Actor.Receive, discardOld: Boolean = true): Unit
def hotswap: Stack[PartialFunction[Any, Unit]]
/**
* Reverts the Actor behavior to the previous one in the hotswap stack.
*/
def unbecome(): Unit
/**
* Returns the current message envelope.
*/
def currentMessage: Envelope
def currentMessage_=(invocation: Envelope): Unit
/**
* Returns a stack with the hotswapped behaviors (as Scala PartialFunction).
*/
def hotswap: Stack[PartialFunction[Any, Unit]]
/**
* Returns the sender 'ActorRef' of the current message.
*/
def sender: ActorRef
/**
* Returns all supervised children.
*/
def children: Iterable[ActorRef]
/**
@ -103,41 +119,35 @@ trait ActorContext extends ActorRefFactory {
*/
implicit def system: ActorSystem
/**
* Returns the supervising parent ActorRef.
*/
def parent: ActorRef
/**
* Registers this actor as a Monitor for the provided ActorRef
* Registers this actor as a Monitor for the provided ActorRef.
* @return the provided ActorRef
*/
def watch(subject: ActorRef): ActorRef
/**
* Unregisters this actor as Monitor for the provided ActorRef
* Unregisters this actor as Monitor for the provided ActorRef.
* @return the provided ActorRef
*/
def unwatch(subject: ActorRef): ActorRef
final protected def writeObject(o: ObjectOutputStream): Unit =
throw new NotSerializableException("ActorContext is not serializable!")
}
trait UntypedActorContext extends ActorContext {
/**
* Returns an unmodifiable Java Collection containing the linked actors,
* please note that the backing map is thread-safe but not immutable
*/
def getChildren(): java.lang.Iterable[ActorRef]
/**
* Gets the current receive timeout
* When specified, the receive method should be able to handle a 'ReceiveTimeout' message.
*/
def getReceiveTimeout: Option[Duration]
/**
* Defines the default timeout for an initial receive invocation.
* When specified, the receive function should be able to handle a 'ReceiveTimeout' message.
* 1 millisecond is the minimum supported timeout.
*/
def setReceiveTimeout(timeout: Duration): Unit
/**
* Changes the Actor's behavior to become the new 'Procedure' handler.
* Puts the behavior on top of the hotswap stack.
@ -191,7 +201,9 @@ private[akka] class ActorCell(
override final def receiveTimeout: Option[Duration] = if (receiveTimeoutData._1 > 0) Some(Duration(receiveTimeoutData._1, MILLISECONDS)) else None
override final def receiveTimeout_=(timeout: Option[Duration]): Unit = {
override final def setReceiveTimeout(timeout: Duration): Unit = setReceiveTimeout(Some(timeout))
final def setReceiveTimeout(timeout: Option[Duration]): Unit = {
val timeoutMs = timeout match {
case None -1L
case Some(duration)
@ -204,22 +216,14 @@ private[akka] class ActorCell(
receiveTimeoutData = (timeoutMs, receiveTimeoutData._2)
}
final override def resetReceiveTimeout(): Unit = setReceiveTimeout(None)
/**
* In milliseconds
*/
final var receiveTimeoutData: (Long, Cancellable) =
if (_receiveTimeout.isDefined) (_receiveTimeout.get.toMillis, emptyCancellable) else emptyReceiveTimeoutData
/**
* UntypedActorContext impl
*/
final def getReceiveTimeout: Option[Duration] = receiveTimeout
/**
* UntypedActorContext impl
*/
final def setReceiveTimeout(timeout: Duration): Unit = receiveTimeout = Some(timeout)
final var childrenRefs: TreeMap[String, ChildRestartStats] = emptyChildrenRefs
private def _actorOf(props: Props, name: String): ActorRef = {
@ -392,7 +396,7 @@ private[akka] class ActorCell(
def resume(): Unit = dispatcher resume this
def terminate() {
receiveTimeout = None
setReceiveTimeout(None)
cancelReceiveTimeout
val c = children
@ -515,8 +519,6 @@ private[akka] class ActorCell(
if (system.settings.DebugAutoReceive) system.eventStream.publish(Debug(self.path.toString, "received AutoReceiveMessage " + msg))
msg.message match {
case HotSwap(code, discardOld) become(code(this), discardOld)
case RevertHotSwap unbecome()
case Failed(cause) handleFailure(sender, cause)
case Kill throw new ActorKilledException("Kill")
case PoisonPill self.stop()
@ -527,11 +529,13 @@ private[akka] class ActorCell(
}
private def doTerminate() {
dispatcher.detach(this)
try {
try {
val a = actor
if (a ne null) a.postStop()
} finally {
dispatcher.detach(this)
}
} finally {
try {
parent.sendSystemMessage(ChildTerminated(self))

View file

@ -25,28 +25,26 @@ import akka.event.LoggingAdapter
* <pre>
* import Actor._
*
* val actor = actorOf[MyActor]
* val actor = actorOf(Props[MyActor]
* actor ! message
* actor.stop()
* </pre>
*
* You can also create and start actors like this:
* <pre>
* val actor = actorOf[MyActor]
* val actor = actorOf(Props[MyActor]
* </pre>
*
* Here is an example on how to create an actor with a non-default constructor.
* <pre>
* import Actor._
*
* val actor = actorOf(new MyActor(...))
* val actor = actorOf(Props(new MyActor(...))
* actor ! message
* actor.stop()
* </pre>
*
* The natural ordering of ActorRef is defined in terms of its [[akka.actor.ActorPath]].
*
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
abstract class ActorRef extends java.lang.Comparable[ActorRef] with Serializable {
scalaRef: InternalActorRef
@ -81,17 +79,29 @@ abstract class ActorRef extends java.lang.Comparable[ActorRef] with Serializable
final def tell(msg: Any, sender: ActorRef): Unit = this.!(msg)(sender)
/**
* Akka Java API. <p/>
* Akka Java API.
*
* Sends a message asynchronously returns a future holding the eventual reply message.
* <p/>
*
* <b>NOTE:</b>
* Use this method with care. In most cases it is better to use 'tell' together with the 'getContext().getSender()' to
* implement request/response message exchanges.
* <p/>
* If you are sending messages using <code>ask</code> then you <b>have to</b> use <code>getContext().sender().tell(...)</code>
* to send a reply message to the original sender. If not then the sender will block until the timeout expires.
* Use this method with care. In most cases it is better to use 'tell' together with the sender
* parameter to implement non-blocking request/response message exchanges.
*
* If you are sending messages using <code>ask</code> and using blocking operations on the Future, such as
* 'get', then you <b>have to</b> use <code>getContext().sender().tell(...)</code>
* in the target actor to send a reply message to the original sender, and thereby completing the Future,
* otherwise the sender will block until the timeout expires.
*
* When using future callbacks, inside actors you need to carefully avoid closing over
* the containing actors reference, i.e. do not call methods or access mutable state
* on the enclosing actor from within the callback. This would break the actor
* encapsulation and may introduce synchronization bugs and race conditions because
* the callback will be scheduled concurrently to the enclosing actor. Unfortunately
* there is not yet a way to detect these illegal accesses at compile time.
*/
def ask(message: AnyRef, timeout: Long): Future[AnyRef] = ?(message, Timeout(timeout)).asInstanceOf[Future[AnyRef]]
def ask(message: AnyRef, timeout: Timeout): Future[AnyRef] = ?(message, timeout).asInstanceOf[Future[AnyRef]]
def ask(message: AnyRef, timeoutMillis: Long): Future[AnyRef] = ask(message, new Timeout(timeoutMillis))
/**
* Forwards the message and passes the original sender actor as the sender.
@ -146,6 +156,21 @@ trait ScalaActorRef { ref: ActorRef ⇒
/**
* Sends a message asynchronously, returning a future which may eventually hold the reply.
* <b>NOTE:</b>
* Use this method with care. In most cases it is better to use '!' together with implicit or explicit
* sender parameter to implement non-blocking request/response message exchanges.
*
* If you are sending messages using <code>ask</code> and using blocking operations on the Future, such as
* 'get', then you <b>have to</b> use <code>getContext().sender().tell(...)</code>
* in the target actor to send a reply message to the original sender, and thereby completing the Future,
* otherwise the sender will block until the timeout expires.
*
* When using future callbacks, inside actors you need to carefully avoid closing over
* the containing actors reference, i.e. do not call methods or access mutable state
* on the enclosing actor from within the callback. This would break the actor
* encapsulation and may introduce synchronization bugs and race conditions because
* the callback will be scheduled concurrently to the enclosing actor. Unfortunately
* there is not yet a way to detect these illegal accesses at compile time.
*/
def ?(message: Any)(implicit timeout: Timeout): Future[Any]
@ -186,8 +211,6 @@ private[akka] case object Nobody extends MinimalActorRef {
/**
* Local (serializable) ActorRef that is used when referencing the Actor on its "home" node.
*
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
private[akka] class LocalActorRef private[akka] (
_system: ActorSystemImpl,
@ -473,7 +496,7 @@ class AskActorRef(
}
override def ?(message: Any)(implicit timeout: Timeout): Future[Any] =
new KeptPromise[Any](Left(new UnsupportedOperationException("Ask/? is not supported for %s".format(getClass.getName))))(dispatcher)
new KeptPromise[Any](Left(new UnsupportedOperationException("Ask/? is not supported for [%s]".format(getClass.getName))))(dispatcher)
override def isTerminated = result.isCompleted || result.isExpired

View file

@ -154,82 +154,6 @@ trait ActorRefFactory {
*/
def actorOf(props: Props, name: String): ActorRef
/**
* Create new actor of the given type as child of this context and give it an automatically
* generated name (currently similar to base64-encoded integer count,
* reversed and with $ prepended, may change in the future). The type must have
* a no-arg constructor which will be invoked using reflection.
*
* When invoked on ActorSystem, this method sends a message to the guardian
* actor and blocks waiting for a reply, see `akka.actor.creation-timeout` in
* the `reference.conf`.
*/
def actorOf[T <: Actor](implicit m: Manifest[T]): ActorRef = actorOf(Props(m.erasure.asInstanceOf[Class[_ <: Actor]]))
/**
* Create new actor of the given type as child of this context with the given name, which must
* not be null, empty or start with $. If the given name is already in use,
* and `InvalidActorNameException` is thrown. The type must have
* a no-arg constructor which will be invoked using reflection.
*
* When invoked on ActorSystem, this method sends a message to the guardian
* actor and blocks waiting for a reply, see `akka.actor.creation-timeout` in
* the `reference.conf`.
*/
def actorOf[T <: Actor](name: String)(implicit m: Manifest[T]): ActorRef =
actorOf(Props(m.erasure.asInstanceOf[Class[_ <: Actor]]), name)
/**
* Create new actor of the given class as child of this context and give it an automatically
* generated name (currently similar to base64-encoded integer count,
* reversed and with $ prepended, may change in the future). The class must have
* a no-arg constructor which will be invoked using reflection.
*
* When invoked on ActorSystem, this method sends a message to the guardian
* actor and blocks waiting for a reply, see `akka.actor.creation-timeout` in
* the `reference.conf`.
*/
def actorOf[T <: Actor](clazz: Class[T]): ActorRef = actorOf(Props(clazz))
/**
* Create new actor as child of this context and give it an automatically
* generated name (currently similar to base64-encoded integer count,
* reversed and with $ prepended, may change in the future). Use this
* method to pass constructor arguments to the [[akka.actor.Actor]] while using
* only default [[akka.actor.Props]]; otherwise refer to `actorOf(Props)`.
*
* When invoked on ActorSystem, this method sends a message to the guardian
* actor and blocks waiting for a reply, see `akka.actor.creation-timeout` in
* the `reference.conf`.
*/
def actorOf(factory: Actor): ActorRef = actorOf(Props(() factory))
/**
* ''Java API'': Create new actor as child of this context and give it an
* automatically generated name (currently similar to base64-encoded integer
* count, reversed and with $ prepended, may change in the future).
*
* Identical to `actorOf(Props(() => creator.create()))`.
*
* When invoked on ActorSystem, this method sends a message to the guardian
* actor and blocks waiting for a reply, see `akka.actor.creation-timeout` in
* the `reference.conf`.
*/
def actorOf(creator: UntypedActorFactory): ActorRef = actorOf(Props(() creator.create()))
/**
* ''Java API'': Create new actor as child of this context with the given name, which must
* not be null, empty or start with $. If the given name is already in use,
* and `InvalidActorNameException` is thrown.
*
* Identical to `actorOf(Props(() => creator.create()), name)`.
*
* When invoked on ActorSystem, this method sends a message to the guardian
* actor and blocks waiting for a reply, see `akka.actor.creation-timeout` in
* the `reference.conf`.
*/
def actorOf(creator: UntypedActorFactory, name: String): ActorRef = actorOf(Props(() creator.create()), name)
/**
* Look-up an actor by path; if it does not exist, returns a reference to
* the dead-letter mailbox of the [[akka.actor.ActorSystem]]. If the path
@ -386,14 +310,14 @@ class LocalActorRefProvider(
override def !(message: Any)(implicit sender: ActorRef = null): Unit = stopped.ifOff(message match {
case Failed(ex) if sender ne null causeOfTermination = Some(ex); sender.stop()
case _ log.error(this + " received unexpected message " + message)
case _ log.error(this + " received unexpected message [" + message + "]")
})
override def sendSystemMessage(message: SystemMessage): Unit = stopped ifOff {
message match {
case Supervise(child) // TODO register child in some map to keep track of it and enable shutdown after all dead
case ChildTerminated(child) stop()
case _ log.error(this + " received unexpected system message " + message)
case _ log.error(this + " received unexpected system message [" + message + "]")
}
}
}

View file

@ -104,8 +104,7 @@ object ActorSystem {
val SchedulerTicksPerWheel = getInt("akka.scheduler.ticksPerWheel")
if (ConfigVersion != Version)
throw new ConfigurationException("Akka JAR version [" + Version +
"] does not match the provided config version [" + ConfigVersion + "]")
throw new ConfigurationException("Akka JAR version [" + Version + "] does not match the provided config version [" + ConfigVersion + "]")
override def toString: String = config.root.render
}
@ -168,16 +167,16 @@ object ActorSystem {
* system.actorOf(props)
*
* // Scala
* system.actorOf[MyActor]("name")
* system.actorOf[MyActor]
* system.actorOf(new MyActor(...))
* system.actorOf(Props[MyActor]("name")
* system.actorOf(Props[MyActor]
* system.actorOf(Props(new MyActor(...))
*
* // Java
* system.actorOf(classOf[MyActor]);
* system.actorOf(new Creator<MyActor>() {
* system.actorOf(Props(new Creator<MyActor>() {
* public MyActor create() { ... }
* });
* system.actorOf(new Creator<MyActor>() {
* system.actorOf(Props(new Creator<MyActor>() {
* public MyActor create() { ... }
* }, "name");
* }}}
@ -262,12 +261,13 @@ abstract class ActorSystem extends ActorRefFactory {
* effort basis and hence not strictly guaranteed.
*/
def deadLetters: ActorRef
//#scheduler
/**
* Light-weight scheduler for running asynchronous tasks after some deadline
* in the future. Not terribly precise but cheap.
*/
def scheduler: Scheduler
//#scheduler
/**
* Helper object for creating new dispatchers and passing in all required
@ -327,7 +327,7 @@ abstract class ActorSystem extends ActorRefFactory {
class ActorSystemImpl(val name: String, applicationConfig: Config) extends ActorSystem {
if (!name.matches("""^\w+$"""))
throw new IllegalArgumentException("invalid ActorSystem name '" + name + "', must contain only word characters (i.e. [a-zA-Z_0-9])")
throw new IllegalArgumentException("invalid ActorSystem name [" + name + "], must contain only word characters (i.e. [a-zA-Z_0-9])")
import ActorSystem._
@ -492,7 +492,7 @@ class ActorSystemImpl(val name: String, applicationConfig: Config) extends Actor
extensions.putIfAbsent(ext, inProcessOfRegistration) match { // Signal that registration is in process
case null try { // Signal was successfully sent
ext.createExtension(this) match { // Create and initialize the extension
case null throw new IllegalStateException("Extension instance created as null for Extension: " + ext)
case null throw new IllegalStateException("Extension instance created as 'null' for extension [" + ext + "]")
case instance
extensions.replace(ext, inProcessOfRegistration, instance) //Replace our in process signal with the initialized extension
instance //Profit!
@ -511,7 +511,7 @@ class ActorSystemImpl(val name: String, applicationConfig: Config) extends Actor
}
def extension[T <: Extension](ext: ExtensionId[T]): T = findExtension(ext) match {
case null throw new IllegalArgumentException("Trying to get non-registered extension " + ext)
case null throw new IllegalArgumentException("Trying to get non-registered extension [" + ext + "]")
case some some.asInstanceOf[T]
}
@ -524,8 +524,8 @@ class ActorSystemImpl(val name: String, applicationConfig: Config) extends Actor
getObjectFor[AnyRef](fqcn).fold(_ createInstance[AnyRef](fqcn, noParams, noArgs), Right(_)) match {
case Right(p: ExtensionIdProvider) registerExtension(p.lookup());
case Right(p: ExtensionId[_]) registerExtension(p);
case Right(other) log.error("'{}' is not an ExtensionIdProvider or ExtensionId, skipping...", fqcn)
case Left(problem) log.error(problem, "While trying to load extension '{}', skipping...", fqcn)
case Right(other) log.error("[{}] is not an 'ExtensionIdProvider' or 'ExtensionId', skipping...", fqcn)
case Left(problem) log.error(problem, "While trying to load extension [{}], skipping...", fqcn)
}
}

View file

@ -564,7 +564,6 @@ trait FSM[S, D] extends ListenerManagement {
/**
* Stackable trait for FSM which adds a rolling event log.
*
* @author Roland Kuhn
* @since 1.2
*/
trait LoggingFSM[S, D] extends FSM[S, D] { this: Actor

View file

@ -193,7 +193,7 @@ trait IO {
private def run() {
_next match {
case ByteStringLength(continuation, handle, message, waitingFor)
context.currentMessage = message
context.asInstanceOf[ActorCell].currentMessage = message
val st = state(handle)
if (st.readBytes.length >= waitingFor) {
val bytes = st.readBytes.take(waitingFor) //.compact
@ -202,7 +202,7 @@ trait IO {
run()
}
case bsd @ ByteStringDelimited(continuation, handle, message, delimiter, inclusive, scanned)
context.currentMessage = message
context.asInstanceOf[ActorCell].currentMessage = message
val st = state(handle)
val idx = st.readBytes.indexOfSlice(delimiter, scanned)
if (idx >= 0) {
@ -215,7 +215,7 @@ trait IO {
_next = bsd.copy(scanned = math.min(idx - delimiter.length, 0))
}
case ByteStringAny(continuation, handle, message)
context.currentMessage = message
context.asInstanceOf[ActorCell].currentMessage = message
val st = state(handle)
if (st.readBytes.length > 0) {
val bytes = st.readBytes //.compact

View file

@ -86,6 +86,25 @@ case class Props(creator: () ⇒ Actor = Props.defaultCreator,
timeout: Timeout = Props.defaultTimeout,
faultHandler: FaultHandlingStrategy = Props.defaultFaultHandler,
routerConfig: RouterConfig = Props.defaultRoutedProps) {
/**
* Java API
*/
def this(factory: UntypedActorFactory) = this(
creator = () factory.create(),
dispatcher = Props.defaultDispatcher,
timeout = Props.defaultTimeout,
faultHandler = Props.defaultFaultHandler)
/**
* Java API
*/
def this(actorClass: Class[_ <: Actor]) = this(
creator = () actorClass.newInstance,
dispatcher = Props.defaultDispatcher,
timeout = Props.defaultTimeout,
faultHandler = Props.defaultFaultHandler)
/**
* No-args constructor that sets all the default values
* Java API

View file

@ -13,7 +13,7 @@
package akka.actor
import akka.util.Duration
//#scheduler
/**
* An Akka scheduler service. This one needs one special behavior: if
* Closeable, it MUST execute all outstanding tasks upon .close() in order
@ -28,6 +28,8 @@ trait Scheduler {
* Schedules a message to be sent repeatedly with an initial delay and frequency.
* E.g. if you would like a message to be sent immediately and thereafter every 500ms you would set
* delay = Duration.Zero and frequency = Duration(500, TimeUnit.MILLISECONDS)
*
* Java & Scala API
*/
def schedule(initialDelay: Duration, frequency: Duration, receiver: ActorRef, message: Any): Cancellable
@ -35,33 +37,53 @@ trait Scheduler {
* Schedules a function to be run repeatedly with an initial delay and a frequency.
* E.g. if you would like the function to be run after 2 seconds and thereafter every 100ms you would set
* delay = Duration(2, TimeUnit.SECONDS) and frequency = Duration(100, TimeUnit.MILLISECONDS)
*
* Scala API
*/
def schedule(initialDelay: Duration, frequency: Duration)(f: Unit): Cancellable
/**
* Schedules a Runnable to be run once with a delay, i.e. a time period that has to pass before the runnable is executed.
*
* Java & Scala API
*/
def scheduleOnce(delay: Duration, runnable: Runnable): Cancellable
/**
* Schedules a message to be sent once with a delay, i.e. a time period that has to pass before the message is sent.
*
* Java & Scala API
*/
def scheduleOnce(delay: Duration, receiver: ActorRef, message: Any): Cancellable
/**
* Schedules a function to be run once with a delay, i.e. a time period that has to pass before the function is run.
*
* Scala API
*/
def scheduleOnce(delay: Duration)(f: Unit): Cancellable
}
//#scheduler
//#cancellable
/**
* Signifies something that can be cancelled
* There is no strict guarantee that the implementation is thread-safe,
* but it should be good practice to make it so.
*/
trait Cancellable {
/**
* Cancels the underlying scheduled task.
* Cancels this Cancellable
*
* Java & Scala API
*/
def cancel(): Unit
/**
* Checks if the underlying scheduled task has been cancelled.
* Returns whether this Cancellable has been cancelled
*
* Java & Scala API
*/
def isCancelled: Boolean
}
//#cancellable

View file

@ -48,8 +48,6 @@ import akka.dispatch.{ MessageDispatcher, Promise }
* }
* }
* </pre>
*
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
abstract class UntypedActor extends Actor {
@ -75,30 +73,36 @@ abstract class UntypedActor extends Actor {
/**
* User overridable callback.
* <p/>
* Is called when an Actor is started, this only happens at most once in the life of an actor.
* Is called when an Actor is started.
* Actor are automatically started asynchronously when created.
* Empty default implementation.
*/
override def preStart() {}
/**
* User overridable callback.
* <p/>
* Is called when 'actor.stop()' is invoked.
* Is called asynchronously after 'actor.stop()' is invoked.
* Empty default implementation.
*/
override def postStop() {}
/**
* User overridable callback.
* <p/>
* Is called on a crashed Actor right BEFORE it is restarted to allow clean up of resources before Actor is terminated.
* Is called on a crashed Actor right BEFORE it is restarted to allow clean
* up of resources before Actor is terminated.
* By default it calls postStop()
*/
override def preRestart(reason: Throwable, lastMessage: Option[Any]) {}
override def preRestart(reason: Throwable, message: Option[Any]) { postStop() }
/**
* User overridable callback.
* <p/>
* Is called right AFTER restart on the newly created Actor to allow reinitialization after an Actor crash.
* By default it calls preStart()
*/
override def postRestart(reason: Throwable) {}
override def postRestart(reason: Throwable) { preStart() }
/**
* User overridable callback.
@ -117,7 +121,5 @@ abstract class UntypedActor extends Actor {
/**
* Factory closure for an UntypedActor, to be used with 'Actors.actorOf(factory)'.
*
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
trait UntypedActorFactory extends Creator[Actor]

View file

@ -17,9 +17,6 @@ import akka.event.EventStream
import akka.actor.ActorSystem.Settings
import com.typesafe.config.Config
/**
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
final case class Envelope(val message: Any, val sender: ActorRef) {
if (message.isInstanceOf[AnyRef] && (message.asInstanceOf[AnyRef] eq null)) throw new InvalidMessageException("Message is null")
}
@ -87,9 +84,6 @@ object MessageDispatcher {
implicit def defaultDispatcher(implicit system: ActorSystem) = system.dispatcher
}
/**
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
abstract class MessageDispatcher(val prerequisites: DispatcherPrerequisites) extends AbstractMessageDispatcher with Serializable {
import MessageDispatcher._
@ -138,7 +132,7 @@ abstract class MessageDispatcher(val prerequisites: DispatcherPrerequisites) ext
shutdownScheduleUpdater.get(this) match {
case UNSCHEDULED
if (shutdownScheduleUpdater.compareAndSet(this, UNSCHEDULED, SCHEDULED)) {
scheduler.scheduleOnce(shutdownTimeout, shutdownAction)
scheduleShutdownAction()
()
} else ifSensibleToDoSoThenScheduleShutdown()
case SCHEDULED
@ -149,6 +143,13 @@ abstract class MessageDispatcher(val prerequisites: DispatcherPrerequisites) ext
case _ ()
}
private def scheduleShutdownAction(): Unit = {
// IllegalStateException is thrown if scheduler has been shutdown
try scheduler.scheduleOnce(shutdownTimeout, shutdownAction) catch {
case _: IllegalStateException shutdown()
}
}
private final val taskCleanup: () Unit =
() if (inhabitantsUpdater.decrementAndGet(this) == 0) ifSensibleToDoSoThenScheduleShutdown()
@ -169,36 +170,9 @@ abstract class MessageDispatcher(val prerequisites: DispatcherPrerequisites) ext
val mailBox = actor.mailbox
mailBox.becomeClosed() // FIXME reschedule in tell if possible race with cleanUp is detected in order to properly clean up
actor.mailbox = deadLetterMailbox
cleanUpMailboxFor(actor, mailBox)
mailBox.cleanUp()
}
/**
* Overridable callback to clean up the mailbox for a given actor,
* called when an actor is unregistered.
*/
protected def cleanUpMailboxFor(actor: ActorCell, mailBox: Mailbox) {
if (mailBox.hasSystemMessages) {
var message = mailBox.systemDrain()
while (message ne null) {
// message must be virgin before being able to systemEnqueue again
val next = message.next
message.next = null
deadLetterMailbox.systemEnqueue(actor.self, message)
message = next
}
}
if (mailBox.hasMessages) {
var envelope = mailBox.dequeue
while (envelope ne null) {
deadLetterMailbox.enqueue(actor.self, envelope)
envelope = mailBox.dequeue
}
}
}
private val shutdownAction = new Runnable {
@tailrec
final def run() {
@ -213,9 +187,7 @@ abstract class MessageDispatcher(val prerequisites: DispatcherPrerequisites) ext
}
case RESCHEDULED
if (shutdownScheduleUpdater.compareAndSet(MessageDispatcher.this, RESCHEDULED, SCHEDULED))
try scheduler.scheduleOnce(shutdownTimeout, this) catch {
case _: IllegalStateException shutdown()
}
scheduleShutdownAction()
else run()
}
}
@ -224,7 +196,7 @@ abstract class MessageDispatcher(val prerequisites: DispatcherPrerequisites) ext
/**
* When the dispatcher no longer has any actors registered, how long will it wait until it shuts itself down,
* defaulting to your akka configs "akka.actor.dispatcher-shutdown-timeout" or default specified in
* akka-actor-reference.conf
* reference.conf
*/
protected[akka] def shutdownTimeout: Duration
@ -290,7 +262,7 @@ abstract class MessageDispatcher(val prerequisites: DispatcherPrerequisites) ext
}
/**
* Trait to be used for hooking in new dispatchers into Dispatchers.fromConfig
* Trait to be used for hooking in new dispatchers into Dispatchers.from(cfg: Config)
*/
abstract class MessageDispatcherConfigurator() {
/**
@ -307,7 +279,8 @@ abstract class MessageDispatcherConfigurator() {
}
}
def configureThreadPool(config: Config,
def configureThreadPool(
config: Config,
settings: Settings,
createDispatcher: (ThreadPoolConfig) MessageDispatcher): ThreadPoolConfigDispatcherBuilder = {
import ThreadPoolConfigDispatcherBuilder.conf_?

View file

@ -28,8 +28,6 @@ import akka.util.Duration
*
* @see akka.dispatch.BalancingDispatcher
* @see akka.dispatch.Dispatchers
*
* @author Viktor Klang
*/
class BalancingDispatcher(
_prerequisites: DispatcherPrerequisites,
@ -65,6 +63,21 @@ class BalancingDispatcher(
final def numberOfMessages: Int = messageQueue.numberOfMessages
final def hasMessages: Boolean = messageQueue.hasMessages
override def cleanUp(): Unit = {
//Don't call the original implementation of this since it scraps all messages, and we don't want to do that
if (hasSystemMessages) {
val dlq = actor.systemImpl.deadLetterMailbox
var message = systemDrain()
while (message ne null) {
// message must be virgin before being able to systemEnqueue again
val next = message.next
message.next = null
dlq.systemEnqueue(actor.self, message)
message = next
}
}
}
}
protected[akka] override def register(actor: ActorCell) = {
@ -78,19 +91,6 @@ class BalancingDispatcher(
intoTheFray(except = actor) //When someone leaves, he tosses a friend into the fray
}
protected override def cleanUpMailboxFor(actor: ActorCell, mailBox: Mailbox) {
if (mailBox.hasSystemMessages) {
var message = mailBox.systemDrain()
while (message ne null) {
// message must be virgin before being able to systemEnqueue again
val next = message.next
message.next = null
prerequisites.deadLetterMailbox.systemEnqueue(actor.self, message)
message = next
}
}
}
def intoTheFray(except: ActorCell): Unit =
if (rebalance.compareAndSet(false, true)) {
try {

View file

@ -55,7 +55,6 @@ import java.util.concurrent._
* But the preferred way of creating dispatchers is to use
* the {@link akka.dispatch.Dispatchers} factory object.
*
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
* @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.

View file

@ -4,16 +4,19 @@
package akka.dispatch
import java.util.concurrent.TimeUnit
import java.util.concurrent.ConcurrentHashMap
import akka.actor.LocalActorRef
import akka.actor.newUuid
import akka.util.{ Duration, ReflectiveAccess }
import java.util.concurrent.TimeUnit
import akka.actor.ActorSystem
import akka.event.EventStream
import akka.actor.Scheduler
import akka.actor.ActorSystem.Settings
import com.typesafe.config.Config
import com.typesafe.config.ConfigFactory
import akka.config.ConfigurationException
trait DispatcherPrerequisites {
def eventStream: EventStream
@ -27,6 +30,10 @@ case class DefaultDispatcherPrerequisites(
val scheduler: Scheduler) extends DispatcherPrerequisites
/**
* It is recommended to define the dispatcher in configuration to allow for tuning
* for different environments. Use the `lookup` or `newFromConfig` method to create
* a dispatcher as specified in configuration.
*
* Scala API. Dispatcher factory.
* <p/>
* Example usage:
@ -53,8 +60,6 @@ case class DefaultDispatcherPrerequisites(
* .build();
* </pre>
* <p/>
*
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
class Dispatchers(val settings: ActorSystem.Settings, val prerequisites: DispatcherPrerequisites) {
@ -64,9 +69,33 @@ class Dispatchers(val settings: ActorSystem.Settings, val prerequisites: Dispatc
val defaultDispatcherConfig = settings.config.getConfig("akka.actor.default-dispatcher")
// TODO PN Shouldn't we fail hard if default-dispatcher is wrong?
lazy val defaultGlobalDispatcher =
from(defaultDispatcherConfig) getOrElse newDispatcher("AkkaDefaultGlobalDispatcher", 1, MailboxType).build
lazy val defaultGlobalDispatcher: MessageDispatcher =
from(defaultDispatcherConfig) getOrElse {
throw new ConfigurationException("Wrong configuration [akka.actor.default-dispatcher]")
}
// FIXME: Dispatchers registered here are are not removed, see ticket #1494
private val dispatchers = new ConcurrentHashMap[String, MessageDispatcher]
/**
* Returns a dispatcher as specified in configuration, or if not defined it uses
* the default dispatcher. The same dispatcher instance is returned for subsequent
* lookups.
*/
def lookup(key: String): MessageDispatcher = {
dispatchers.get(key) match {
case null
// It doesn't matter if we create a dispatcher that isn't used due to concurrent lookup.
// That shouldn't happen often and in case it does the actual ExecutorService isn't
// created until used, i.e. cheap.
val newDispatcher = newFromConfig(key)
dispatchers.putIfAbsent(key, newDispatcher) match {
case null newDispatcher
case existing existing
}
case existing existing
}
}
/**
* Creates an thread based dispatcher serving a single actor through the same single thread.
@ -135,7 +164,7 @@ class Dispatchers(val settings: ActorSystem.Settings, val prerequisites: Dispatc
new Dispatcher(prerequisites, name, throughput, throughputDeadline, mailboxType, config, settings.DispatcherDefaultShutdown), ThreadPoolConfig())
/**
* Creates a executor-based event-driven dispatcher, with work-stealing, serving multiple (millions) of actors through a thread pool.
* Creates a executor-based event-driven dispatcher, with work-sharing, serving multiple (millions) of actors through a thread pool.
* <p/>
* Has a fluent builder interface for configuring its semantics.
*/
@ -144,7 +173,7 @@ class Dispatchers(val settings: ActorSystem.Settings, val prerequisites: Dispatc
settings.DispatcherThroughputDeadlineTime, MailboxType, config, settings.DispatcherDefaultShutdown), ThreadPoolConfig())
/**
* Creates a executor-based event-driven dispatcher, with work-stealing, serving multiple (millions) of actors through a thread pool.
* Creates a executor-based event-driven dispatcher, with work-sharing, serving multiple (millions) of actors through a thread pool.
* <p/>
* Has a fluent builder interface for configuring its semantics.
*/
@ -154,7 +183,7 @@ class Dispatchers(val settings: ActorSystem.Settings, val prerequisites: Dispatc
config, settings.DispatcherDefaultShutdown), ThreadPoolConfig())
/**
* Creates a executor-based event-driven dispatcher, with work-stealing, serving multiple (millions) of actors through a thread pool.
* Creates a executor-based event-driven dispatcher, with work-sharing, serving multiple (millions) of actors through a thread pool.
* <p/>
* Has a fluent builder interface for configuring its semantics.
*/
@ -164,7 +193,7 @@ class Dispatchers(val settings: ActorSystem.Settings, val prerequisites: Dispatc
config, settings.DispatcherDefaultShutdown), ThreadPoolConfig())
/**
* Creates a executor-based event-driven dispatcher, with work-stealing, serving multiple (millions) of actors through a thread pool.
* Creates a executor-based event-driven dispatcher, with work-sharing, serving multiple (millions) of actors through a thread pool.
* <p/>
* Has a fluent builder interface for configuring its semantics.
*/
@ -172,13 +201,13 @@ class Dispatchers(val settings: ActorSystem.Settings, val prerequisites: Dispatc
ThreadPoolConfigDispatcherBuilder(config
new BalancingDispatcher(prerequisites, name, throughput, throughputDeadline, mailboxType,
config, settings.DispatcherDefaultShutdown), ThreadPoolConfig())
/**
* Utility function that tries to load the specified dispatcher config from the akka.conf
* Creates a new dispatcher as specified in configuration
* or if not defined it uses the supplied dispatcher.
* Uses default values from default-dispatcher, i.e. all options doesn't need to be defined
* in config.
* Uses default values from default-dispatcher, i.e. all options doesn't need to be defined.
*/
def fromConfig(key: String, default: MessageDispatcher = defaultGlobalDispatcher, cfg: Config = settings.config): MessageDispatcher = {
def newFromConfig(key: String, default: MessageDispatcher, cfg: Config): MessageDispatcher = {
import scala.collection.JavaConverters._
def simpleName = key.substring(key.lastIndexOf('.') + 1)
cfg.hasPath(key) match {
@ -186,10 +215,18 @@ class Dispatchers(val settings: ActorSystem.Settings, val prerequisites: Dispatc
case true
val conf = cfg.getConfig(key)
val confWithName = conf.withFallback(ConfigFactory.parseMap(Map("name" -> simpleName).asJava))
from(confWithName).getOrElse(default)
from(confWithName).getOrElse(throw new ConfigurationException("Wrong configuration [%s]".format(key)))
}
}
/**
* Creates a new dispatcher as specified in configuration, or if not defined it uses
* the default dispatcher.
* Uses default configuration values from default-dispatcher, i.e. all options doesn't
* need to be defined.
*/
def newFromConfig(key: String): MessageDispatcher = newFromConfig(key, defaultGlobalDispatcher, settings.config)
/*
* Creates of obtains a dispatcher from a ConfigMap according to the format below.
* Uses default values from default-dispatcher.

View file

@ -33,9 +33,6 @@ object Mailbox {
final val debug = false
}
/**
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
abstract class Mailbox(val actor: ActorCell) extends MessageQueue with SystemMessageQueue with Runnable {
import Mailbox._
@ -209,8 +206,29 @@ abstract class Mailbox(val actor: ActorCell) extends MessageQueue with SystemMes
/**
* Overridable callback to clean up the mailbox,
* called when an actor is unregistered.
* By default it dequeues all system messages + messages and ships them to the owning actors' systems' DeadLetterMailbox
*/
protected[dispatch] def cleanUp() {}
protected[dispatch] def cleanUp(): Unit = if (actor ne null) {
val dlq = actor.systemImpl.deadLetterMailbox
if (hasSystemMessages) {
var message = systemDrain()
while (message ne null) {
// message must be virgin before being able to systemEnqueue again
val next = message.next
message.next = null
dlq.systemEnqueue(actor.self, message)
message = next
}
}
if (hasMessages) {
var envelope = dequeue
while (envelope ne null) {
dlq.enqueue(actor.self, envelope)
envelope = dequeue
}
}
}
}
trait MessageQueue {

View file

@ -14,8 +14,6 @@ import java.util.concurrent.TimeUnit
/**
* Dedicates a unique thread for each actor passed in as reference. Served through its messageQueue.
*
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
class PinnedDispatcher(
_prerequisites: DispatcherPrerequisites,
@ -32,7 +30,7 @@ class PinnedDispatcher(
_shutdownTimeout) {
@volatile
protected[akka] var owner: ActorCell = _actor
private var owner: ActorCell = _actor
//Relies on an external lock provided by MessageDispatcher.attach
protected[akka] override def register(actorCell: ActorCell) = {

View file

@ -144,9 +144,6 @@ case class ThreadPoolConfigDispatcherBuilder(dispatcherFactory: (ThreadPoolConfi
def configure(fs: Option[Function[ThreadPoolConfigDispatcherBuilder, ThreadPoolConfigDispatcherBuilder]]*): ThreadPoolConfigDispatcherBuilder = fs.foldLeft(this)((c, f) f.map(_(c)).getOrElse(c))
}
/**
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
class MonitorableThreadFactory(val name: String, val daemonic: Boolean = false) extends ThreadFactory {
protected val counter = new AtomicLong
@ -157,9 +154,6 @@ class MonitorableThreadFactory(val name: String, val daemonic: Boolean = false)
}
}
/**
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
object MonitorableThread {
val DEFAULT_NAME = "MonitorableThread".intern
@ -168,9 +162,6 @@ object MonitorableThread {
val alive = new AtomicInteger
}
/**
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
class MonitorableThread(runnable: Runnable, name: String)
extends Thread(runnable, name + "-" + MonitorableThread.created.incrementAndGet) {

View file

@ -281,19 +281,34 @@ object Logging {
val debugFormat = "[DEBUG] [%s] [%s] [%s] %s".intern
/**
* Obtain LoggingAdapter for the given application and source object. The
* source is used to identify the source of this logging channel and must have
* Obtain LoggingAdapter for the given event stream (system) and source object.
* Note that there is an implicit conversion from [[akka.actor.ActorSystem]]
* to [[akka.event.LoggingBus]].
*
* The source is used to identify the source of this logging channel and must have
* a corresponding LogSource[T] instance in scope; by default these are
* provided for Class[_], Actor, ActorRef and String types.
* provided for Class[_], Actor, ActorRef and String types. The source
* object is translated to a String according to the following rules:
* <ul>
* <li>if it is an Actor or ActorRef, its path is used</li>
* <li>in case of a String it is used as is</li>
* <li>in case of a class an approximation of its simpleName
* <li>and in all other cases the simpleName of its class</li>
* </ul>
*/
def apply[T: LogSource](eventStream: LoggingBus, logSource: T): LoggingAdapter =
new BusLogging(eventStream, implicitly[LogSource[T]].genString(logSource))
/**
* Java API: Obtain LoggingAdapter for the given application and source object. The
* source object is used to identify the source of this logging channel; if it is
* an Actor or ActorRef, its address is used, in case of a class an approximation of
* its simpleName and in all other cases the simpleName of its class.
* Java API: Obtain LoggingAdapter for the given system and source object. The
* source object is used to identify the source of this logging channel. The source
* object is translated to a String according to the following rules:
* <ul>
* <li>if it is an Actor or ActorRef, its path is used</li>
* <li>in case of a String it is used as is</li>
* <li>in case of a class an approximation of its simpleName
* <li>and in all other cases the simpleName of its class</li>
* </ul>
*/
def getLogger(system: ActorSystem, logSource: AnyRef): LoggingAdapter = apply(system.eventStream, LogSource.fromAnyRef(logSource))
@ -354,6 +369,11 @@ object Logging {
*/
case object LoggerInitialized
/**
* Java API to create a LoggerInitialized message.
*/
def loggerInitialized() = LoggerInitialized
class LoggerInitializationException(msg: String) extends AkkaException(msg)
trait StdOutLogger {

View file

@ -10,7 +10,6 @@ import annotation.target._
* This annotation marks a feature which is not yet considered stable and may
* change or be removed in a future release.
*
* @author Roland Kuhn
* @since 1.2
*/
@getter

View file

@ -24,8 +24,6 @@ trait VersionedIterable[A] {
/**
* Manages connections (ActorRefs) for a router.
*
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
trait ConnectionManager {
/**

View file

@ -15,8 +15,6 @@ import scala.collection.mutable.{ Buffer, Map }
* Consistent Hashing node ring abstraction.
*
* Not thread-safe, to be used from within an Actor or protected some other way.
*
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
class ConsistentHash[T](nodes: Seq[T], replicas: Int) {
private val cluster = Buffer[T]()

View file

@ -7,7 +7,6 @@ package akka.serialization
import akka.actor.Actor
/**
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
* trait Serializer extends scala.Serializable {
* @volatile
* var classLoader: Option[ClassLoader] = None

View file

@ -4,9 +4,6 @@
package akka.util
/**
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
object Convert {
def intToBytes(value: Int): Array[Byte] = {

View file

@ -6,9 +6,6 @@ package akka.util
import java.security.{ MessageDigest, SecureRandom }
/**
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
object Crypt {
val hex = "0123456789ABCDEF"
val lineSeparator = System.getProperty("line.separator")

View file

@ -38,7 +38,19 @@ case class Timer(duration: Duration, throwExceptionOnTimeout: Boolean = false) {
}
}
case class Deadline(d: Duration) {
def +(other: Duration): Deadline = copy(d = d + other)
def -(other: Duration): Deadline = copy(d = d - other)
def -(other: Deadline): Duration = d - other.d
def timeLeft: Duration = this - Deadline.now
}
object Deadline {
def now: Deadline = Deadline(Duration(System.nanoTime, NANOSECONDS))
}
object Duration {
implicit def timeLeft(implicit d: Deadline): Duration = d.timeLeft
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))
@ -129,10 +141,7 @@ object Duration {
override def *(factor: Double): Duration = throw new IllegalArgumentException("cannot multiply Undefined duration")
override def /(factor: Double): Duration = throw new IllegalArgumentException("cannot divide Undefined duration")
override def /(other: Duration): Double = throw new IllegalArgumentException("cannot divide Undefined duration")
def >(other: Duration) = throw new IllegalArgumentException("cannot compare Undefined duration")
def >=(other: Duration) = throw new IllegalArgumentException("cannot compare Undefined duration")
def <(other: Duration) = throw new IllegalArgumentException("cannot compare Undefined duration")
def <=(other: Duration) = throw new IllegalArgumentException("cannot compare Undefined duration")
def compare(other: Duration) = throw new IllegalArgumentException("cannot compare Undefined duration")
def unary_- : Duration = throw new IllegalArgumentException("cannot negate Undefined duration")
}
@ -183,10 +192,7 @@ object Duration {
*/
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 compare(other: Duration) = 1
def unary_- : Duration = MinusInf
}
@ -196,10 +202,7 @@ object Duration {
*/
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 compare(other: Duration) = -1
def unary_- : Duration = Inf
}
@ -255,7 +258,7 @@ object Duration {
* val d3 = d2 + 1.millisecond
* </pre>
*/
abstract class Duration extends Serializable {
abstract class Duration extends Serializable with Ordered[Duration] {
def length: Long
def unit: TimeUnit
def toNanos: Long
@ -267,10 +270,6 @@ abstract class Duration extends Serializable {
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
@ -281,6 +280,7 @@ abstract class Duration extends Serializable {
def min(other: Duration): Duration = if (this < other) this else other
def max(other: Duration): Duration = if (this > other) this else other
def sleep(): Unit = Thread.sleep(toMillis)
def fromNow: Deadline = Deadline.now + this
// Java API
def lt(other: Duration) = this < other
@ -329,37 +329,12 @@ class FiniteDuration(val length: Long, val unit: TimeUnit) extends Duration {
def printHMS = "%02d:%02d:%06.3f".format(toHours, toMinutes % 60, toMillis / 1000. % 60)
def <(other: Duration) = {
def compare(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
}
}
val me = toNanos
val o = other.toNanos
if (me > o) 1 else if (me < o) -1 else 0
} else -other.compare(this)
def +(other: Duration) = {
if (!other.finite_?) {
@ -397,6 +372,8 @@ class FiniteDuration(val length: Long, val unit: TimeUnit) extends Duration {
}
class DurationInt(n: Int) {
import duration.Classifier
def nanoseconds = Duration(n, NANOSECONDS)
def nanos = Duration(n, NANOSECONDS)
def nanosecond = Duration(n, NANOSECONDS)
@ -423,9 +400,38 @@ class DurationInt(n: Int) {
def days = Duration(n, DAYS)
def day = Duration(n, DAYS)
def nanoseconds[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, NANOSECONDS))
def nanos[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, NANOSECONDS))
def nanosecond[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, NANOSECONDS))
def nano[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, NANOSECONDS))
def microseconds[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, MICROSECONDS))
def micros[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, MICROSECONDS))
def microsecond[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, MICROSECONDS))
def micro[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, MICROSECONDS))
def milliseconds[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, MILLISECONDS))
def millis[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, MILLISECONDS))
def millisecond[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, MILLISECONDS))
def milli[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, MILLISECONDS))
def seconds[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, SECONDS))
def second[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, SECONDS))
def minutes[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, MINUTES))
def minute[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, MINUTES))
def hours[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, HOURS))
def hour[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, HOURS))
def days[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, DAYS))
def day[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, DAYS))
}
class DurationLong(n: Long) {
import duration.Classifier
def nanoseconds = Duration(n, NANOSECONDS)
def nanos = Duration(n, NANOSECONDS)
def nanosecond = Duration(n, NANOSECONDS)
@ -452,9 +458,38 @@ class DurationLong(n: Long) {
def days = Duration(n, DAYS)
def day = Duration(n, DAYS)
def nanoseconds[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, NANOSECONDS))
def nanos[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, NANOSECONDS))
def nanosecond[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, NANOSECONDS))
def nano[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, NANOSECONDS))
def microseconds[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, MICROSECONDS))
def micros[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, MICROSECONDS))
def microsecond[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, MICROSECONDS))
def micro[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, MICROSECONDS))
def milliseconds[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, MILLISECONDS))
def millis[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, MILLISECONDS))
def millisecond[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, MILLISECONDS))
def milli[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, MILLISECONDS))
def seconds[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, SECONDS))
def second[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, SECONDS))
def minutes[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, MINUTES))
def minute[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, MINUTES))
def hours[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, HOURS))
def hour[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, HOURS))
def days[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, DAYS))
def day[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, DAYS))
}
class DurationDouble(d: Double) {
import duration.Classifier
def nanoseconds = Duration(d, NANOSECONDS)
def nanos = Duration(d, NANOSECONDS)
def nanosecond = Duration(d, NANOSECONDS)
@ -481,5 +516,32 @@ class DurationDouble(d: Double) {
def days = Duration(d, DAYS)
def day = Duration(d, DAYS)
def nanoseconds[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d, NANOSECONDS))
def nanos[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d, NANOSECONDS))
def nanosecond[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d, NANOSECONDS))
def nano[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d, NANOSECONDS))
def microseconds[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d, MICROSECONDS))
def micros[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d, MICROSECONDS))
def microsecond[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d, MICROSECONDS))
def micro[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d, MICROSECONDS))
def milliseconds[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d, MILLISECONDS))
def millis[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d, MILLISECONDS))
def millisecond[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d, MILLISECONDS))
def milli[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d, MILLISECONDS))
def seconds[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d, SECONDS))
def second[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d, SECONDS))
def minutes[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d, MINUTES))
def minute[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d, MINUTES))
def hours[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d, HOURS))
def hour[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d, HOURS))
def days[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d, DAYS))
def day[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d, DAYS))
}

View file

@ -21,8 +21,6 @@ import java.lang.{ Float ⇒ JFloat, Double ⇒ JDouble }
* result
* }
* </pre>
*
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
object HashCode {
val SEED = 23

View file

@ -8,9 +8,6 @@ import java.util.Comparator
import scala.annotation.tailrec
import java.util.regex.Pattern
/**
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
object Helpers {
def makePattern(s: String): Pattern = Pattern.compile("^\\Q" + s.replace("?", "\\E.\\Q").replace("*", "\\E.*\\Q") + "\\E$")

View file

@ -13,8 +13,6 @@ import scala.collection.mutable
* 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, V](val mapSize: Int, val valueComparator: Comparator[V]) {
@ -192,7 +190,5 @@ class Index[K, V](val mapSize: Int, val valueComparator: Comparator[V]) {
* An implementation of a ConcurrentMultiMap
* Adds/remove is serialized over the specified key
* Reads are fully concurrent <-- el-cheapo
*
* @author Viktor Klang
*/
class ConcurrentMultiMap[K, V](mapSize: Int, valueComparator: Comparator[V]) extends Index[K, V](mapSize, valueComparator)

View file

@ -9,9 +9,6 @@ import java.lang.management.ManagementFactory
import javax.management.{ ObjectInstance, ObjectName, InstanceAlreadyExistsException, InstanceNotFoundException }
import akka.actor.ActorSystem
/**
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
object JMX {
private val mbeanServer = ManagementFactory.getPlatformMBeanServer

View file

@ -9,8 +9,6 @@ import akka.actor.{ ActorInitializationException, ActorRef }
/**
* A manager for listener actors. Intended for mixin by observables.
*
* @author Martin Krasser
*/
trait ListenerManagement {

View file

@ -7,9 +7,6 @@ package akka.util
import java.util.concurrent.locks.{ ReentrantLock }
import java.util.concurrent.atomic.{ AtomicBoolean }
/**
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
final class ReentrantGuard {
final val lock = new ReentrantLock

View file

@ -7,6 +7,23 @@ package akka.util
import java.util.concurrent.TimeUnit
package object duration {
trait Classifier[C] {
type R
def convert(d: Duration): R
}
object span
implicit object spanConvert extends Classifier[span.type] {
type R = Duration
def convert(d: Duration) = d
}
object fromNow
implicit object fromNowConvert extends Classifier[fromNow.type] {
type R = Deadline
def convert(d: Duration) = Deadline.now + d
}
implicit def intToDurationInt(n: Int) = new DurationInt(n)
implicit def longToDurationLong(n: Long) = new DurationLong(n)
implicit def doubleToDurationDouble(d: Double) = new DurationDouble(d)

View file

@ -21,10 +21,10 @@ class TypedConsumerPublishRequestorTest extends JUnitSuite {
@Before
def setUp{
publisher = actorOf(new TypedConsumerPublisherMock)
requestor = actorOf(new TypedConsumerPublishRequestor)
publisher = actorOf(Props(new TypedConsumerPublisherMock)
requestor = actorOf(Props(new TypedConsumerPublishRequestor)
requestor ! InitPublishRequestor(publisher)
consumer = actorOf(new Actor with Consumer {
consumer = actorOf(Props(new Actor with Consumer {
def endpointUri = "mock:test"
protected def receive = null
})

View file

@ -18,10 +18,10 @@ class ConsumerPublishRequestorTest extends JUnitSuite {
@Before
def setUp{
publisher = actorOf(new ConsumerPublisherMock)
requestor = actorOf(new ConsumerPublishRequestor)
publisher = actorOf(Props(new ConsumerPublisherMock)
requestor = actorOf(Props(new ConsumerPublishRequestor)
requestor ! InitPublishRequestor(publisher)
consumer = actorOf(new Actor with Consumer {
consumer = actorOf(Props(new Actor with Consumer {
def endpointUri = "mock:test"
protected def receive = null
}).asInstanceOf[LocalActorRef]

View file

@ -9,21 +9,21 @@ class ConsumerRegisteredTest extends JUnitSuite {
@Test
def shouldCreateSomeNonBlockingPublishRequestFromConsumer = {
val c = Actor.actorOf[ConsumerActor1]
val c = Actor.actorOf(Props[ConsumerActor1]
val event = ConsumerActorRegistered.eventFor(c)
assert(event === Some(ConsumerActorRegistered(c, consumerOf(c))))
}
@Test
def shouldCreateSomeBlockingPublishRequestFromConsumer = {
val c = Actor.actorOf[ConsumerActor2]
val c = Actor.actorOf(Props[ConsumerActor2]
val event = ConsumerActorRegistered.eventFor(c)
assert(event === Some(ConsumerActorRegistered(c, consumerOf(c))))
}
@Test
def shouldCreateNoneFromConsumer = {
val event = ConsumerActorRegistered.eventFor(Actor.actorOf[PlainActor])
val event = ConsumerActorRegistered.eventFor(Actor.actorOf(Props[PlainActor])
assert(event === None)
}

View file

@ -27,7 +27,7 @@ class ConsumerScalaTest extends WordSpec with BeforeAndAfterAll with MustMatcher
service = CamelServiceFactory.createCamelService
// register test consumer before registering the publish requestor
// and before starting the CamelService (registry is scanned for consumers)
actorOf(new TestConsumer("direct:publish-test-1"))
actorOf(Props(new TestConsumer("direct:publish-test-1"))
service.registerPublishRequestor
service.awaitEndpointActivation(1) {
service.start
@ -54,7 +54,7 @@ class ConsumerScalaTest extends WordSpec with BeforeAndAfterAll with MustMatcher
"started" must {
"support an in-out message exchange via its endpoint" in {
service.awaitEndpointActivation(1) {
consumer = actorOf(new TestConsumer("direct:publish-test-2"))
consumer = actorOf(Props(new TestConsumer("direct:publish-test-2"))
} must be(true)
mandatoryTemplate.requestBody("direct:publish-test-2", "msg2") must equal("received msg2")
}
@ -119,7 +119,7 @@ class ConsumerScalaTest extends WordSpec with BeforeAndAfterAll with MustMatcher
"activated with a custom error handler" must {
"handle thrown exceptions by generating a custom response" in {
service.awaitEndpointActivation(1) {
actorOf[ErrorHandlingConsumer]
actorOf(Props[ErrorHandlingConsumer]
} must be(true)
mandatoryTemplate.requestBody("direct:error-handler-test", "hello") must equal("error: hello")
@ -128,7 +128,7 @@ class ConsumerScalaTest extends WordSpec with BeforeAndAfterAll with MustMatcher
"activated with a custom redelivery handler" must {
"handle thrown exceptions by redelivering the initial message" in {
service.awaitEndpointActivation(1) {
actorOf[RedeliveringConsumer]
actorOf(Props[RedeliveringConsumer]
} must be(true)
mandatoryTemplate.requestBody("direct:redelivery-test", "hello") must equal("accepted: hello")
@ -143,7 +143,7 @@ class ConsumerScalaTest extends WordSpec with BeforeAndAfterAll with MustMatcher
var consumer: ActorRef = null
service.awaitEndpointActivation(1) {
consumer = actorOf(new TestAckConsumer("direct:system-ack-test"))
consumer = actorOf(Props(new TestAckConsumer("direct:system-ack-test"))
} must be(true)
val endpoint = mandatoryContext.getEndpoint("direct:system-ack-test", classOf[DirectEndpoint])
@ -169,19 +169,19 @@ class ConsumerScalaTest extends WordSpec with BeforeAndAfterAll with MustMatcher
"A supervised consumer" must {
"be able to reply during receive" in {
val consumer = Actor.actorOf(new SupervisedConsumer("reply-channel-test-1"))
val consumer = Actor.actorOf(Props(new SupervisedConsumer("reply-channel-test-1"))
(consumer ? "succeed").get must equal("ok")
}
"be able to reply on failure during preRestart" in {
val consumer = Actor.actorOf(new SupervisedConsumer("reply-channel-test-2"))
val consumer = Actor.actorOf(Props(new SupervisedConsumer("reply-channel-test-2"))
val supervisor = Supervisor(
SupervisorConfig(
OneForOneStrategy(List(classOf[Exception]), 2, 10000),
Supervise(consumer, Permanent) :: Nil))
val latch = new CountDownLatch(1)
val sender = Actor.actorOf(new Sender("pr", latch))
val sender = Actor.actorOf(Props(new Sender("pr", latch))
consumer.!("fail")(Some(sender))
latch.await(5, TimeUnit.SECONDS) must be(true)
@ -195,7 +195,7 @@ class ConsumerScalaTest extends WordSpec with BeforeAndAfterAll with MustMatcher
Supervise(consumer, Temporary) :: Nil))
val latch = new CountDownLatch(1)
val sender = Actor.actorOf(new Sender("ps", latch))
val sender = Actor.actorOf(Props(new Sender("ps", latch))
consumer.!("fail")(Some(sender))
latch.await(5, TimeUnit.SECONDS) must be(true)

View file

@ -31,7 +31,7 @@ class ProducerFeatureTest extends FeatureSpec with BeforeAndAfterAll with Before
scenario("produce message and receive normal response") {
given("a registered two-way producer")
val producer = actorOf(new TestProducer("direct:producer-test-2", true))
val producer = actorOf(Props(new TestProducer("direct:producer-test-2", true))
when("a test message is sent to the producer with ?")
val message = Message("test", Map(Message.MessageExchangeId -> "123"))
@ -44,7 +44,7 @@ class ProducerFeatureTest extends FeatureSpec with BeforeAndAfterAll with Before
scenario("produce message and receive failure response") {
given("a registered two-way producer")
val producer = actorOf(new TestProducer("direct:producer-test-2"))
val producer = actorOf(Props(new TestProducer("direct:producer-test-2"))
when("a test message causing an exception is sent to the producer with ?")
val message = Message("fail", Map(Message.MessageExchangeId -> "123"))
@ -59,7 +59,7 @@ class ProducerFeatureTest extends FeatureSpec with BeforeAndAfterAll with Before
scenario("produce message oneway") {
given("a registered one-way producer")
val producer = actorOf(new TestProducer("direct:producer-test-1", true) with Oneway)
val producer = actorOf(Props(new TestProducer("direct:producer-test-1", true) with Oneway)
when("a test message is sent to the producer with !")
mockEndpoint.expectedBodiesReceived("TEST")
@ -71,7 +71,7 @@ class ProducerFeatureTest extends FeatureSpec with BeforeAndAfterAll with Before
scenario("produce message twoway without sender reference") {
given("a registered two-way producer")
val producer = actorOf(new TestProducer("direct:producer-test-1"))
val producer = actorOf(Props(new TestProducer("direct:producer-test-1"))
when("a test message is sent to the producer with !")
mockEndpoint.expectedBodiesReceived("test")
@ -86,7 +86,7 @@ class ProducerFeatureTest extends FeatureSpec with BeforeAndAfterAll with Before
scenario("produce message and receive normal response") {
given("a registered two-way producer")
val producer = actorOf(new TestProducer("direct:producer-test-3"))
val producer = actorOf(Props(new TestProducer("direct:producer-test-3"))
when("a test message is sent to the producer with ?")
val message = Message("test", Map(Message.MessageExchangeId -> "123"))
@ -98,7 +98,7 @@ class ProducerFeatureTest extends FeatureSpec with BeforeAndAfterAll with Before
scenario("produce message and receive failure response") {
given("a registered two-way producer")
val producer = actorOf(new TestProducer("direct:producer-test-3"))
val producer = actorOf(Props(new TestProducer("direct:producer-test-3"))
when("a test message causing an exception is sent to the producer with ?")
val message = Message("fail", Map(Message.MessageExchangeId -> "123"))
@ -116,8 +116,8 @@ class ProducerFeatureTest extends FeatureSpec with BeforeAndAfterAll with Before
scenario("produce message, forward normal response to a replying target actor and receive response") {
given("a registered two-way producer configured with a forward target")
val target = actorOf[ReplyingForwardTarget]
val producer = actorOf(new TestForwarder("direct:producer-test-2", target))
val target = actorOf(Props[ReplyingForwardTarget]
val producer = actorOf(Props(new TestForwarder("direct:producer-test-2", target))
when("a test message is sent to the producer with ?")
val message = Message("test", Map(Message.MessageExchangeId -> "123"))
@ -130,8 +130,8 @@ class ProducerFeatureTest extends FeatureSpec with BeforeAndAfterAll with Before
scenario("produce message, forward failure response to a replying target actor and receive response") {
given("a registered two-way producer configured with a forward target")
val target = actorOf[ReplyingForwardTarget]
val producer = actorOf(new TestForwarder("direct:producer-test-2", target))
val target = actorOf(Props[ReplyingForwardTarget]
val producer = actorOf(Props(new TestForwarder("direct:producer-test-2", target))
when("a test message causing an exception is sent to the producer with ?")
val message = Message("fail", Map(Message.MessageExchangeId -> "123"))
@ -146,8 +146,8 @@ class ProducerFeatureTest extends FeatureSpec with BeforeAndAfterAll with Before
scenario("produce message, forward normal response to a producing target actor and produce response to direct:forward-test-1") {
given("a registered one-way producer configured with a forward target")
val target = actorOf[ProducingForwardTarget]
val producer = actorOf(new TestForwarder("direct:producer-test-2", target))
val target = actorOf(Props[ProducingForwardTarget]
val producer = actorOf(Props(new TestForwarder("direct:producer-test-2", target))
when("a test message is sent to the producer with !")
mockEndpoint.expectedBodiesReceived("received test")
@ -159,8 +159,8 @@ class ProducerFeatureTest extends FeatureSpec with BeforeAndAfterAll with Before
scenario("produce message, forward failure response to a producing target actor and produce response to direct:forward-test-1") {
given("a registered one-way producer configured with a forward target")
val target = actorOf[ProducingForwardTarget]
val producer = actorOf(new TestForwarder("direct:producer-test-2", target))
val target = actorOf(Props[ProducingForwardTarget]
val producer = actorOf(Props(new TestForwarder("direct:producer-test-2", target))
when("a test message causing an exception is sent to the producer with !")
mockEndpoint.expectedMessageCount(1)
@ -176,8 +176,8 @@ class ProducerFeatureTest extends FeatureSpec with BeforeAndAfterAll with Before
scenario("produce message, forward normal response to a replying target actor and receive response") {
given("a registered two-way producer configured with a forward target")
val target = actorOf[ReplyingForwardTarget]
val producer = actorOf(new TestForwarder("direct:producer-test-3", target))
val target = actorOf(Props[ReplyingForwardTarget]
val producer = actorOf(Props(new TestForwarder("direct:producer-test-3", target))
when("a test message is sent to the producer with ?")
val message = Message("test", Map(Message.MessageExchangeId -> "123"))
@ -190,8 +190,8 @@ class ProducerFeatureTest extends FeatureSpec with BeforeAndAfterAll with Before
scenario("produce message, forward failure response to a replying target actor and receive response") {
given("a registered two-way producer configured with a forward target")
val target = actorOf[ReplyingForwardTarget]
val producer = actorOf(new TestForwarder("direct:producer-test-3", target))
val target = actorOf(Props[ReplyingForwardTarget]
val producer = actorOf(Props(new TestForwarder("direct:producer-test-3", target))
when("a test message causing an exception is sent to the producer with ?")
val message = Message("fail", Map(Message.MessageExchangeId -> "123"))
@ -206,8 +206,8 @@ class ProducerFeatureTest extends FeatureSpec with BeforeAndAfterAll with Before
scenario("produce message, forward normal response to a producing target actor and produce response to direct:forward-test-1") {
given("a registered one-way producer configured with a forward target")
val target = actorOf[ProducingForwardTarget]
val producer = actorOf(new TestForwarder("direct:producer-test-3", target))
val target = actorOf(Props[ProducingForwardTarget]
val producer = actorOf(Props(new TestForwarder("direct:producer-test-3", target))
when("a test message is sent to the producer with !")
mockEndpoint.expectedBodiesReceived("received test")
@ -219,8 +219,8 @@ class ProducerFeatureTest extends FeatureSpec with BeforeAndAfterAll with Before
scenario("produce message, forward failure response to a producing target actor and produce response to direct:forward-test-1") {
given("a registered one-way producer configured with a forward target")
val target = actorOf[ProducingForwardTarget]
val producer = actorOf(new TestForwarder("direct:producer-test-3", target))
val target = actorOf(Props[ProducingForwardTarget]
val producer = actorOf(Props(new TestForwarder("direct:producer-test-3", target))
when("a test message causing an exception is sent to the producer with !")
mockEndpoint.expectedMessageCount(1)
@ -271,7 +271,7 @@ object ProducerFeatureTest {
}
class TestRoute extends RouteBuilder {
val responder = actorOf[TestResponder]
val responder = actorOf(Props[TestResponder]
def configure {
from("direct:forward-test-1").to("mock:mock")
// for one-way messaging tests

View file

@ -33,7 +33,7 @@ class ActorComponentFeatureTest extends FeatureSpec with BeforeAndAfterAll with
import CamelContextManager.mandatoryTemplate
scenario("one-way communication") {
val actor = actorOf[Tester1]
val actor = actorOf(Props[Tester1]
val latch = (actor ? SetExpectedMessageCount(1)).as[CountDownLatch].get
mandatoryTemplate.sendBody("actor:uuid:%s" format actor.uuid, "Martin")
assert(latch.await(5000, TimeUnit.MILLISECONDS))
@ -42,7 +42,7 @@ class ActorComponentFeatureTest extends FeatureSpec with BeforeAndAfterAll with
}
scenario("two-way communication") {
val actor = actorOf[Tester2]
val actor = actorOf(Props[Tester2]
assert(mandatoryTemplate.requestBody("actor:uuid:%s" format actor.uuid, "Martin") === "Hello Martin")
}
@ -70,7 +70,7 @@ class ActorComponentFeatureTest extends FeatureSpec with BeforeAndAfterAll with
import CamelContextManager.mandatoryTemplate
scenario("one-way communication") {
val actor = actorOf[Tester1]
val actor = actorOf(Props[Tester1]
val latch = (actor ? SetExpectedMessageCount(1)).as[CountDownLatch].get
mandatoryTemplate.sendBody("actor:%s" format actor.address, "Martin")
assert(latch.await(5000, TimeUnit.MILLISECONDS))
@ -79,12 +79,12 @@ class ActorComponentFeatureTest extends FeatureSpec with BeforeAndAfterAll with
}
scenario("two-way communication") {
val actor = actorOf[Tester2]
val actor = actorOf(Props[Tester2]
assert(mandatoryTemplate.requestBody("actor:%s" format actor.address, "Martin") === "Hello Martin")
}
scenario("two-way communication via a custom route") {
val actor = actorOf[CustomIdActor]("custom-id")
val actor = actorOf(Props[CustomIdActor]("custom-id")
assert(mandatoryTemplate.requestBody("direct:custom-id-test-1", "Martin") === "Received Martin")
assert(mandatoryTemplate.requestBody("direct:custom-id-test-2", "Martin") === "Received Martin")
}
@ -113,8 +113,8 @@ object ActorComponentFeatureTest {
}
class TestRoute extends RouteBuilder {
val failWithMessage = actorOf[FailWithMessage]
val failWithException = actorOf[FailWithException]
val failWithMessage = actorOf(Props[FailWithMessage]
val failWithException = actorOf(Props[FailWithException]
def configure {
from("direct:custom-id-test-1").to("actor:custom-id")
from("direct:custom-id-test-2").to("actor:id:custom-id")

View file

@ -23,7 +23,7 @@ class ActorProducerTest extends JUnitSuite with BeforeAndAfterAll {
@Test
def shouldSendMessageToActorWithSyncProcessor = {
val actor = actorOf[Tester1]
val actor = actorOf(Props[Tester1]
val latch = (actor ? SetExpectedMessageCount(1)).as[CountDownLatch].get
val endpoint = actorEndpoint("actor:uuid:%s" format actor.uuid)
val exchange = endpoint.createExchange(ExchangePattern.InOnly)
@ -38,7 +38,7 @@ class ActorProducerTest extends JUnitSuite with BeforeAndAfterAll {
@Test
def shouldSendMessageToActorWithAsyncProcessor = {
val actor = actorOf[Tester1]
val actor = actorOf(Props[Tester1]
val latch = (actor ? SetExpectedMessageCount(1)).as[CountDownLatch].get
val endpoint = actorEndpoint("actor:uuid:%s" format actor.uuid)
val exchange = endpoint.createExchange(ExchangePattern.InOnly)
@ -53,7 +53,7 @@ class ActorProducerTest extends JUnitSuite with BeforeAndAfterAll {
@Test
def shouldSendMessageToActorAndReceiveResponseWithSyncProcessor = {
val actor = actorOf(new Tester2 {
val actor = actorOf(Props(new Tester2 {
override def response(msg: Message) = Message(super.response(msg), Map("k2" -> "v2"))
})
val endpoint = actorEndpoint("actor:uuid:%s" format actor.uuid)
@ -67,7 +67,7 @@ class ActorProducerTest extends JUnitSuite with BeforeAndAfterAll {
@Test
def shouldSendMessageToActorAndReceiveResponseWithAsyncProcessor = {
val actor = actorOf(new Tester2 {
val actor = actorOf(Props(new Tester2 {
override def response(msg: Message) = Message(super.response(msg), Map("k2" -> "v2"))
})
val completion = expectAsyncCompletion
@ -83,7 +83,7 @@ class ActorProducerTest extends JUnitSuite with BeforeAndAfterAll {
@Test
def shouldSendMessageToActorAndReceiveFailureWithAsyncProcessor = {
val actor = actorOf(new Tester2 {
val actor = actorOf(Props(new Tester2 {
override def response(msg: Message) = Failure(new Exception("testmsg"), Map("k3" -> "v3"))
})
val completion = expectAsyncCompletion
@ -100,7 +100,7 @@ class ActorProducerTest extends JUnitSuite with BeforeAndAfterAll {
@Test
def shouldSendMessageToActorAndReceiveAckWithAsyncProcessor = {
val actor = actorOf(new Tester2 {
val actor = actorOf(Props(new Tester2 {
override def response(msg: Message) = akka.camel.Ack
})
val completion = expectAsyncCompletion
@ -115,8 +115,8 @@ class ActorProducerTest extends JUnitSuite with BeforeAndAfterAll {
@Test
def shouldDynamicallyRouteMessageToActorWithDefaultId = {
val actor1 = actorOf[Tester1]("x")
val actor2 = actorOf[Tester1]("y")
val actor1 = actorOf(Props[Tester1]("x")
val actor2 = actorOf(Props[Tester1]("y")
actor1
actor2
val latch1 = (actor1 ? SetExpectedMessageCount(1)).as[CountDownLatch].get
@ -139,8 +139,8 @@ class ActorProducerTest extends JUnitSuite with BeforeAndAfterAll {
@Test
def shouldDynamicallyRouteMessageToActorWithoutDefaultId = {
val actor1 = actorOf[Tester1]("x")
val actor2 = actorOf[Tester1]("y")
val actor1 = actorOf(Props[Tester1]("x")
val actor2 = actorOf(Props[Tester1]("y")
actor1
actor2
val latch1 = (actor1 ? SetExpectedMessageCount(1)).as[CountDownLatch].get
@ -164,8 +164,8 @@ class ActorProducerTest extends JUnitSuite with BeforeAndAfterAll {
@Test
def shouldDynamicallyRouteMessageToActorWithDefaultUuid = {
val actor1 = actorOf[Tester1]
val actor2 = actorOf[Tester1]
val actor1 = actorOf(Props[Tester1]
val actor2 = actorOf(Props[Tester1]
val latch1 = (actor1 ? SetExpectedMessageCount(1)).as[CountDownLatch].get
val latch2 = (actor2 ? SetExpectedMessageCount(1)).as[CountDownLatch].get
val endpoint = actorEndpoint("actor:uuid:%s" format actor1.uuid)
@ -186,8 +186,8 @@ class ActorProducerTest extends JUnitSuite with BeforeAndAfterAll {
@Test
def shouldDynamicallyRouteMessageToActorWithoutDefaultUuid = {
val actor1 = actorOf[Tester1]
val actor2 = actorOf[Tester1]
val actor1 = actorOf(Props[Tester1]
val actor2 = actorOf(Props[Tester1]
val latch1 = (actor1 ? SetExpectedMessageCount(1)).as[CountDownLatch].get
val latch2 = (actor2 ? SetExpectedMessageCount(1)).as[CountDownLatch].get
val endpoint = actorEndpoint("actor:uuid:")
@ -209,7 +209,7 @@ class ActorProducerTest extends JUnitSuite with BeforeAndAfterAll {
@Test
def shouldThrowExceptionWhenIdNotSet{
val actor = actorOf[Tester1]
val actor = actorOf(Props[Tester1]
val latch = (actor ? SetExpectedMessageCount(1)).as[CountDownLatch].get
val endpoint = actorEndpoint("actor:id:")
intercept[ActorIdentifierNotSetException] {
@ -219,7 +219,7 @@ class ActorProducerTest extends JUnitSuite with BeforeAndAfterAll {
@Test
def shouldThrowExceptionWhenUuidNotSet{
val actor = actorOf[Tester1]
val actor = actorOf(Props[Tester1]
val latch = (actor ? SetExpectedMessageCount(1)).as[CountDownLatch].get
val endpoint = actorEndpoint("actor:uuid:")
intercept[ActorIdentifierNotSetException] {

View file

@ -21,9 +21,6 @@ entry number it will use MAX_INTEGER). Once all the entries have been processed,
new one for its use.
*/
/**
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
object BookKeeperServer {
val port = 3181
val zkServers = "localhost:2181"

View file

@ -57,8 +57,6 @@ import com.google.protobuf.ByteString
/**
* JMX MBean for the cluster service.
*
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
trait ClusterNodeMBean {
@ -140,8 +138,6 @@ trait ClusterNodeMBean {
/**
* Module for the Cluster. Also holds global state such as configuration data etc.
*
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
object Cluster {
val EMPTY_STRING = "".intern
@ -257,8 +253,6 @@ object Cluster {
*
* /clusterName/'actor-address-to-uuids'/actorAddress/actorUuid
* </pre>
*
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
class DefaultClusterNode private[akka] (
val nodeAddress: NodeAddress,
@ -1601,9 +1595,6 @@ class DefaultClusterNode private[akka] (
}
}
/**
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
class MembershipChildListener(self: ClusterNode) extends IZkChildListener with ErrorHandler {
def handleChildChange(parentPath: String, currentChilds: JList[String]) {
withErrorHandler {
@ -1643,9 +1634,6 @@ class MembershipChildListener(self: ClusterNode) extends IZkChildListener with E
}
}
/**
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
class StateListener(self: ClusterNode) extends IZkStateListener {
def handleStateChanged(state: KeeperState) {
state match {
@ -1671,9 +1659,6 @@ class StateListener(self: ClusterNode) extends IZkStateListener {
}
}
/**
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
trait ErrorHandler {
def withErrorHandler[T](body: T) = {
try {
@ -1686,9 +1671,6 @@ trait ErrorHandler {
}
}
/**
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
object RemoteClusterDaemon {
val Address = "akka-cluster-daemon".intern
@ -1700,8 +1682,6 @@ object RemoteClusterDaemon {
* Internal "daemon" actor for cluster internal communication.
*
* It acts as the brain of the cluster that responds to cluster events (messages) and undertakes action.
*
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
class RemoteClusterDaemon(cluster: ClusterNode) extends Actor {

View file

@ -21,8 +21,6 @@ import annotation.tailrec
/**
* ClusterActorRef factory and locator.
*
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
object ClusterActorRef {
import FailureDetectorType._
@ -77,8 +75,6 @@ object ClusterActorRef {
/**
* ActorRef representing a one or many instances of a clustered, load-balanced and sometimes replicated actor
* where the instances can reside on other nodes in the cluster.
*
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
private[akka] class ClusterActorRef(props: RoutedProps, val address: String) extends AbstractRoutedActorRef(props) {

View file

@ -24,10 +24,6 @@ import java.util.concurrent.{ CountDownLatch, TimeUnit }
/**
* A ClusterDeployer is responsible for deploying a Deploy.
*
* FIXME Document: what does Deploy mean?
*
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
object ClusterDeployer extends ActorDeployer {
val clusterName = Cluster.name

View file

@ -26,19 +26,12 @@ import java.util.Enumeration
// FIXME allow user to choose dynamically between 'async' and 'sync' tx logging (asyncAddEntry(byte[] data, AddCallback cb, Object ctx))
// FIXME clean up old entries in log after doing a snapshot
/**
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
class ReplicationException(message: String, cause: Throwable = null) extends AkkaException(message) {
def this(msg: String) = this(msg, null)
}
/**
* TODO: Explain something about threadsafety.
*
* A TransactionLog makes chunks of data durable.
*
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
class TransactionLog private (
ledger: LedgerHandle,
@ -352,7 +345,7 @@ class TransactionLog private (
}
/**
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
* TODO: Documentation.
*/
object TransactionLog {
@ -563,8 +556,6 @@ object TransactionLog {
/**
* TODO: Documentation.
*
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
object LocalBookKeeperEnsemble {
private val isRunning = new Switch(false)

View file

@ -37,7 +37,7 @@ class ClusterActorRefCleanupMultiJvmNode1 extends MasterClusterTestNode {
Cluster.node.start()
barrier("awaitStarted", NrOfNodes).await()
val ref = Actor.actorOf[ClusterActorRefCleanupMultiJvmSpec.TestActor]("service-test")
val ref = Actor.actorOf(Props[ClusterActorRefCleanupMultiJvmSpec.TestActor]("service-test")
ref.isInstanceOf[ClusterActorRef] must be(true)

View file

@ -42,7 +42,7 @@
// }
// barrier("create-actor-on-node1", NrOfNodes) {
// val actorRef = Actor.actorOf[HelloWorld]("hello-world-write-behind-nosnapshot")
// val actorRef = Actor.actorOf(Props[HelloWorld]("hello-world-write-behind-nosnapshot")
// // node.isInUseOnNode("hello-world") must be(true)
// actorRef.address must be("hello-world-write-behind-nosnapshot")
// for (i 0 until 10) {

View file

@ -44,7 +44,7 @@
// }
// barrier("create-actor-on-node1", NrOfNodes) {
// val actorRef = Actor.actorOf[HelloWorld]("hello-world-write-behind-snapshot")
// val actorRef = Actor.actorOf(Props[HelloWorld]("hello-world-write-behind-snapshot")
// node.isInUseOnNode("hello-world-write-behind-snapshot") must be(true)
// actorRef.address must be("hello-world-write-behind-snapshot")
// var counter = 0

View file

@ -44,7 +44,7 @@
// }
// barrier("create-actor-on-node1", NrOfNodes) {
// val actorRef = Actor.actorOf[HelloWorld]("hello-world-write-through-nosnapshot")
// val actorRef = Actor.actorOf(Props[HelloWorld]("hello-world-write-through-nosnapshot")
// actorRef.address must be("hello-world-write-through-nosnapshot")
// for (i 0 until 10)
// (actorRef ? Count(i)).as[String] must be(Some("World from node [node1]"))

View file

@ -42,7 +42,7 @@
// }
// barrier("create-actor-on-node1", NrOfNodes) {
// val actorRef = Actor.actorOf[HelloWorld]("hello-world-write-through-snapshot")
// val actorRef = Actor.actorOf(Props[HelloWorld]("hello-world-write-through-snapshot")
// node.isInUseOnNode("hello-world-write-through-snapshot") must be(true)
// actorRef.address must be("hello-world-write-through-snapshot")
// var counter = 0

View file

@ -44,7 +44,7 @@ class DirectRoutingFailoverMultiJvmNode1 extends MasterClusterTestNode {
}
LocalCluster.barrier("actor-creation", NrOfNodes) {
actor = Actor.actorOf[SomeActor]("service-hello")
actor = Actor.actorOf(Props[SomeActor]("service-hello")
}
LocalCluster.barrier("verify-actor", NrOfNodes) {

View file

@ -45,11 +45,11 @@ class HomeNodeMultiJvmNode2 extends ClusterTestNode {
Cluster.node.start()
barrier("waiting-for-begin", NrOfNodes).await()
val actorNode1 = Actor.actorOf[SomeActor]("service-node1")
val actorNode1 = Actor.actorOf(Props[SomeActor]("service-node1")
val name1 = (actorNode1 ? "identify").get.asInstanceOf[String]
name1 must equal("node1")
val actorNode2 = Actor.actorOf[SomeActor]("service-node2")
val actorNode2 = Actor.actorOf(Props[SomeActor]("service-node2")
val name2 = (actorNode2 ? "identify").get.asInstanceOf[String]
name2 must equal("node2")

Some files were not shown because too many files have changed in this diff Show more