about summary refs log tree commit homepage
path: root/lib/rainbows/revactor
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2010-12-30 08:33:15 +0000
committerEric Wong <normalperson@yhbt.net>2011-01-04 16:37:42 -0800
commite21939d776673b2f8887adf7a5c64812b7d2e98e (patch)
tree48aa3a71201e770758bd09b325c3f2704411af7f /lib/rainbows/revactor
parent4a76da1833922c74e147be5def9bfe04fd0c16a2 (diff)
downloadrainbows-e21939d776673b2f8887adf7a5c64812b7d2e98e.tar.gz
Rack::Utils::HeaderHash is still very expensive in Rack 1.2,
especially for simple things that we want to run as fast as
possible with minimal interference.  HeaderHash is unnecessary
for most requests that do not send Content-Range in responses.
Diffstat (limited to 'lib/rainbows/revactor')
-rw-r--r--lib/rainbows/revactor/client.rb59
-rw-r--r--lib/rainbows/revactor/client/methods.rb (renamed from lib/rainbows/revactor/body.rb)29
-rw-r--r--lib/rainbows/revactor/client/tee_socket.rb (renamed from lib/rainbows/revactor/tee_socket.rb)2
3 files changed, 74 insertions, 16 deletions
diff --git a/lib/rainbows/revactor/client.rb b/lib/rainbows/revactor/client.rb
new file mode 100644
index 0000000..7c4b53d
--- /dev/null
+++ b/lib/rainbows/revactor/client.rb
@@ -0,0 +1,59 @@
+# -*- encoding: binary -*-
+# :enddoc:
+require 'fcntl'
+class Rainbows::Revactor::Client
+  autoload :TeeSocket, 'rainbows/revactor/client/tee_socket'
+  RD_ARGS = {}
+  RD_ARGS[:timeout] = Rainbows::G.kato if Rainbows::G.kato > 0
+  attr_reader :kgio_addr
+
+  def initialize(client)
+    @client, @rd_args, @ts = client, [ nil ], nil
+    io = client.instance_variable_get(:@_io)
+    io.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
+    @kgio_addr = if Revactor::TCP::Socket === client
+      @rd_args << RD_ARGS
+      client.remote_addr
+    else
+      Kgio::LOCALHOST
+    end
+  end
+
+  def kgio_read!(nr, buf)
+    buf.replace(@client.read)
+  end
+
+  def write(buf)
+    @client.write(buf)
+  end
+
+  def write_nonblock(buf) # only used for errors
+    @client.instance_variable_get(:@_io).write_nonblock(buf)
+  end
+
+  def timed_read(buf2)
+    buf2.replace(@client.read(*@rd_args))
+  end
+
+  def set_input(env, hp)
+    env[RACK_INPUT] = 0 == hp.content_length ?
+                      NULL_IO : IC.new(@ts = TeeSocket.new(@client), hp)
+    env[CLIENT_IO] = @client
+  end
+
+  def close
+    @client.close
+    @client = nil
+  end
+
+  def closed?
+    @client.nil?
+  end
+
+  def self.setup
+    self.const_set(:IC, Unicorn::HttpRequest.input_class)
+    include Rainbows::ProcessClient
+    include Methods
+  end
+end
+require 'rainbows/revactor/client/methods'
diff --git a/lib/rainbows/revactor/body.rb b/lib/rainbows/revactor/client/methods.rb
index 9820df3..e9b39a3 100644
--- a/lib/rainbows/revactor/body.rb
+++ b/lib/rainbows/revactor/client/methods.rb
@@ -1,15 +1,10 @@
 # -*- encoding: binary -*-
 # :enddoc:
-module Rainbows::Revactor::Body
-  # TODO non-blocking splice(2) under Linux
-  ALIASES = {
-    :write_body_stream => :write_body_each
-  }
-
+module Rainbows::Revactor::Client::Methods
   if IO.method_defined?(:sendfile_nonblock)
-    def write_body_file_sendfile_revactor(client, body, range)
-      body = body_to_io(body)
-      sock = client.instance_variable_get(:@_io)
+    def write_body_file(body, range)
+      body, client = body_to_io(body), @client
+      sock = @client.instance_variable_get(:@_io)
       pfx = Revactor::TCP::Socket === client ? :tcp : :unix
       write_complete = T[:"#{pfx}_write_complete", client]
       closed = T[:"#{pfx}_closed", client]
@@ -33,14 +28,18 @@ module Rainbows::Revactor::Body
       ensure
         close_if_private(body)
     end
-    ALIASES[:write_body_file] = :write_body_file_sendfile_revactor
-  else
-    ALIASES[:write_body] = :write_body_each
+  end
+
+  def handle_error(e)
+    Revactor::TCP::ReadError === e or super
+  end
+
+  def write_response(status, headers, body, alive)
+    super(status, headers, body, alive)
+    alive && @ts and @hp.buf << @ts.leftover
   end
 
   def self.included(klass)
-    ALIASES.each do |new_method, orig_method|
-      klass.__send__(:alias_method, new_method, orig_method)
-    end
+    klass.__send__ :alias_method, :write_body_stream, :write_body_each
   end
 end
diff --git a/lib/rainbows/revactor/tee_socket.rb b/lib/rainbows/revactor/client/tee_socket.rb
index 71aeb88..2f9f52e 100644
--- a/lib/rainbows/revactor/tee_socket.rb
+++ b/lib/rainbows/revactor/client/tee_socket.rb
@@ -5,7 +5,7 @@
 # enough to avoid mucking with TeeInput internals.  Fortunately
 # this code is not heavily used so we can usually avoid the overhead
 # of adding a userspace buffer.
-class Rainbows::Revactor::TeeSocket
+class Rainbows::Revactor::Client::TeeSocket
   def initialize(socket)
     # IO::Buffer is used internally by Rev which Revactor is based on
     # so we'll always have it available