thin 1.3.1 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. data/CHANGELOG +8 -0
  2. data/README.md +83 -0
  3. data/Rakefile +9 -32
  4. data/example/vlad.rake +1 -1
  5. data/lib/rack/adapter/loader.rb +0 -16
  6. data/lib/thin.rb +22 -24
  7. data/lib/thin/backends/base.rb +3 -1
  8. data/lib/thin/connection.rb +9 -8
  9. data/lib/thin/daemonizing.rb +3 -1
  10. data/lib/thin/logging.rb +1 -1
  11. data/lib/thin/runner.rb +36 -36
  12. data/lib/thin/server.rb +13 -0
  13. data/lib/thin/version.rb +3 -3
  14. metadata +5 -91
  15. data/README +0 -69
  16. data/benchmark/abc +0 -51
  17. data/benchmark/benchmarker.rb +0 -80
  18. data/benchmark/runner +0 -82
  19. data/spec/backends/swiftiply_client_spec.rb +0 -66
  20. data/spec/backends/tcp_server_spec.rb +0 -33
  21. data/spec/backends/unix_server_spec.rb +0 -37
  22. data/spec/command_spec.rb +0 -25
  23. data/spec/configs/cluster.yml +0 -9
  24. data/spec/configs/single.yml +0 -9
  25. data/spec/connection_spec.rb +0 -107
  26. data/spec/controllers/cluster_spec.rb +0 -267
  27. data/spec/controllers/controller_spec.rb +0 -129
  28. data/spec/controllers/service_spec.rb +0 -50
  29. data/spec/daemonizing_spec.rb +0 -200
  30. data/spec/headers_spec.rb +0 -40
  31. data/spec/logging_spec.rb +0 -52
  32. data/spec/perf/request_perf_spec.rb +0 -50
  33. data/spec/perf/response_perf_spec.rb +0 -19
  34. data/spec/perf/server_perf_spec.rb +0 -39
  35. data/spec/rack/loader_spec.rb +0 -42
  36. data/spec/rack/rails_adapter_spec.rb +0 -173
  37. data/spec/rails_app/app/controllers/application.rb +0 -10
  38. data/spec/rails_app/app/controllers/simple_controller.rb +0 -19
  39. data/spec/rails_app/app/helpers/application_helper.rb +0 -3
  40. data/spec/rails_app/app/views/simple/index.html.erb +0 -15
  41. data/spec/rails_app/config/boot.rb +0 -109
  42. data/spec/rails_app/config/environment.rb +0 -64
  43. data/spec/rails_app/config/environments/development.rb +0 -18
  44. data/spec/rails_app/config/environments/production.rb +0 -19
  45. data/spec/rails_app/config/environments/test.rb +0 -22
  46. data/spec/rails_app/config/initializers/inflections.rb +0 -10
  47. data/spec/rails_app/config/initializers/mime_types.rb +0 -5
  48. data/spec/rails_app/config/routes.rb +0 -35
  49. data/spec/rails_app/public/404.html +0 -30
  50. data/spec/rails_app/public/422.html +0 -30
  51. data/spec/rails_app/public/500.html +0 -30
  52. data/spec/rails_app/public/dispatch.cgi +0 -10
  53. data/spec/rails_app/public/dispatch.fcgi +0 -24
  54. data/spec/rails_app/public/dispatch.rb +0 -10
  55. data/spec/rails_app/public/favicon.ico +0 -0
  56. data/spec/rails_app/public/images/rails.png +0 -0
  57. data/spec/rails_app/public/index.html +0 -277
  58. data/spec/rails_app/public/javascripts/application.js +0 -2
  59. data/spec/rails_app/public/javascripts/controls.js +0 -963
  60. data/spec/rails_app/public/javascripts/dragdrop.js +0 -972
  61. data/spec/rails_app/public/javascripts/effects.js +0 -1120
  62. data/spec/rails_app/public/javascripts/prototype.js +0 -4225
  63. data/spec/rails_app/public/robots.txt +0 -5
  64. data/spec/rails_app/script/about +0 -3
  65. data/spec/rails_app/script/console +0 -3
  66. data/spec/rails_app/script/destroy +0 -3
  67. data/spec/rails_app/script/generate +0 -3
  68. data/spec/rails_app/script/performance/benchmarker +0 -3
  69. data/spec/rails_app/script/performance/profiler +0 -3
  70. data/spec/rails_app/script/performance/request +0 -3
  71. data/spec/rails_app/script/plugin +0 -3
  72. data/spec/rails_app/script/process/inspector +0 -3
  73. data/spec/rails_app/script/process/reaper +0 -3
  74. data/spec/rails_app/script/process/spawner +0 -3
  75. data/spec/rails_app/script/runner +0 -3
  76. data/spec/rails_app/script/server +0 -3
  77. data/spec/request/mongrel_spec.rb +0 -39
  78. data/spec/request/parser_spec.rb +0 -254
  79. data/spec/request/persistent_spec.rb +0 -35
  80. data/spec/request/processing_spec.rb +0 -50
  81. data/spec/response_spec.rb +0 -102
  82. data/spec/runner_spec.rb +0 -168
  83. data/spec/server/builder_spec.rb +0 -44
  84. data/spec/server/pipelining_spec.rb +0 -110
  85. data/spec/server/robustness_spec.rb +0 -34
  86. data/spec/server/stopping_spec.rb +0 -55
  87. data/spec/server/swiftiply.yml +0 -6
  88. data/spec/server/swiftiply_spec.rb +0 -32
  89. data/spec/server/tcp_spec.rb +0 -47
  90. data/spec/server/threaded_spec.rb +0 -27
  91. data/spec/server/unix_socket_spec.rb +0 -26
  92. data/spec/server_spec.rb +0 -100
  93. data/spec/spec_helper.rb +0 -234
  94. data/tasks/announce.rake +0 -22
  95. data/tasks/deploy.rake +0 -13
  96. data/tasks/email.erb +0 -27
  97. data/tasks/gem.rake +0 -65
  98. data/tasks/rdoc.rake +0 -25
  99. data/tasks/site.rake +0 -15
  100. data/tasks/spec.rake +0 -43
  101. data/tasks/stats.rake +0 -28
