fix some warts in IO

- remove TcpPipelineHandler’s type parameter
- remove not-accept() failure test (which is completely bogus)
- add comments explaining more about TcpPipelineHandler.Init
- remove the funny “manager” from the Server example
This commit is contained in:
Roland 2013-05-08 18:10:49 +02:00
parent f3f55d4972
commit 025a91ecc2
5 changed files with 30 additions and 36 deletions

View file

@ -483,28 +483,6 @@ class TcpConnectionSpec extends AkkaSpec("akka.io.tcp.register-timeout = 500ms")
} }
} }
// This test is disabled on windows, as the assumption that not calling accept on a server socket means that
// no TCP level connection has been established with the client does not hold.
// RK: I think Windows is no different than any other OS in this regard, there was just a sleep() missing.
"report failed connection attempt while not accepted" in new UnacceptedConnectionTest {
run {
ignoreIfWindows()
// close instead of accept
localServerChannel.close()
// must give the OS some time to send RST from server to client
Thread.sleep(100)
EventFilter[SocketException](occurrences = 1) intercept {
selector.send(connectionActor, ChannelConnectable)
userHandler.expectMsg(CommandFailed(Connect(serverAddress)))
}
verifyActorTermination(connectionActor)
}
}
val UnboundAddress = temporaryServerAddress() val UnboundAddress = temporaryServerAddress()
"report failed connection attempt when target is unreachable" in "report failed connection attempt when target is unreachable" in

View file

@ -134,9 +134,9 @@ class TcpPipelineHandler[Ctx <: PipelineContext, Cmd, Evt](
* that are not Receive events will be passed directly to the handler registered for TcpPipelineHandler. * that are not Receive events will be passed directly to the handler registered for TcpPipelineHandler.
* @tparam Ctx * @tparam Ctx
*/ */
class TcpReadWriteAdapter[Ctx <: PipelineContext] extends PipelineStage[Ctx, ByteString, Tcp.Command, ByteString, Tcp.Event] { class TcpReadWriteAdapter extends PipelineStage[PipelineContext, ByteString, Tcp.Command, ByteString, Tcp.Event] {
override def apply(ctx: Ctx) = new PipePair[ByteString, Tcp.Command, ByteString, Tcp.Event] { override def apply(ctx: PipelineContext) = new PipePair[ByteString, Tcp.Command, ByteString, Tcp.Event] {
override val commandPipeline = { override val commandPipeline = {
data: ByteString ctx.singleCommand(Tcp.Write(data)) data: ByteString ctx.singleCommand(Tcp.Write(data))

View file

@ -26,11 +26,7 @@ class DemoActor extends Actor {
} }
//#server //#server
object Server { class Server extends Actor {
def apply(manager: ActorRef) = Props(classOf[Server], manager)
}
class Server(manager: ActorRef) extends Actor {
import Tcp._ import Tcp._
import context.system import context.system
@ -38,12 +34,17 @@ class Server(manager: ActorRef) extends Actor {
IO(Tcp) ! Bind(self, new InetSocketAddress("localhost", 0)) IO(Tcp) ! Bind(self, new InetSocketAddress("localhost", 0))
def receive = { def receive = {
case b @ Bound(localAddress) manager ! b case b @ Bound(localAddress)
//#do-some-logging-or-setup
context.parent ! b
//#do-some-logging-or-setup
case CommandFailed(_: Bind) context stop self case CommandFailed(_: Bind) context stop self
case c @ Connected(remote, local) case c @ Connected(remote, local)
manager ! c //#server
context.parent ! c
//#server
val handler = context.actorOf(Props[SimplisticHandler]) val handler = context.actorOf(Props[SimplisticHandler])
val connection = sender val connection = sender
connection ! Register(handler) connection ! Register(handler)
@ -97,8 +98,15 @@ class Client(remote: InetSocketAddress, listener: ActorRef) extends Actor {
class IODocSpec extends AkkaSpec { class IODocSpec extends AkkaSpec {
class Parent extends Actor {
context.actorOf(Props[Server], "server")
def receive = {
case msg testActor forward msg
}
}
"demonstrate connect" in { "demonstrate connect" in {
val server = system.actorOf(Server(testActor), "server1") val server = system.actorOf(Props(classOf[Parent], this), "parent")
val listen = expectMsgType[Tcp.Bound].localAddress val listen = expectMsgType[Tcp.Bound].localAddress
val client = system.actorOf(Client(listen, testActor), "client1") val client = system.actorOf(Client(listen, testActor), "client1")

View file

@ -427,6 +427,7 @@ Accepting connections
^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^
.. includecode:: code/docs/io/IODocSpec.scala#server .. includecode:: code/docs/io/IODocSpec.scala#server
:exclude: do-some-logging-or-setup
To create a TCP server and listen for inbound connections, a :class:`Bind` To create a TCP server and listen for inbound connections, a :class:`Bind`
command has to be sent to the TCP manager. This will instruct the TCP manager command has to be sent to the TCP manager. This will instruct the TCP manager

View file

@ -102,7 +102,7 @@ class SslTlsSupportSpec extends AkkaSpec {
val init = new TcpPipelineHandler.Init( val init = new TcpPipelineHandler.Init(
new StringByteStringAdapter >> new StringByteStringAdapter >>
new DelimiterFraming(maxSize = 1024, delimiter = ByteString('\n'), includeDelimiter = true) >> new DelimiterFraming(maxSize = 1024, delimiter = ByteString('\n'), includeDelimiter = true) >>
new TcpReadWriteAdapter[HasLogging] >> new TcpReadWriteAdapter >>
new SslTlsSupport(sslEngine(connected.remoteAddress, client = true))) { new SslTlsSupport(sslEngine(connected.remoteAddress, client = true))) {
override def makeContext(actorContext: ActorContext): HasLogging = new HasLogging { override def makeContext(actorContext: ActorContext): HasLogging = new HasLogging {
override def getLogger = system.log override def getLogger = system.log
@ -148,9 +148,16 @@ class SslTlsSupportSpec extends AkkaSpec {
val init = val init =
new TcpPipelineHandler.Init( new TcpPipelineHandler.Init(
new StringByteStringAdapter >> new StringByteStringAdapter >>
new DelimiterFraming(maxSize = 1024, delimiter = ByteString('\n'), includeDelimiter = true) >> new DelimiterFraming(maxSize = 1024, delimiter = ByteString('\n'),
new TcpReadWriteAdapter[HasLogging] >> includeDelimiter = true) >>
new TcpReadWriteAdapter >>
new SslTlsSupport(sslEngine(remote, client = false))) { new SslTlsSupport(sslEngine(remote, client = false))) {
/*
* When creating an `Init` the abstract `makeContext` method needs to be
* implemented. If the type of the returned context does not satisfy the
* requirements of all pipeline stages, then youll get an error that
* `makeContext` has an incompatible type.
*/
override def makeContext(actorContext: ActorContext): HasLogging = override def makeContext(actorContext: ActorContext): HasLogging =
new HasLogging { new HasLogging {
override def getLogger = log override def getLogger = log