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/base.rb | 51 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 10 deletions(-) (limited to 'lib/rainbows/base.rb') diff --git a/lib/rainbows/base.rb b/lib/rainbows/base.rb index 2627719..24924cb 100644 --- a/lib/rainbows/base.rb +++ b/lib/rainbows/base.rb @@ -39,25 +39,56 @@ module Rainbows::Base logger.info "Rainbows! #@use worker_connections=#@worker_connections" end + # TODO: move write_body_* stuff out of Base + def write_body_each(client, body) + body.each { |chunk| client.write(chunk) } + ensure + body.respond_to?(:close) and body.close + end + + # The sendfile 1.0.0 RubyGem includes IO#sendfile and + # IO#sendfile_nonblock, previous versions didn't have + # IO#sendfile_nonblock, and IO#sendfile in previous versions + # could other threads under 1.8 with large files + # + # IO#sendfile currently (June 2010) beats 1.9 IO.copy_stream with + # non-Linux support and large files on 32-bit. We still fall back to + # IO.copy_stream (if available) if we're dealing with DevFdResponse + # objects, though. + if IO.method_defined?(:sendfile_nonblock) + def write_body_path(client, body) + file = Rainbows.body_to_io(body) + file.stat.file? ? client.sendfile(file, 0) : + write_body_stream(client, file) + end + end + if IO.respond_to?(:copy_stream) - def write_body(client, body) - if body.respond_to?(:to_path) + unless method_defined?(:write_body_path) + def write_body_path(client, body) IO.copy_stream(Rainbows.body_to_io(body), client) - else - body.each { |chunk| client.write(chunk) } end - ensure - body.respond_to?(:close) and body.close + end + + def write_body_stream(client, body) + IO.copy_stream(body, client) end else + alias write_body_stream write_body_each + end + + if method_defined?(:write_body_path) def write_body(client, body) - body.each { |chunk| client.write(chunk) } - ensure - body.respond_to?(:close) and body.close + body.respond_to?(:to_path) ? + write_body_path(client, body) : + write_body_each(client, body) end + else + alias write_body write_body_each end - module_function :write_body + module_function :write_body, :write_body_each, :write_body_stream + method_defined?(:write_body_path) and module_function(:write_body_path) def wait_headers_readable(client) IO.select([client], nil, nil, G.kato) -- cgit v1.2.3-24-ge0c7