lib/rainbows/revactor.rb in rainbows-0.91.1 vs lib/rainbows/revactor.rb in rainbows-0.92.0
- old
+ new
@@ -19,12 +19,10 @@
# in the application using this model should be implemented using the
# \Revactor library as well, to take advantage of the networking
# concurrency features this model provides.
module Revactor
- require 'rainbows/revactor/tee_input'
-
RD_ARGS = {}
include Base
# once a client is accepted, it is processed in its entirety here
@@ -35,11 +33,11 @@
rd_args = [ nil ]
remote_addr = if ::Revactor::TCP::Socket === client
rd_args << RD_ARGS
client.remote_addr
else
- LOCALHOST
+ Unicorn::HttpRequest::LOCALHOST
end
buf = client.read(*rd_args)
hp = HttpParser.new
env = {}
alive = true
@@ -50,11 +48,11 @@
end
env[Const::CLIENT_IO] = client
env[Const::RACK_INPUT] = 0 == hp.content_length ?
HttpRequest::NULL_IO :
- Rainbows::Revactor::TeeInput.new(client, env, hp, buf)
+ TeeInput.new(PartialSocket.new(client), env, hp, buf)
env[Const::REMOTE_ADDR] = remote_addr
response = app.call(env.update(RACK_DEFAULTS))
if 100 == response.first.to_i
client.write(Const::EXPECT_100_RESPONSE)
@@ -132,9 +130,45 @@
when UNIXServer
l = ::Revactor::UNIX.listen(s)
[ l, T[:unix_closed, ::Revactor::UNIX::Socket ],
T[:unix_connection, l, ::Revactor::UNIX::Socket] ]
end
+ end
+ end
+
+ # Revactor Sockets do not implement readpartial, so we emulate just
+ # 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 PartialSocket < Struct.new(:socket, :rbuf)
+ def initialize(socket)
+ # IO::Buffer is used internally by Rev which Revactor is based on
+ # so we'll always have it available
+ super(socket, IO::Buffer.new)
+ end
+
+ # Revactor socket reads always return an unspecified amount,
+ # sometimes too much
+ def readpartial(length, dst = "")
+ return dst if length == 0
+ # always check and return from the userspace buffer first
+ rbuf.size > 0 and return dst.replace(rbuf.read(length))
+
+ # read off the socket since there was nothing in rbuf
+ tmp = socket.read
+
+ # we didn't read too much, good, just return it straight back
+ # to avoid needlessly wasting memory bandwidth
+ tmp.size <= length and return dst.replace(tmp)
+
+ # ugh, read returned too much, copy + reread to avoid slicing
+ rbuf << tmp[length, tmp.size]
+ dst.replace(tmp[0, length])
+ end
+
+ # just proxy any remaining methods TeeInput may use
+ def close
+ socket.close
end
end
end
end