data/CHANGELOG CHANGED
@@ -1,3 +1,11 @@
1
+ == 1.4.0 Chromeo
2
+ * kill -USR1 $PID for log rotation [catwell].
3
+ * Fix HUP signal being reseted after deamonization [atotic].
4
+ * Fix error with nil addresses in Connection#socket_address.
5
+
6
+ == 1.3.2 Low-bar Squat
7
+ * Remove mack and halcyon Rack adapters from automatic detection.
8
+
1
9
  == 1.3.1 Triple Espresso
2
10
  * Fix service not working pre 1.9.
3
11
 
@@ -0,0 +1,83 @@
1
+ Thin
2
+ ====
3
+
4
+ Tiny, fast & funny HTTP server
5
+
6
+ Thin is a Ruby web server that glues together 3 of the best Ruby libraries in web history:
7
+
8
+ * The Mongrel parser: the root of Mongrel speed and security
9
+ * Event Machine: a network I/O library with extremely high scalability, performance and stability
10
+ * Rack: a minimal interface between webservers and Ruby frameworks
11
+
12
+ Which makes it, with all humility, the most secure, stable, fast and extensible Ruby web server
13
+ bundled in an easy to use gem for your own pleasure.
14
+
15
+ Site: http://code.macournoyer.com/thin/
16
+ Group: http://groups.google.com/group/thin-ruby/topics
17
+ Bugs: http://github.com/macournoyer/thin/issues
18
+ Code: http://github.com/macournoyer/thin
19
+ IRC: #thin on freenode
20
+
21
+ Installation
22
+ ============
23
+ For the latest stable version:
24
+
25
+ `gem install thin`
26
+
27
+ Or from source:
28
+
29
+ ```
30
+ git clone git://github.com/macournoyer/thin.git
31
+ cd thin
32
+ rake install
33
+ ```
34
+
35
+
36
+ Usage
37
+ =====
38
+ A +thin+ script offers an easy way to start your Rack application:
39
+
40
+ ```
41
+ cd to/your/app
42
+ thin start
43
+ ```
44
+
45
+ But Thin is also usable with a Rack config file.
46
+ You need to setup a config.ru file and pass it to the thin script:
47
+
48
+ ```ruby
49
+ #cat config.ru
50
+ app = proc do |env|
51
+ [
52
+ 200,
53
+ {
54
+ 'Content-Type' => 'text/html',
55
+ 'Content-Length' => '2'
56
+ },
57
+ ['hi']
58
+ ]
59
+ end
60
+
61
+ run app
62
+ ```
63
+
64
+ ` thin start -R config.ru `
65
+
66
+ See example directory for more samples and run 'thin -h' for usage.
67
+
68
+ License
69
+ =======
70
+ Ruby License, http://www.ruby-lang.org/en/LICENSE.txt.
71
+
72
+ Credits
73
+ =======
74
+ The parser was stolen from Mongrel http://mongrel.rubyforge.org by Zed Shaw.
75
+ Mongrel Web Server (Mongrel) is copyrighted free software by Zed A. Shaw
76
+ <zedshaw at zedshaw dot com> You can redistribute it and/or modify it under
77
+ either the terms of the GPL.
78
+
79
+ Thin is copyright Marc-Andre Cournoyer <macournoyer@gmail.com>
80
+
81
+ Get help at http://groups.google.com/group/thin-ruby/
82
+ Report bugs at https://github.com/macournoyer/thin/issues
83
+ and major security issues directly to me macournoyer@gmail.com.
data/Rakefile CHANGED
@@ -1,44 +1,21 @@
1
- RUBY_1_9 = RUBY_VERSION =~ /^1\.9/
2
- WIN = (RUBY_PLATFORM =~ /mswin|cygwin/)
3
- SUDO = (WIN ? "" : "sudo")
4
-
5
1
  require 'rake'
