Merge pull request #1321 from spray/wip-IO-WriteFile-rebased

Tcp: introduce WriteFile to support zero-copy writing of files, fixes #2896
This commit is contained in:
Roland Kuhn 2013-04-17 04:39:41 -07:00
commit cdf717e855
4 changed files with 208 additions and 59 deletions

View file

@ -4,8 +4,8 @@
package akka.io
import java.io.IOException
import java.net.{ ConnectException, InetSocketAddress, SocketException }
import java.io.{ FileOutputStream, File, IOException }
import java.net.{ URLClassLoader, ConnectException, InetSocketAddress, SocketException }
import java.nio.ByteBuffer
import java.nio.channels.{ SelectionKey, Selector, ServerSocketChannel, SocketChannel }
import java.nio.channels.spi.SelectorProvider
@ -190,6 +190,29 @@ class TcpConnectionSpec extends AkkaSpec("akka.io.tcp.register-timeout = 500ms")
writer.expectMsg(Ack)
}
"write file to network" in withEstablishedConnection() { setup
import setup._
// hacky: we need a file for testing purposes, so try to get the biggest one from our own classpath
val testFile =
classOf[TcpConnectionSpec].getClassLoader.asInstanceOf[URLClassLoader]
.getURLs
.filter(_.getProtocol == "file")
.map(url new File(url.toURI))
.filter(_.exists)
.sortBy(-_.length)
.head
// maximum of 100 MB
val size = math.min(testFile.length(), 100000000).toInt
object Ack
val writer = TestProbe()
writer.send(connectionActor, WriteFile(testFile.getAbsolutePath, 0, size, Ack))
pullFromServerSide(size, 1000000)
writer.expectMsg(Ack)
}
/*
* Disabled on Windows: http://support.microsoft.com/kb/214397
*
@ -235,8 +258,8 @@ class TcpConnectionSpec extends AkkaSpec("akka.io.tcp.register-timeout = 500ms")
writer.expectMsg(CommandFailed(secondWrite))
// reject even empty writes
writer.send(connectionActor, Write.Empty)
writer.expectMsg(CommandFailed(Write.Empty))
writer.send(connectionActor, Write.empty)
writer.expectMsg(CommandFailed(Write.empty))
// there will be immediately more space in the send buffer because
// some data will have been sent by now, so we assume we can write
@ -607,7 +630,7 @@ class TcpConnectionSpec extends AkkaSpec("akka.io.tcp.register-timeout = 500ms")
*/
@tailrec final def pullFromServerSide(remaining: Int, remainingTries: Int = 1000): Unit =
if (remainingTries <= 0)
throw new AssertionError("Pulling took too many loops")
throw new AssertionError("Pulling took too many loops, remaining data: " + remaining)
else if (remaining > 0) {
if (selector.msgAvailable) {
selector.expectMsg(WriteInterest)