about summary refs log tree commit homepage
path: root/lib
diff options
context:
space:
mode:
authorEric Wong <e@80x24.org>2013-11-01 22:01:45 +0000
committerEric Wong <normalperson@yhbt.net>2013-11-01 22:01:45 +0000
commit2260de380fc920f2d3108405ac3df5db7225a90e (patch)
tree2d4d9fd99a071ec5d273860f026db10588232b01 /lib
parent98b663091a919035ea85bc5273bfe4bd1aac2073 (diff)
downloadyahns-2260de380fc920f2d3108405ac3df5db7225a90e.tar.gz
This allows users to specify alternative temporary directories
in case buffers get too large for one filesystem to handle or
to give priority to some clients on certain ports.
Diffstat (limited to 'lib')
-rw-r--r--lib/yahns/cap_input.rb4
-rw-r--r--lib/yahns/config.rb23
-rw-r--r--lib/yahns/http_context.rb20
-rw-r--r--lib/yahns/http_response.rb4
-rw-r--r--lib/yahns/tmpio.rb4
-rw-r--r--lib/yahns/wbuf.rb4
6 files changed, 45 insertions, 14 deletions
diff --git a/lib/yahns/cap_input.rb b/lib/yahns/cap_input.rb
index 1aa10b6..313b3ce 100644
--- a/lib/yahns/cap_input.rb
+++ b/lib/yahns/cap_input.rb
@@ -7,8 +7,8 @@
 class Yahns::CapInput < Yahns::TmpIO # :nodoc:
   attr_writer :bytes_left
 
-  def self.new(limit)
-    rv = super()
+  def self.new(limit, tmpdir)
+    rv = super(tmpdir)
     rv.bytes_left = limit
     rv
   end
diff --git a/lib/yahns/config.rb b/lib/yahns/config.rb
index 1862eee..4ea51af 100644
--- a/lib/yahns/config.rb
+++ b/lib/yahns/config.rb
@@ -334,9 +334,7 @@ class Yahns::Config # :nodoc:
   end
 
   # boolean config directives for app
