thin-preforker 0.0.1

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.
data/CHANGELOG ADDED
@@ -0,0 +1,2 @@
1
+ == 0.0.1
2
+ * First alphaish version.
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in thin-preforker.gemspec
4
+ gemspec
5
+
6
+ group :development do
7
+ gem "rake"
8
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,16 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ thin-preforker (0.0.1)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ rake (0.9.2.2)
10
+
11
+ PLATFORMS
12
+ ruby
13
+
14
+ DEPENDENCIES
15
+ rake
16
+ thin-preforker!
data/LICENSE ADDED
@@ -0,0 +1,7 @@
1
+ Copyright (C) 2012 Rafael Gaspar.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
File without changes
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # Thin command line interface script.
3
+ # Run <tt>thin-preforker -h</tt> to get more usage.
4
+
5
+ require 'thin/preforker'
6
+ Thin::Preforker::Runner.new(ARGV).run!
@@ -0,0 +1,148 @@
1
+ module Thin
2
+ module Preforker
3
+ class Controller < Thin::Controllers::Cluster
4
+ def initialize *args
5
+ super
6
+
7
+ GC.copy_on_write_friendly = true if GC.respond_to?(:copy_on_write_friendly=)
8
+ end
9
+
10
+ # Start the servers
11
+ def start
12
+ with_each_server do |n|
13
+ start_server n, app
14
+ sleep 0.1 # Let the OS breath
15
+ end
16
+ end
17
+
18
+ # Start a single server
19
+ def start_server(number, app)
20
+ log "Starting server on #{server_id(number)} ... "
21
+
22
+ # Save the log files
23
+ logs = logs_to_reopen
24
+
25
+ # Force GC to collect before forking
26
+ GC.start
27
+
28
+ fork do
29
+ $stdout.reopen($stdout)
30
+ $stderr.reopen($stderr)
31
+ $stdin.reopen("/dev/null")
32
+
33
+ # Constantize backend class
34
+ server_options_for(number)[:backend] = eval(server_options_for(number)[:backend], TOPLEVEL_BINDING) if server_options_for(number)[:backend]
35
+
36
+ server = Thin::Server.new(server_options_for(number)[:socket] || server_options_for(number)[:address], # Server detects kind of socket
37
+ server_options_for(number)[:port], # Port ignored on UNIX socket
38
+ server_options_for(number))
39
+
40
+ # Set options
41
+ server.pid_file = server_options_for(number)[:pid]
42
+ server.log_file = server_options_for(number)[:log]
43
+ server.timeout = server_options_for(number)[:timeout]
44
+ server.maximum_connections = server_options_for(number)[:max_conns]
45
+ server.maximum_persistent_connections = server_options_for(number)[:max_persistent_conns]
46
+ server.threaded = server_options_for(number)[:threaded]
47
+ server.no_epoll = server_options_for(number)[:no_epoll] if server.backend.respond_to?(:no_epoll=)
48
+
49
+ # ssl support
50
+ if server_options_for(number)[:ssl]
51
+ server.ssl = true
52
+ server.ssl_options = { :private_key_file => server_options_for(number)[:ssl_key_file], :cert_chain_file => server_options_for(number)[:ssl_cert_file], :verify_peer => server_options_for(number)[:ssl_verify] }
53
+ end
54
+
55
+ # Detach the process, after this line the current process returns
56
+ server.daemonize if server_options_for(number)[:daemonize]
57
+
58
+ # +config+ must be called before changing privileges since it might require superuser power.
59
+ server.config
60
+
61
+ server.change_privilege server_options_for(number)[:user], server_options_for(number)[:group] if server_options_for(number)[:user] && server_options_for(number)[:group]
62
+
63
+ # Set app already loaded
64
+ server.app = app
65
+
66
+ # If a prefix is required, wrap in Rack URL mapper
67
+ server.app = Rack::URLMap.new(server_options_for(number)[:prefix] => server.app) if server_options_for(number)[:prefix]
68
+
69
+ # If a stats URL is specified, wrap in Stats adapter
70
+ server.app = Thin::Stats::Adapter.new(server.app, server_options_for(number)[:stats]) if server_options_for(number)[:stats]
71
+
72
+ reopen_logs logs
73
+
74
+ server.start
75
+ end
76
+ end
77
+
78
+ # Stop the servers
79
+ def stop
80
+ with_each_server do |n|
81
+ stop_server n
82
+ end
83
+ end
84
+
85
+ # Stop a single server
86
+ def stop_server(number)
87
+ log "Stopping server on #{server_id(number)} ... "
88
+
89
+ raise Thin::OptionRequired, :pid unless @options[:pid]
90
+
91
+ tail_log(server_options_for(number)[:log]) do
92
+ if Server.kill(server_options_for(number)[:pid], server_options_for(number)[:force] ? 0 : (server_options_for(number)[:timeout] || 60))
93
+ wait_for_file :deletion, server_options_for(number)[:pid]
94
+ end
95
+ end
96
+ end
97
+
98
+ # Stop and start the servers.
99
+ def restart
100
+ app
101
+
102
+ with_each_server do |n|
103
+ stop_server n
104
+ start_server n, app
105
+ sleep 0.1 # Let the OS breath
106
+ end
107
+ end
108
+
109
+ private
110
+ def app
111
+ # If a Rack config file is specified we eval it inside a Rack::Builder block to create
112
+ # a Rack adapter from it. Or else we guess which adapter to use and load it.
113
+ @app ||= @options[:rackup] ? load_rackup_config : load_adapter
114
+ end
115
+
116
+ def server_options_for(number)
117
+ @server_options ||= {}
118
+ return @server_options[number] if @server_options[number]
119
+
120
+ # Sets the server options for this server
121
+ @server_options[number] = @options.reject { |option, value| CLUSTER_OPTIONS.include?(option) }
122
+ @server_options[number].merge!(:pid => pid_file_for(number), :log => log_file_for(number))
123
+ if socket
124
+ @server_options[number].merge!(:socket => socket_for(number))
125
+ elsif swiftiply?
126
+ @server_options[number].merge!(:port => first_port)
127
+ else
128
+ @server_options[number].merge!(:port => number)
129
+ end
130
+
131
+ return @server_options[number]
132
+ end
133
+
134
+ def logs_to_reopen
135
+ require 'fcntl'
136
+
137
+ logs = []
138
+ ObjectSpace.each_object(File) { |fp| logs << fp.path if fp.fcntl(Fcntl::F_GETFL) == File::APPEND | File::WRONLY rescue false }
139
+
140
+ logs
141
+ end
142
+
143
+ def reopen_logs logs
144
+ ObjectSpace.each_object(File) { |fp| fp.reopen(fp.path, "a") if logs.include? fp.path }
145
+ end
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,32 @@
1
+ class Thin::Preforker::Runner < Thin::Runner
2
+ # Error raised that will abort the process and print not backtrace.
3
+ class RunnerError < RuntimeError; end
4
+
5
+ def run_command
6
+ load_options_from_config_file! unless CONFIGLESS_COMMANDS.include?(@command)
7
+
8
+ # PROGRAM_NAME is relative to the current directory, so make sure
9
+ # we store and expand it before changing directory.
10
+ Thin::Command.script = File.expand_path($PROGRAM_NAME)
11
+
12
+ # Change the current directory ASAP so that all relative paths are
13
+ # relative to this one.
14
+ Dir.chdir(@options[:chdir]) unless CONFIGLESS_COMMANDS.include?(@command)
15
+
16
+ @options[:require].each { |r| ruby_require r }
17
+ Thin::Logging.debug = @options[:debug]
18
+ Thin::Logging.trace = @options[:trace]
19
+
20
+ controller = Thin::Preforker::Controller.new(@options)
21
+
22
+ if controller.respond_to?(@command)
23
+ begin
24
+ controller.send(@command, *@arguments)
25
+ rescue RunnerError => e
26
+ abort e.message
27
+ end
28
+ else
29
+ abort "Invalid options for command: #{@command}"
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,14 @@
1
+ module Thin
2
+ module Preforker
3
+ module VERSION #:nodoc:
4
+ MAJOR = 0
5
+ MINOR = 0
6
+ TINY = 1
7
+
8
+ STRING = [MAJOR, MINOR, TINY].join('.')
9
+ end
10
+
11
+ NAME = 'thin-preforker'.freeze
12
+ SERVER = "#{NAME} #{VERSION::STRING}".freeze
13
+ end
14
+ end
@@ -0,0 +1,8 @@
1
+ module Thin
2
+ module Preforker
3
+ autoload :Controller, "thin/preforker/controller"
4
+ autoload :Runner, "thin/preforker/runner"
5
+ end
6
+ end
7
+
8
+ require "thin/preforker/version"
@@ -0,0 +1,21 @@
1
+ # Maintain your gem's version:
2
+ require File.expand_path('../lib/thin/preforker/version', __FILE__)
3
+
4
+ # Describe your gem and declare its dependencies:
5
+ Gem::Specification.new do |spec|
6
+ spec.name = Thin::Preforker::NAME
7
+ spec.version = Thin::Preforker::VERSION::STRING
8
+ spec.description = "A thin controller and spawner with prefork"
9
+ spec.summary = "A thin controller and spawner with prefork"
10
+
11
+ spec.author = "Rafael Gaspar"
12
+ spec.email = 'rafael.gaspar@me.com'
13
+ spec.homepage = 'http://github.com/rafaelgaspar/thin-preforker/'
14
+
15
+ spec.license = 'MIT'
16
+
17
+ spec.files = `git ls-files`.split($\)
18
+ spec.executables = spec.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.require_paths = ["lib"]
21
+ end
metadata ADDED
@@ -0,0 +1,64 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: thin-preforker
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Rafael Gaspar
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-07-10 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: A thin controller and spawner with prefork
15
+ email: rafael.gaspar@me.com
16
+ executables:
17
+ - thin-preforker
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - CHANGELOG
22
+ - Gemfile
23
+ - Gemfile.lock
24
+ - LICENSE
25
+ - README.md
26
+ - Rakefile
27
+ - bin/thin-preforker
28
+ - lib/thin/preforker.rb
29
+ - lib/thin/preforker/controller.rb
30
+ - lib/thin/preforker/runner.rb
31
+ - lib/thin/preforker/version.rb
32
+ - thin-preforker.gemspec
33
+ homepage: http://github.com/rafaelgaspar/thin-preforker/
34
+ licenses:
35
+ - MIT
36
+ post_install_message:
37
+ rdoc_options: []
38
+ require_paths:
39
+ - lib
40
+ required_ruby_version: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ segments:
47
+ - 0
48
+ hash: -4544492274511813298
49
+ required_rubygems_version: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ segments:
56
+ - 0
57
+ hash: -4544492274511813298
58
+ requirements: []
59
+ rubyforge_project:
60
+ rubygems_version: 1.8.10
61
+ signing_key:
62
+ specification_version: 3
63
+ summary: A thin controller and spawner with prefork
64
+ test_files: []