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