-  %w(check_client_connection
-     output_buffering
-     persistent_connections).each do |_v|
+  %w(check_client_connection persistent_connections).each do |_v|
     eval(
     %Q(def #{_v}(bool);) <<
     %Q(  _check_in_block(:app, :#{_v});) <<
@@ -345,6 +343,21 @@ class Yahns::Config # :nodoc:
     )
   end
 
+  def output_buffering(bool, opts = {})
+    var = _check_in_block(:app, :output_buffering)
+    @block.ctx.__send__("#{var}=", _check_bool(var, bool))
+    tmpdir = opts[:tmpdir] and
+      @block.ctx.output_buffer_tmpdir = _check_tmpdir(var, tmpdir)
+  end
+
+  def _check_tmpdir(var, path)
+    File.directory?(path) or
+      raise ArgumentError, "#{var} tmpdir: #{path} is not a directory"
+    File.writable?(path) or
+      raise ArgumentError, "#{var} tmpdir: #{path} is not writable"
+    path
+  end
+
   # integer config directives for app
   {
     # config name, minimum value
@@ -371,12 +384,14 @@ class Yahns::Config # :nodoc:
     @block.ctx.__send__("#{var}=", val)
   end
 
-  def input_buffering(val)
+  def input_buffering(val, opts = {})
     var = _check_in_block(:app, :input_buffering)
     ok = [ :lazy, true, false ]
     ok.include?(val) or
       raise ArgumentError, "`#{var}' must be one of: #{ok.inspect}"
     @block.ctx.__send__("#{var}=", val)
+    tmpdir = opts[:tmpdir] and
+      @block.ctx.input_buffer_tmpdir = _check_tmpdir(var, tmpdir)
   end
 
   # used to configure rack.errors destination
diff --git a/lib/yahns/http_context.rb b/lib/yahns/http_context.rb
index 605989f..bd455bd 100644
--- a/lib/yahns/http_context.rb
+++ b/lib/yahns/http_context.rb
@@ -18,6 +18,8 @@ module Yahns::HttpContext # :nodoc:
   attr_accessor :queue # set right before spawning acceptors
   attr_reader :app
   attr_reader :app_defaults
+  attr_writer :input_buffer_tmpdir
+  attr_writer :output_buffer_tmpdir
 
   def http_ctx_init(yahns_rack)
     @yahns_rack = yahns_rack
@@ -32,6 +34,10 @@ module Yahns::HttpContext # :nodoc:
     @client_timeout = 15
     @qegg = nil
     @queue = nil
+
+    # Dir.tmpdir can change while running, so leave these as nil
+    @input_buffer_tmpdir = nil
+    @output_buffer_tmpdir = nil
   end
 
   # call this after forking
@@ -74,10 +80,20 @@ module Yahns::HttpContext # :nodoc:
 
   def tmpio_for(len)
     if len # Content-Length given
-      len <= @client_body_buffer_size ? StringIO.new("") : Yahns::TmpIO.new
+      len <= @client_body_buffer_size ? StringIO.new("")
+           : Yahns::TmpIO.new(input_buffer_tmpdir)
     else # chunked, unknown length
       mbs = @client_max_body_size
-      mbs ? Yahns::CapInput.new(mbs) : Yahns::TmpIO.new
+      tmpdir = input_buffer_tmpdir
+      mbs ? Yahns::CapInput.new(mbs, tmpdir) : Yahns::TmpIO.new(tmpdir)
     end
   end
+
+  def input_buffer_tmpdir
+    @input_buffer_tmpdir || Dir.tmpdir
+  end
+
+  def output_buffer_tmpdir
+    @output_buffer_tmpdir || Dir.tmpdir
+  end
 end
diff --git a/lib/yahns/http_response.rb b/lib/yahns/http_response.rb
index 6ddb1c8..f48b4d8 100644
--- a/lib/yahns/http_response.rb
+++ b/lib/yahns/http_response.rb
@@ -47,7 +47,7 @@ module Yahns::HttpResponse # :nodoc:
       alive = Yahns::StreamFile.new(body, alive, offset, count)
       body = nil
     end
-    wbuf = Yahns::Wbuf.new(body, alive)
+    wbuf = Yahns::Wbuf.new(body, alive, self.class.output_buffer_tmpdir)
     rv = wbuf.wbuf_write(self, header)
     body.each { |chunk| rv = wbuf.wbuf_write(self, chunk) } if body
     wbuf_maybe(wbuf, rv, alive)
@@ -165,7 +165,7 @@ module Yahns::HttpResponse # :nodoc:
           chunk = rv # hope the skb grows when we loop into the trywrite
         when :wait_writable, :wait_readable
           if k.output_buffering
-            wbuf = Yahns::Wbuf.new(body, alive)
+            wbuf = Yahns::Wbuf.new(body, alive, k.output_buffer_tmpdir)
             rv = wbuf.wbuf_write(self, chunk)
             break
           else
diff --git a/lib/yahns/tmpio.rb b/lib/yahns/tmpio.rb
index 4fe4794..bcf6b8a 100644
--- a/lib/yahns/tmpio.rb
+++ b/lib/yahns/tmpio.rb
@@ -11,10 +11,10 @@ class Yahns::TmpIO < File # :nodoc:
   # creates and returns a new File object.  The File is unlinked
   # immediately, switched to binary mode, and userspace output
   # buffering is disabled
-  def self.new
+  def self.new(tmpdir = Dir.tmpdir)
     retried = false
     begin
-      fp = super("#{Dir.tmpdir}/#{rand}", RDWR|CREAT|EXCL, 0600)
+      fp = super("#{tmpdir}/#{rand}", RDWR|CREAT|EXCL, 0600)
     rescue Errno::EEXIST
       retry
     rescue Errno::EMFILE, Errno::ENFILE
diff --git a/lib/yahns/wbuf.rb b/lib/yahns/wbuf.rb
index 8b2b82e..e6039b7 100644
--- a/lib/yahns/wbuf.rb
+++ b/lib/yahns/wbuf.rb
@@ -6,8 +6,8 @@ require_relative 'wbuf_common'
 class Yahns::Wbuf # :nodoc:
   include Yahns::WbufCommon
 
-  def initialize(body, persist)
-    @tmpio = Yahns::TmpIO.new
+  def initialize(body, persist, tmpdir)
+    @tmpio = Yahns::TmpIO.new(tmpdir)
     @sf_offset = @sf_count = 0
     @wbuf_persist = persist # whether or not we keep the connection alive
     @body = body