about summary refs log tree commit homepage
path: root/lib/rainbows/fiber
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2010-06-28 08:06:32 +0000
committerEric Wong <normalperson@yhbt.net>2010-06-28 08:57:26 +0000
commit8175a52c67fb9dfc9c04a7b0597b680699f43deb (patch)
tree9c50e69b27c271929082aad63d0f1f7e9a4d28fa /lib/rainbows/fiber
parent86e9c7013308d77def5fe41b52a35dea60c7361c (diff)
downloadrainbows-8175a52c67fb9dfc9c04a7b0597b680699f43deb.tar.gz
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.
Diffstat (limited to 'lib/rainbows/fiber')
-rw-r--r--lib/rainbows/fiber/base.rb29
1 files changed, 25 insertions, 4 deletions
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)