restore Rainbows::HttpResponse.write for Cramp
[rainbows.git] / lib / rainbows.rb
blob4e9578b04f132cab5d2846da602197ac09c51e18
1 # -*- encoding: binary -*-
2 require 'unicorn'
3 # the value passed to TCP_DEFER_ACCEPT actually matters in Linux 2.6.32+
4 Unicorn::SocketHelper::DEFAULTS[:tcp_defer_accept] = 60
6 require 'rainbows/error'
7 require 'rainbows/configurator'
8 require 'fcntl'
10 module Rainbows
12   # global vars because class/instance variables are confusing me :<
13   # this struct is only accessed inside workers and thus private to each
14   # G.cur may not be used in the network concurrency model
15   class State < Struct.new(:alive,:m,:cur,:kato,:server,:tmp,:expire)
16     def tick
17       tmp.chmod(self.m = m == 0 ? 1 : 0)
18       exit!(2) if expire && Time.now >= expire
19       alive && server.master_pid == Process.ppid or quit!
20     end
22     def quit!
23       self.alive = false
24       self.expire ||= Time.now + (server.timeout * 2.0)
25       server.class.const_get(:LISTENERS).map! { |s| s.close rescue nil }
26       false
27     end
28   end
29   # :stopdoc:
30   G = State.new(true, 0, 0, 5)
31   O = {}
32   # :startdoc:
34   require 'rainbows/const'
35   require 'rainbows/http_server'
36   require 'rainbows/response'
37   require 'rainbows/base'
38   require 'rainbows/tee_input'
39   autoload :Sendfile, 'rainbows/sendfile'
40   autoload :AppPool, 'rainbows/app_pool'
41   autoload :DevFdResponse, 'rainbows/dev_fd_response'
42   autoload :MaxBody, 'rainbows/max_body'
43   autoload :QueuePool, 'rainbows/queue_pool'
45   class << self
47     # Sleeps the current application dispatch.  This will pick the
48     # optimal method to sleep depending on the concurrency model chosen
49     # (which may still suck and block the entire process).  Using this
50     # with the basic :Rev or :EventMachine models is not recommended.
51     # This should be used within your Rack application.
52     def sleep(nr)
53       case G.server.use
54       when :FiberPool, :FiberSpawn
55         Rainbows::Fiber.sleep(nr)
56       when :RevFiberSpawn
57         Rainbows::Fiber::Rev::Sleeper.new(nr)
58       when :Revactor
59         Actor.sleep(nr)
60       else
61         Kernel.sleep(nr)
62       end
63     end
65     # runs the Rainbows! HttpServer with +app+ and +options+ and does
66     # not return until the server has exited.
67     def run(app, options = {})
68       HttpServer.new(app, options).start.join
69     end
71     # returns nil if accept fails
72     def sync_accept(sock)
73       rv = sock.accept
74       rv.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
75       rv
76     rescue Errno::EAGAIN, Errno::ECONNABORTED, Errno::EINTR
77     end
79     # returns nil if accept fails
80     def accept(sock)
81       rv = sock.accept_nonblock
82       rv.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
83       rv
84     rescue Errno::EAGAIN, Errno::ECONNABORTED
85     end
87     # returns a string representing the address of the given client +io+
88     # For local UNIX domain sockets, this will return a string referred
89     # to by the (non-frozen) Unicorn::HttpRequest::LOCALHOST constant.
90     def addr(io)
91       io.respond_to?(:peeraddr) ?
92                         io.peeraddr[-1] : Unicorn::HttpRequest::LOCALHOST
93     end
95     # the default max body size is 1 megabyte (1024 * 1024 bytes)
96     @@max_bytes = 1024 * 1024
98     def max_bytes; @@max_bytes; end
99     def max_bytes=(nr); @@max_bytes = nr; end
100   end
102   # :stopdoc:
103   # maps models to default worker counts, default worker count numbers are
104   # pretty arbitrary and tuning them to your application and hardware is
105   # highly recommended
106   MODEL_WORKER_CONNECTIONS = {
107     :Base => 1, # this one can't change
108     :WriterThreadPool => 20,
109     :WriterThreadSpawn => 20,
110     :Revactor => 50,
111     :ThreadSpawn => 30,
112     :ThreadPool => 20,
113     :Rev => 50,
114     :RevThreadSpawn => 50,
115     :RevThreadPool => 50,
116     :EventMachine => 50,
117     :FiberSpawn => 50,
118     :FiberPool => 50,
119     :ActorSpawn => 50,
120     :NeverBlock => 50,
121     :RevFiberSpawn => 50,
122   }.each do |model, _|
123     u = model.to_s.gsub(/([a-z0-9])([A-Z0-9])/) { "#{$1}_#{$2.downcase!}" }
124     autoload model, "rainbows/#{u.downcase!}"
125   end
126   # :startdoc:
127   autoload :Fiber, 'rainbows/fiber' # core class
128   autoload :ByteSlice, 'rainbows/byte_slice'
129   autoload :StreamFile, 'rainbows/stream_file'
130   autoload :HttpResponse, 'rainbows/http_response' # deprecated