Object
Controls one Thin server. Allow to start, stop, restart and configure a single thin server.
# File lib/thin/controllers/controller.rb, line 109
109: def config
110: config_file = @options.delete(:config) || raise(OptionRequired, :config)
111:
112: # Stringify keys
113: @options.keys.each { |o| @options[o.to_s] = @options.delete(o) }
114:
115: File.open(config_file, 'w') { |f| f << @options.to_yaml }
116: log ">> Wrote configuration to #{config_file}"
117: end
# File lib/thin/controllers/controller.rb, line 99
99: def restart
100: raise OptionRequired, :pid unless @options[:pid]
101:
102: tail_log(@options[:log]) do
103: if Server.restart(@options[:pid])
104: wait_for_file :creation, @options[:pid]
105: end
106: end
107: end
# File lib/thin/controllers/controller.rb, line 37
37: def start
38: # Constantize backend class
39: @options[:backend] = eval(@options[:backend], TOPLEVEL_BINDING) if @options[:backend]
40:
41: server = Server.new(@options[:socket] || @options[:address], # Server detects kind of socket
42: @options[:port], # Port ignored on UNIX socket
43: @options)
44:
45: # Set options
46: server.pid_file = @options[:pid]
47: server.log_file = @options[:log]
48: server.timeout = @options[:timeout]
49: server.maximum_connections = @options[:max_conns]
50: server.maximum_persistent_connections = @options[:max_persistent_conns]
51: server.threaded = @options[:threaded]
52: server.no_epoll = @options[:no_epoll] if server.backend.respond_to?(:no_epoll=)
53:
54: # ssl support
55: if @options[:ssl]
56: server.ssl = true
57: server.ssl_options = { :private_key_file => @options[:ssl_key_file], :cert_chain_file => @options[:ssl_cert_file], :verify_peer => @options[:ssl_verify] }
58: end
59:
60: # Detach the process, after this line the current process returns
61: server.daemonize if @options[:daemonize]
62:
63: # +config+ must be called before changing privileges since it might require superuser power.
64: server.config
65:
66: server.change_privilege @options[:user], @options[:group] if @options[:user] && @options[:group]
67:
68: # If a Rack config file is specified we eval it inside a Rack::Builder block to create
69: # a Rack adapter from it. Or else we guess which adapter to use and load it.
70: if @options[:rackup]
71: server.app = load_rackup_config
72: else
73: server.app = load_adapter
74: end
75:
76: # If a prefix is required, wrap in Rack URL mapper
77: server.app = Rack::URLMap.new(@options[:prefix] => server.app) if @options[:prefix]
78:
79: # If a stats URL is specified, wrap in Stats adapter
80: server.app = Stats::Adapter.new(server.app, @options[:stats]) if @options[:stats]
81:
82: # Register restart procedure which just start another process with same options,
83: # so that's why this is done here.
84: server.on_restart { Command.run(:start, @options) }
85:
86: server.start
87: end
# File lib/thin/controllers/controller.rb, line 89
89: def stop
90: raise OptionRequired, :pid unless @options[:pid]
91:
92: tail_log(@options[:log]) do
93: if Server.kill(@options[:pid], @options[:force] ? 0 : (@options[:timeout] || 60))
94: wait_for_file :deletion, @options[:pid]
95: end
96: end
97: end
Acts like GNU tail command. Taken from Rails.
# File lib/thin/controllers/controller.rb, line 142
142: def tail(file)
143: cursor = File.exist?(file) ? File.size(file) : 0
144: last_checked = Time.now
145: tail_thread = Thread.new do
146: Thread.pass until File.exist?(file)
147: File.open(file, 'r') do |f|
148: loop do
149: f.seek cursor
150: if f.mtime > last_checked
151: last_checked = f.mtime
152: contents = f.read
153: cursor += contents.length
154: print contents
155: STDOUT.flush
156: end
157: sleep 0.1
158: end
159: end
160: end
161: sleep 1 if File.exist?(file) # HACK Give the thread a little time to open the file
162: tail_thread
163: end
Tail the log file of server number during the execution of the block.
# File lib/thin/controllers/controller.rb, line 131
131: def tail_log(log_file)
132: if log_file
133: tail_thread = tail(log_file)
134: yield
135: tail_thread.kill
136: else
137: yield
138: end
139: end
Wait for a pid file to either be created or deleted.
# File lib/thin/controllers/controller.rb, line 121
121: def wait_for_file(state, file)
122: Timeout.timeout(@options[:timeout] || 30) do
123: case state
124: when :creation then sleep 0.1 until File.exist?(file)
125: when :deletion then sleep 0.1 while File.exist?(file)
126: end
127: end
128: end
# File lib/thin/controllers/controller.rb, line 166
166: def load_adapter
167: adapter = @options[:adapter] || Rack::Adapter.guess(@options[:chdir])
168: log ">> Using #{adapter} adapter"
169: Rack::Adapter.for(adapter, @options)
170: rescue Rack::AdapterNotFound => e
171: raise InvalidOption, e.message
172: end
# File lib/thin/controllers/controller.rb, line 174
174: def load_rackup_config
175: ENV['RACK_ENV'] = @options[:environment]
176: case @options[:rackup]
177: when /\.rb$/
178: Kernel.load(@options[:rackup])
179: Object.const_get(File.basename(@options[:rackup], '.rb').capitalize.to_sym)
180: when /\.ru$/
181: Rack::Adapter.load(@options[:rackup])
182: else
183: raise "Invalid rackup file. please specify either a .ru or .rb file"
184: end
185: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.