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.