about summary refs log tree commit homepage
path: root/lib/rainbows/fiber/body.rb
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2010-07-04 22:16:52 +0000
committerEric Wong <normalperson@yhbt.net>2010-07-04 22:34:09 +0000
commit39b178cdebe275cbc8ce19cf269bea7cd15ff4ca (patch)
treeb7628ed278895fcf70ea3206956be586ac9e1ac5 /lib/rainbows/fiber/body.rb
parent75f5aa9a0d6b37a94afbea3121fc2c16e70a2b1d (diff)
downloadrainbows-39b178cdebe275cbc8ce19cf269bea7cd15ff4ca.tar.gz
This hopefully allows the "sendfile" gem to be required
anywhere in the Rainbows!/Unicorn config file, and not
have to be required via RUBYOPT or the '-r' command-line
switch.

We also modularize HttpResponse and avoids singleton methods
in the response path.  This (hopefully) makes it easier for
individual concurrency models to share code and override
individual methods.
Diffstat (limited to 'lib/rainbows/fiber/body.rb')
-rw-r--r--lib/rainbows/fiber/body.rb36
1 files changed, 36 insertions, 0 deletions
diff --git a/lib/rainbows/fiber/body.rb b/lib/rainbows/fiber/body.rb
new file mode 100644
index 0000000..cd6c55c
--- /dev/null
+++ b/lib/rainbows/fiber/body.rb
@@ -0,0 +1,36 @@
+# -*- encoding: binary -*-
+# non-portable body handling for Fiber-based concurrency goes here
+# this module is required and included in worker processes only
+# this is meant to be included _after_ Rainbows::HttpResponse::Body
+module Rainbows::Fiber::Body # :nodoc:
+
+  # TODO non-blocking splice(2) under Linux
+  ALIASES = {
+    :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_file(client, body)
+      sock, off = client.to_io, 0
+      begin
+        off += sock.sendfile_nonblock(body, off, 0x10000)
+      rescue Errno::EAGAIN
+        client.wait_writable
+      rescue EOFError
+        break
+      rescue => e
+        Rainbows::Error.app(e)
+        break
+      end while true
+    end
+  else
+    ALIASES[:write_body] = :write_body_each
+  end
+
+  def self.included(klass)
+    ALIASES.each do |new_method, orig_method|
+      klass.__send__(:alias_method, new_method, orig_method)
+    end
+  end
+end