From 1562a19a021a72a78ba495328d2d37ba0dc83b8c Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Tue, 7 Dec 2010 12:11:51 -0800 Subject: rev+revactor: fix LARGE pipelined uploads Large uploads behave differently with regard to buffering, and there were bugs in the way the Rev and Revactor backends handled uploads. --- lib/rainbows/ev_core.rb | 2 ++ lib/rainbows/revactor.rb | 8 ++++++- t/t0106-rack-input-keepalive.sh | 48 ++++++++++++++++++++++++++++++++++++++++- 3 files changed, 56 insertions(+), 2 deletions(-) diff --git a/lib/rainbows/ev_core.rb b/lib/rainbows/ev_core.rb index 8241584..46fdedf 100644 --- a/lib/rainbows/ev_core.rb +++ b/lib/rainbows/ev_core.rb @@ -86,6 +86,8 @@ module Rainbows::EvCore @hp.filter_body(@buf2, @buf << data) @input << @buf2 on_read("") + else + want_more end when :trailers if @hp.trailers(@env, @buf << data) diff --git a/lib/rainbows/revactor.rb b/lib/rainbows/revactor.rb index 59f37b0..51f6c1f 100644 --- a/lib/rainbows/revactor.rb +++ b/lib/rainbows/revactor.rb @@ -46,13 +46,14 @@ module Rainbows::Revactor alive = false begin + ts = nil until env = hp.parse buf << client.read(*rd_args) end env[CLIENT_IO] = client env[RACK_INPUT] = 0 == hp.content_length ? - NULL_IO : Unicorn::TeeInput.new(TeeSocket.new(client), hp) + NULL_IO : Unicorn::TeeInput.new(ts = TeeSocket.new(client), hp) env[REMOTE_ADDR] = remote_addr status, headers, body = app.call(env.update(RACK_DEFAULTS)) @@ -68,6 +69,7 @@ module Rainbows::Revactor alive = hp.next? && G.alive && G.kato > 0 headers[CONNECTION] = alive ? KEEP_ALIVE : CLOSE client.write(response_header(status, headers)) + alive && ts and buf << ts.leftover end write_body(client, body, range) end while alive @@ -155,6 +157,10 @@ module Rainbows::Revactor @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 = "") diff --git a/t/t0106-rack-input-keepalive.sh b/t/t0106-rack-input-keepalive.sh index c4a531d..ce6d092 100755 --- a/t/t0106-rack-input-keepalive.sh +++ b/t/t0106-rack-input-keepalive.sh @@ -1,6 +1,6 @@ #!/bin/sh . ./test-lib.sh -t_plan 7 "rack.input pipelining test" +t_plan 11 "rack.input pipelining test" t_begin "setup and startup" && { rainbows_setup $model @@ -9,9 +9,55 @@ t_begin "setup and startup" && { body=hello body_size=$(printf $body | wc -c) body_sha1=$(printf $body | rsha1) + random_blob_size=$(wc -c < random_blob) + random_blob_sha1=$(rsha1 < random_blob) rainbows_wait_start } +t_begin "send big pipelined chunked requests" && { + ( + cat $fifo > $tmp & + content-md5-put < random_blob + content-md5-put < random_blob + content-md5-put < random_blob + printf 'PUT / HTTP/1.0\r\n' + printf 'Content-Length: %d\r\n\r\n' $random_blob_size + cat random_blob + wait + echo ok > $ok + ) | socat - TCP4:$listen > $fifo + test x"$(cat $ok)" = xok +} + +t_begin "check responses" && { + dbgcat tmp + test 4 -eq $(grep $random_blob_sha1 $tmp | wc -l) +} + +t_begin "send big pipelined identity requests" && { + ( + cat $fifo > $tmp & + printf 'PUT / HTTP/1.0\r\n' + printf 'Connection: keep-alive\r\n' + printf 'Content-Length: %d\r\n\r\n' $random_blob_size + cat random_blob + printf 'PUT / HTTP/1.1\r\n' + printf 'Content-Length: %d\r\n\r\n' $random_blob_size + cat random_blob + printf 'PUT / HTTP/1.0\r\n' + printf 'Content-Length: %d\r\n\r\n' $random_blob_size + cat random_blob + wait + echo ok > $ok + ) | socat - TCP4:$listen > $fifo + test x"$(cat $ok)" = xok +} + +t_begin "check responses" && { + dbgcat tmp + test 3 -eq $(grep $random_blob_sha1 $tmp | wc -l) +} + t_begin "send pipelined identity requests" && { { -- cgit v1.2.3-24-ge0c7