6
2
  require 'rake/clean'
7
- require 'rake/extensiontask' # from rake-compiler gem
8
-
9
- $: << File.join(File.dirname(__FILE__), 'lib')
10
- require 'thin/version'
3
+ load 'thin.gemspec'
11
4
 
12
5
  # Load tasks in tasks/
13
6
  Dir['tasks/**/*.rake'].each { |rake| load rake }
14
7
 
15
8
  task :default => :spec
16
9
 
17
- Rake::ExtensionTask.new('thin_parser', Thin::GemSpec) do |ext|
18
- # enable cross compilation (requires cross compile toolchain)
19
- ext.cross_compile = true
20
-
21
- # forces the Windows platform instead of the default one
22
- # configure options only for cross compile
23
- ext.cross_platform = %w( i386-mswin32 x86-mingw32 )
24
- end
25
-
26
- CLEAN.include %w(**/*.{o,bundle,jar,so,obj,pdb,lib,def,exp,log} ext/*/Makefile ext/*/conftest.dSYM lib/1.{8,9}})
27
-
28
- desc "Compile the Ragel state machines"
29
- task :ragel do
30
- Dir.chdir 'ext/thin_parser' do
31
- target = "parser.c"
32
- File.unlink target if File.exist? target
33
- sh "ragel parser.rl -G2 -o #{target}"
34
- raise "Failed to compile Ragel state machine" unless File.exist? target
35
- end
10
+ desc "Build gem packages"
11
+ task :build do
12
+ sh "gem build thin.gemspec"
36
13
  end
37
14
 
38
- desc "Build gem packages"
39
- task :gems do
40
- sh "rake clean gem && rake cross native gem RUBY_CC_VERSION=1.8.6:1.9.1"
15
+ desc "Push gem packages"
16
+ task :push => :build do
17
+ sh "gem push thin-*.gem"
41
18
  end
42
19
 
43
- desc "Release version #{Thin::VERSION::STRING} gems to rubyforge"
44
- task :release => [:tag, "gem:push"]
20
+ desc "Release version #{Thin::VERSION::STRING}"
21
+ task :release => [:tag, :push]
@@ -53,7 +53,7 @@ configuration is set via the thin_* variables.".cleanup
53
53
  desc "Restart the app servers"
54
54
 
55
55
  remote_task :start_app, :roles => :app do
56
- run thin("restart -s #{thin_servers}")
56
+ run thin("restart -O -s #{thin_servers}")
57
57
  end
58
58
 
59
59
  desc "Stop the app servers"
@@ -11,10 +11,7 @@ module Rack
11
11
  [:rack, 'config.ru'],
12
12
  [:rails, 'config/environment.rb'],
13
13
  [:ramaze, 'start.rb'],
14
- [:halcyon, 'runner.ru'],
15
14
  [:merb, 'config/init.rb'],
16
- [:mack, 'config/app_config/default.yml'],
17
- [:mack, 'config/configatron/default.rb'],
18
15
  [:file, nil]
19
16
  ]
20
17
 
@@ -66,19 +63,6 @@ module Rack
66
63
 
67
64
  return Merb::Rack::Application.new
68
65
 
69
- when :halcyon
70
- require 'halcyon'
71
-
72
- $:.unshift(Halcyon.root/'lib')
73
-
74
- return Halcyon::Runner.new
75
-
76
- when :mack
77
- ENV["MACK_ENV"] = options[:environment]
78
- load(::File.join(options[:chdir], "Rakefile"))
79
- require 'mack'
80
- return Mack::Utils::Server.build_app
81
-
82
66
  when :file
83
67
  return Rack::File.new(options[:chdir])
84
68
 
@@ -8,40 +8,38 @@ require 'eventmachine'
8
8
  require 'rack'
9
9
 
10
10
  module Thin
11
- ROOT = File.expand_path(File.dirname(__FILE__))
12
-
13
- autoload :Command, "#{ROOT}/thin/command"
14
- autoload :Connection, "#{ROOT}/thin/connection"
15
- autoload :Daemonizable, "#{ROOT}/thin/daemonizing"
16
- autoload :Logging, "#{ROOT}/thin/logging"
17
- autoload :Headers, "#{ROOT}/thin/headers"
18
- autoload :Request, "#{ROOT}/thin/request"
19
- autoload :Response, "#{ROOT}/thin/response"
20
- autoload :Runner, "#{ROOT}/thin/runner"
21
- autoload :Server, "#{ROOT}/thin/server"
22
- autoload :Stats, "#{ROOT}/thin/stats"
11
+ autoload :Command, "thin/command"
12
+ autoload :Connection, "thin/connection"
13
+ autoload :Daemonizable, "thin/daemonizing"
14
+ autoload :Logging, "thin/logging"
15
+ autoload :Headers, "thin/headers"
16
+ autoload :Request, "thin/request"
17
+ autoload :Response, "thin/response"
18
+ autoload :Runner, "thin/runner"
19
+ autoload :Server, "thin/server"
20
+ autoload :Stats, "thin/stats"
23
21
 
24
22
  module Backends
25
- autoload :Base, "#{ROOT}/thin/backends/base"
26
- autoload :SwiftiplyClient, "#{ROOT}/thin/backends/swiftiply_client"
27
- autoload :TcpServer, "#{ROOT}/thin/backends/tcp_server"
28
- autoload :UnixServer, "#{ROOT}/thin/backends/unix_server"
23
+ autoload :Base, "thin/backends/base"
24
+ autoload :SwiftiplyClient, "thin/backends/swiftiply_client"
25
+ autoload :TcpServer, "thin/backends/tcp_server"
26
+ autoload :UnixServer, "thin/backends/unix_server"
29
27
  end
30
28
 
31
29
  module Controllers
32
- autoload :Cluster, "#{ROOT}/thin/controllers/cluster"
33
- autoload :Controller, "#{ROOT}/thin/controllers/controller"
34
- autoload :Service, "#{ROOT}/thin/controllers/service"
30
+ autoload :Cluster, "thin/controllers/cluster"
31
+ autoload :Controller, "thin/controllers/controller"
32
+ autoload :Service, "thin/controllers/service"
35
33
  end
36
34
  end
37
35
 
38
- require "#{Thin::ROOT}/thin/version"
39
- require "#{Thin::ROOT}/thin/statuses"
40
- require "#{Thin::ROOT}/rack/adapter/loader"
41
- require "#{Thin::ROOT}/thin_parser"
36
+ require "thin/version"
37
+ require "thin/statuses"
38
+ require "rack/adapter/loader"
39
+ require "thin_parser"
42
40
 
43
41
  module Rack
44
42
  module Adapter
45
- autoload :Rails, "#{Thin::ROOT}/rack/adapter/rails"
43
+ autoload :Rails, "rack/adapter/rails"
46
44
  end
47
45
  end
@@ -44,6 +44,8 @@ module Thin
44
44
  @maximum_connections = Server::DEFAULT_MAXIMUM_CONNECTIONS
45
45
  @maximum_persistent_connections = Server::DEFAULT_MAXIMUM_PERSISTENT_CONNECTIONS
46
46
  @no_epoll = false
47
+ @ssl = nil
48
+ @threaded = nil
47
49
  end
48
50
 
49
51
  # Start the backend and connect it.
@@ -146,4 +148,4 @@ module Thin
146
148
 
147
149
  end
148
150
  end
149
- end
151
+ end
@@ -6,10 +6,10 @@ module Thin
6
6
  # that is opened.
7
7
  class Connection < EventMachine::Connection
8
8
  include Logging
9
-
9
+
10
10
  # This is a template async response. N.B. Can't use string for body on 1.9
11
11
  AsyncResponse = [-1, {}, []].freeze
12
-
12
+
13
13
  # Rack application (adapter) served by this connection.
14
14
  attr_accessor :app
15
15
 
@@ -25,7 +25,7 @@ module Thin
25
25
  # Calling the application in a threaded allowing
26
26
  # concurrent processing of requests.
27
27
  attr_writer :threaded
28
-
28
+
29
29
  # Get the connection ready to process a request.
30
30
  def post_init
31
31
  @request = Request.new
@@ -59,13 +59,13 @@ module Thin
59
59
  @request.remote_address = remote_address
60
60
 
61
61
  # Connection may be closed unless the App#call response was a [-1, ...]
62
- # It should be noted that connection objects will linger until this
62
+ # It should be noted that connection objects will linger until this
63
63
  # callback is no longer referenced, so be tidy!
64
64
  @request.async_callback = method(:post_process)
65
-
65
+
66
66
  if @backend.ssl?
67
67
  @request.env["rack.url_scheme"] = "https"
68
-
68
+
69
69
  if cert = get_peer_cert
70
70
  @request.env['rack.peer_cert'] = cert
71
71
  end
@@ -89,7 +89,7 @@ module Thin
89
89
  def post_process(result)
90
90
  return unless result
91
91
  result = result.to_a
92
-
92
+
93
93
  # Status code -1 indicates that we're going to respond later (async).
94
94
  return if result.first == AsyncResponse.first
95
95
 
@@ -190,7 +190,8 @@ module Thin
190
190
  protected
191
191
  # Returns IP address of peer as a string.
192
192
  def socket_address
193
- Socket.unpack_sockaddr_in(get_peername)[1]
193
+ peer = get_peername
194
+ Socket.unpack_sockaddr_in(peer)[1] if peer
194
195
  end
195
196
  end
196
197
  end
@@ -21,7 +21,7 @@ module Thin
21
21
  # Handle stuff like:
22
22
  # * storing the PID in a file
23
23
  # * redirecting output to the log file
24
- # * changing processs privileges
24
+ # * changing process privileges
25
25
  # * killing the process gracefully
26
26
  module Daemonizable
27
27
  attr_accessor :pid_file, :log_file
@@ -53,6 +53,8 @@ module Thin
53
53
  Dir.chdir(pwd)
54
54
 
55
55
  write_pid_file
56
+
57
+ self.after_daemonize if self.respond_to? :after_daemonize
56
58
 
57
59
  at_exit do
58
60
  log ">> Exiting!"
@@ -46,7 +46,7 @@ module Thin
46
46
 
47
47
  # Log an error backtrace if debugging is activated
48
48
  def log_error(e=$!)
49
- STDERR.print("#{e}\n\t" + e.backtrace.join("\n\t")) if Logging.debug?
49
+ STDERR.print("#{e}\n\t" + e.backtrace.join("\n\t") + "\n") if Logging.debug?
50
50
  end
51
51
  module_function :log_error
52
52
  public :log_error
@@ -1,39 +1,39 @@
1
1
  require 'optparse'
2
2
  require 'yaml'
3
3
 
4
- module Thin
4
+ module Thin
5
5
  # CLI runner.
6
6
  # Parse options and send command to the correct Controller.
7
7
  class Runner
8
8
  COMMANDS = %w(start stop restart config)
9
9
  LINUX_ONLY_COMMANDS = %w(install)
10
-
10
+
11
11
  # Commands that wont load options from the config file
12
12
  CONFIGLESS_COMMANDS = %w(config install)
13
-
13
+
14
14
  # Parsed options
15
15
  attr_accessor :options
16
-
16
+
17
17
  # Name of the command to be runned.
18
18
  attr_accessor :command
19
-
19
+
20
20
  # Arguments to be passed to the command.
21
21
  attr_accessor :arguments
22
-
22
+
23
23
  # Return all available commands
24
24
  def self.commands
25
25
  commands = COMMANDS
26
26
  commands += LINUX_ONLY_COMMANDS if Thin.linux?
27
27
  commands
28
28
  end
29
-
29
+
30
30
  def initialize(argv)
31
31
  @argv = argv
32
-
32
+
33
33
  # Default options values
34
34
  @options = {
35
35
  :chdir => Dir.pwd,
36
- :environment => 'development',
36
+ :environment => ENV['RACK_ENV'] || 'development',
37
37
  :address => '0.0.0.0',
38
38
  :port => Server::DEFAULT_PORT,
39
39
  :timeout => Server::DEFAULT_TIMEOUT,
@@ -44,10 +44,10 @@ module Thin
44
44
  :require => [],
45
45
  :wait => Controllers::Cluster::DEFAULT_WAIT_TIME
46
46
  }
47
-
47
+
48
48
  parse!
49
49
  end
50
-
50
+
51
51
  def parser
52
52
  # NOTE: If you add an option here make sure the key in the +options+ hash is the
53
53
  # same as the name of the command line option.
@@ -81,26 +81,26 @@ module Thin
81
81
 
82
82
  opts.separator ""
83
83
  opts.separator "Adapter options:"
84
- opts.on("-e", "--environment ENV", "Framework environment " +
84
+ opts.on("-e", "--environment ENV", "Framework environment " +
85
85
  "(default: #{@options[:environment]})") { |env| @options[:environment] = env }
86
86
  opts.on( "--prefix PATH", "Mount the app under PATH (start with /)") { |path| @options[:prefix] = path }
87
-
87
+
88
88
  unless Thin.win? # Daemonizing not supported on Windows
89
89
  opts.separator ""
90
90
  opts.separator "Daemon options:"
91
-
91
+
92
92
  opts.on("-d", "--daemonize", "Run daemonized in the background") { @options[:daemonize] = true }
93
- opts.on("-l", "--log FILE", "File to redirect output " +
93
+ opts.on("-l", "--log FILE", "File to redirect output " +
94
94
  "(default: #{@options[:log]})") { |file| @options[:log] = file }
95
- opts.on("-P", "--pid FILE", "File to store PID " +
95
+ opts.on("-P", "--pid FILE", "File to store PID " +
96
96
  "(default: #{@options[:pid]})") { |file| @options[:pid] = file }
97
97
  opts.on("-u", "--user NAME", "User to run daemon as (use with -g)") { |user| @options[:user] = user }
98
98
  opts.on("-g", "--group NAME", "Group to run daemon as (use with -u)") { |group| @options[:group] = group }
99
99
  opts.on( "--tag NAME", "Additional text to display in process listing") { |tag| @options[:tag] = tag }
100
-
100
+
101
101
  opts.separator ""
102
- opts.separator "Cluster options:"
103
-
102
+ opts.separator "Cluster options:"
103
+
104
104
  opts.on("-s", "--servers NUM", "Number of servers to start") { |num| @options[:servers] = num.to_i }
105
105
  opts.on("-o", "--only NUM", "Send command to only one server of the cluster") { |only| @options[:only] = only.to_i }
106
106
  opts.on("-C", "--config FILE", "Load options from config file") { |file| @options[:config] = file }
@@ -108,12 +108,12 @@ module Thin
108
108
  opts.on("-O", "--onebyone", "Restart the cluster one by one (only works with restart command)") { @options[:onebyone] = true }
109
109
  opts.on("-w", "--wait NUM", "Maximum wait time for server to be started in seconds (use with -O)") { |time| @options[:wait] = time.to_i }
110
110
  end
111
-
111
+
112
112
  opts.separator ""
113
113
  opts.separator "Tuning options:"
114
-
114
+
115
115
  opts.on("-b", "--backend CLASS", "Backend to use, full classname") { |name| @options[:backend] = name }
116
- opts.on("-t", "--timeout SEC", "Request or command timeout in sec " +
116
+ opts.on("-t", "--timeout SEC", "Request or command timeout in sec " +
117
117
  "(default: #{@options[:timeout]})") { |sec| @options[:timeout] = sec.to_i }
118
118
  opts.on("-f", "--force", "Force the execution of the command") { @options[:force] = true }
119
119
  opts.on( "--max-conns NUM", "Maximum number of open file descriptors " +
@@ -125,7 +125,7 @@ module Thin
125
125
  opts.on( "--threaded", "Call the Rack application in threads " +
126
126
  "[experimental]") { @options[:threaded] = true }
127
127
  opts.on( "--no-epoll", "Disable the use of epoll") { @options[:no_epoll] = true } if Thin.linux?
128
-
128
+
129
129
  opts.separator ""
130
130
  opts.separator "Common options:"
131
131
 
@@ -136,14 +136,14 @@ module Thin
136
136
  opts.on_tail('-v', '--version', "Show version") { puts Thin::SERVER; exit }
137
137
  end
138
138
  end
139
-
139
+
140
140
  # Parse the options.
141
141
  def parse!
142
142
  parser.parse! @argv
143
143
  @command = @argv.shift
144
144
  @arguments = @argv
145
145
  end
146
-
146
+
147
147
  # Parse the current shell arguments and run the command.
148
148
  # Exits on error.
149
149
  def run!
@@ -152,34 +152,34 @@ module Thin
152
152
  elsif @command.nil?
153
153
  puts "Command required"
154
154
  puts @parser
155
- exit 1
155
+ exit 1
156
156
  else
157
157
  abort "Unknown command: #{@command}. Use one of #{self.class.commands.join(', ')}"
158
158
  end
159
159
  end
160
-
160
+
161
161
  # Send the command to the controller: single instance or cluster.
162
162
  def run_command
163
163
  load_options_from_config_file! unless CONFIGLESS_COMMANDS.include?(@command)
164
-
164
+
165
165
  # PROGRAM_NAME is relative to the current directory, so make sure
166
166
  # we store and expand it before changing directory.
167
167
  Command.script = File.expand_path($PROGRAM_NAME)
168
-
168
+
169
169
  # Change the current directory ASAP so that all relative paths are
170
170
  # relative to this one.
171
171
  Dir.chdir(@options[:chdir]) unless CONFIGLESS_COMMANDS.include?(@command)
172
-
172
+
173
173
  @options[:require].each { |r| ruby_require r }
174
174
  Logging.debug = @options[:debug]
175
175
  Logging.trace = @options[:trace]
176
-
176
+
177
177
  controller = case
178
178
  when cluster? then Controllers::Cluster.new(@options)
179
179
  when service? then Controllers::Service.new(@options)
180
180
  else Controllers::Controller.new(@options)
181
181
  end
182
-
182
+
183
183
  if controller.respond_to?(@command)
184
184
  begin
185
185
  controller.send(@command, *@arguments)
@@ -190,24 +190,24 @@ module Thin
190
190
  abort "Invalid options for command: #{@command}"
191
191
  end
192
192
  end
193
-
193
+
194
194
  # +true+ if we're controlling a cluster.
195
195
  def cluster?
196
196
  @options[:only] || @options[:servers] || @options[:config]
197
197
  end
198
-
198
+
199
199
  # +true+ if we're acting a as system service.
200
200
  def service?
201
201
  @options.has_key?(:all) || @command == 'install'
202
202
  end
203
-
203
+
204
204
  private
205
205
  def load_options_from_config_file!
206
206
  if file = @options.delete(:config)
207
207
  YAML.load_file(file).each { |key, value| @options[key.to_sym] = value }
208
208
  end
209
209
  end
210
-
210
+
211
211
  def ruby_require(file)
212
212
  if File.extname(file) == '.ru'
213
213
  warn 'WARNING: Use the -R option to load a Rack config file'