about summary refs log tree commit homepage
path: root/lib/rainbows/revactor/client/tee_socket.rb
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/client/tee_socket.rb
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/client/tee_socket.rb')
-rw-r--r--lib/rainbows/revactor/client/tee_socket.rb44
1 files changed, 44 insertions, 0 deletions
diff --git a/lib/rainbows/revactor/client/tee_socket.rb b/lib/rainbows/revactor/client/tee_socket.rb
new file mode 100644
index 0000000..2f9f52e
--- /dev/null
+++ b/lib/rainbows/revactor/client/tee_socket.rb
@@ -0,0 +1,44 @@
+# -*- encoding: binary -*-
+# :enddoc:
+#
+# 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 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
+    @socket, @rbuf = socket, IO::Buffer.new
+  end
+
+  def leftover
+    @rbuf.read
+  end
+
+  # Revactor socket reads always return an unspecified amount,
+  # sometimes too much
+  def kgio_read(length, dst = "")
+    return dst.replace("") 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
+    @rbuf << tmp[length, tmp.size]
+    dst.replace(tmp[0, length])
+    rescue EOFError
+  end
+
+  # just proxy any remaining methods TeeInput may use
+  def close
+    @socket.close
+  end
+end