Class: Thin::Controllers::Controller

Class Thin::Controllers::Controller < Object

(in files lib/thin/controllers/controller.rb )

Controls one Thin server. Allow to start, stop, restart and configure a single thin server.

Includes

Methods

Public Class new(options)

    # File lib/thin/controllers/controller.rb, line 28
28:       def initialize(options)
29:         @options = options
30:         
31:         if @options[:socket]
32:           @options.delete(:address)
33:           @options.delete(:port)
34:         end
35:       end

Public Instance config()

     # File lib/thin/controllers/controller.rb, line 103
103:       def config
104:         config_file = @options.delete(:config) || raise(OptionRequired, :config)
105: 
106:         # Stringify keys
107:         @options.keys.each { |o| @options[o.to_s] = @options.delete(o) }
108: 
109:         File.open(config_file, 'w') { |f| f << @options.to_yaml }
110:         log ">> Wrote configuration to #{config_file}"
111:       end

Public Instance restart()

     # File lib/thin/controllers/controller.rb, line 93
 93:       def restart
 94:         raise OptionRequired, :pid unless @options[:pid]
 95:         
 96:         tail_log(@options[:log]) do
 97:           if Server.restart(@options[:pid])
 98:             wait_for_file :creation, @options[:pid]
 99:           end
100:         end
101:       end

Public Instance start()

    # 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:         # Detach the process, after this line the current process returns
55:         server.daemonize if @options[:daemonize]
56: 
57:         # +config+ must be called before changing privileges since it might require superuser power.
58:         server.config
59:         
60:         server.change_privilege @options[:user], @options[:group] if @options[:user] && @options[:group]
61: 
62:         # If a Rack config file is specified we eval it inside a Rack::Builder block to create
63:         # a Rack adapter from it. Or else we guess which adapter to use and load it.
64:         if @options[:rackup]
65:           server.app = load_rackup_config
66:         else
67:           server.app = load_adapter
68:         end
69: 
70:         # If a prefix is required, wrap in Rack URL mapper
71:         server.app = Rack::URLMap.new(@options[:prefix] => server.app) if @options[:prefix]
72: 
73:         # If a stats URL is specified, wrap in Stats adapter
74:         server.app = Stats::Adapter.new(server.app, @options[:stats]) if @options[:stats]
75: 
76:         # Register restart procedure which just start another process with same options,
77:         # so that's why this is done here.
78:         server.on_restart { Command.run(:start, @options) }
79: 
80:         server.start
81:       end

Public Instance stop()

    # File lib/thin/controllers/controller.rb, line 83
83:       def stop
84:         raise OptionRequired, :pid unless @options[:pid]
85:       
86:         tail_log(@options[:log]) do
87:           if Server.kill(@options[:pid], @options[:force] ? 0 : (@options[:timeout] || 60))
88:             wait_for_file :deletion, @options[:pid]
89:           end
90:         end
91:       end

Protected Instance tail(file)

Acts like GNU tail command. Taken from Rails.

     # File lib/thin/controllers/controller.rb, line 136
136:         def tail(file)
137:           cursor = File.exist?(file) ? File.size(file) : 0
138:           last_checked = Time.now
139:           tail_thread = Thread.new do
140:             Thread.pass until File.exist?(file)
141:             File.open(file, 'r') do |f|
142:               loop do
143:                 f.seek cursor
144:                 if f.mtime > last_checked
145:                   last_checked = f.mtime
146:                   contents = f.read
147:                   cursor += contents.length
148:                   print contents
149:                   STDOUT.flush
150:                 end
151:                 sleep 0.1
152:               end
153:             end
154:           end
155:           sleep 1 if File.exist?(file) # HACK Give the thread a little time to open the file
156:           tail_thread
157:         end

Protected Instance tail_log(log_file) {|| ...}

Tail the log file of server number during the execution of the block.

     # File lib/thin/controllers/controller.rb, line 125
125:         def tail_log(log_file)
126:           if log_file
127:             tail_thread = tail(log_file)
128:             yield
129:             tail_thread.kill
130:           else
131:             yield
132:           end
133:         end

Protected Instance wait_for_file(state, file)

Wait for a pid file to either be created or deleted.

     # File lib/thin/controllers/controller.rb, line 115
115:         def wait_for_file(state, file)
116:           Timeout.timeout(@options[:timeout] || 30) do
117:             case state
118:             when :creation then sleep 0.1 until File.exist?(file)
119:             when :deletion then sleep 0.1 while File.exist?(file)
120:             end
121:           end
122:         end