From 8175a52c67fb9dfc9c04a7b0597b680699f43deb Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Mon, 28 Jun 2010 08:06:32 +0000 Subject: add preliminary sendfile (1.0.0) gem support This still needs work and lots of cleanup, but the basics are there. The sendfile 1.0.0 RubyGem is now safe to use under MRI 1.8, and is superior to current (1.9.2-preview3) versions of IO.copy_stream for static files in that it supports more platforms and doesn't truncate large files on 32-bit platforms. --- lib/rainbows/fiber/base.rb | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) (limited to 'lib/rainbows/fiber/base.rb') diff --git a/lib/rainbows/fiber/base.rb b/lib/rainbows/fiber/base.rb index 0298948..7e39441 100644 --- a/lib/rainbows/fiber/base.rb +++ b/lib/rainbows/fiber/base.rb @@ -72,10 +72,31 @@ module Rainbows max.nil? || max > (now + 1) ? 1 : max - now end - def write_body(client, body) - body.each { |chunk| client.write(chunk) } - ensure - body.respond_to?(:close) and body.close + # TODO: IO.splice under Linux + alias write_body_stream write_body_each + + # the sendfile 1.0.0+ gem includes IO#sendfile_nonblock + if ::IO.method_defined?(:sendfile_nonblock) + def write_body_path(client, body) + file = Rainbows.body_to_io(body) + if file.stat.file? + sock, off = client.to_io, 0 + begin + off += sock.sendfile_nonblock(file, off, 0x10000) + rescue Errno::EAGAIN + client.wait_writable + rescue EOFError + break + rescue => e + Rainbows::Error.app(e) + break + end while true + else + write_body_stream(client, body) + end + end + else + alias write_body write_body_each end def wait_headers_readable(client) -- cgit v1.2.3-24-ge0c7