thin 1.3.1 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
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'