about summary refs log tree commit homepage
path: root/lib/rainbows/fiber/base.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rainbows/fiber/base.rb')
-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)