mongrel_cow_cluster 0.3.5

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.
@@ -0,0 +1,5 @@
1
+ v0.3.5 fix default timeout to match Mongrel default; respect "num_procs" for mongrel_cluster compatibility
2
+ v0.3.4 load configuration file before validation
3
+ v0.3.3 respect "address" in config for mongrel_cluster compatibility
4
+ v0.3.1 bind to a random port on 127.0.0.1 to preload Rails
5
+ v0.3.0 rolling_interval option added to delay between member restarts
data/LICENSE ADDED
@@ -0,0 +1,56 @@
1
+ cow_cluster is copyrighted free software by Eric Wong <normalperson@yhbt.net>.
2
+ You can redistribute it and/or modify it under either the terms of the GPL
3
+ version 2 (see the file GPL), or the conditions below:
4
+
5
+ 1. You may make and give away verbatim copies of the source form of the
6
+ software without restriction, provided that you duplicate all of the
7
+ original copyright notices and associated disclaimers.
8
+
9
+ 2. You may modify your copy of the software in any way, provided that
10
+ you do at least ONE of the following:
11
+
12
+ a) place your modifications in the Public Domain or otherwise
13
+ make them Freely Available, such as by posting said
14
+ modifications to Usenet or an equivalent medium, or by allowing
15
+ the author to include your modifications in the software.
16
+
17
+ b) use the modified software only within your corporation or
18
+ organization.
19
+
20
+ c) give non-standard binaries non-standard names, with
21
+ instructions on where to get the original software distribution.
22
+
23
+ d) make other distribution arrangements with the author.
24
+
25
+ 3. You may distribute the software in object code or binary form,
26
+ provided that you do at least ONE of the following:
27
+
28
+ a) distribute the binaries and library files of the software,
29
+ together with instructions (in the manual page or equivalent)
30
+ on where to get the original distribution.
31
+
32
+ b) accompany the distribution with the machine-readable source of
33
+ the software.
34
+
35
+ c) give non-standard binaries non-standard names, with
36
+ instructions on where to get the original software distribution.
37
+
38
+ d) make other distribution arrangements with the author.
39
+
40
+ 4. You may modify and include the part of the software into any other
41
+ software (possibly commercial). But some files in the distribution
42
+ are not written by the author, so that they are not under these terms.
43
+
44
+ For the list of those files and their copying conditions, see the
45
+ file LEGAL.
46
+
47
+ 5. The scripts and library files supplied as input to or produced as
48
+ output from the software do not automatically fall under the
49
+ copyright of the software, but belong to whomever generated them,
50
+ and may be sold commercially, and may be aggregated with this
51
+ software.
52
+
53
+ 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
54
+ IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
55
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
56
+ PURPOSE.
@@ -0,0 +1,7 @@
1
+ CHANGELOG
2
+ README
3
+ Manifest
4
+ LICENSE
5
+ lib/mongrel_cow_cluster/init.rb
6
+ resources/defaults.yaml
7
+ tools/rakehelp.rb
data/README ADDED
@@ -0,0 +1,133 @@
1
+ MongrelCowCluster
2
+ by Eric Wong <normalperson@yhbt.net>
3
+ FIX (http://rubyforge.org/projects/mongrel-cow/)
4
+
5
+ == DESCRIPTION:
6
+
7
+ A faster, Rails-only replacement for mongrel_cluster
8
+
9
+ Uses copy-on-write fork() to drastically reduce startup times when
10
+ starting mongrel server. This means all of the Rails and environment
11
+ code is read and loaded _once_ and forked N times where N is the number
12
+ of ports one wishes to bind to.
13
+
14
+ It is very similar to mongrel_cluster in use and can use config files
15
+ generated for mongrel_cluster. This still creates pid and log files
16
+ that are similar to those used by mongrel_cluster (mongrel.<port>.log
17
+ and mongrel.<port>.pid).
18
+
19
+ All children are independent of each other and the death of one will
20
+ not influence another. The parent process dies as soon as the final
21
+ child is spawned.
22
+
23
+ Unlike traditional non-Ruby applications that use copy-on-write fork()
24
+ to save memory, do NOT expect any significant memory savings even though
25
+ this uses copy-on-write(), since the Ruby GC will trigger writes on
26
+ whatever pages it marks. The main performance benefit of this is that
27
+ the application code can be parsed once and reused.
28
+
29
+ If you connect to any other databases or services at Rails startup, you
30
+ will need to re-init them manually. The default ActiveRecord::Base
31
+ connection provided by Rails is disconnected after Rails is loaded
32
+ and restarted/reconnected in each child process.
33
+
34
+
35
+ == FEATURES/PROBLEMS:
36
+
37
+ Rolling restarts:
38
+
39
+ Although machines are all issued cow_cluster restart commands at
40
+ the same time (by Capistrano), each individual mongrel process
41
+ will be restarted independently of the others. This means that
42
+ (assuming this works correctly :), only ONE mongrel process
43
+ per machine will be down at any given time. This makes life
44
+ a lot easier for the Apache proxies (which will failover to
45
+ the next available port) and *should* be completely transparent
46
+ to the end user.
47
+
48
+ We now also check for successful startup of each individual port
49
+ by issuing an HTTP GET on "/" and report back to the person
50
+ running cow_cluster if that server has been successfully
51
+ started.
52
+
53
+ Daemonization is handled internally by cow_cluster since
54
+ Daemons::Daemonize (used by Mongrel) does too many things behind
55
+ our back wrt closing AR:B connections and redirecting log
56
+ files of the managing process.
57
+
58
+ == SYNOPSIS:
59
+
60
+ Start:
61
+ mongrel_rails cow_cluster::start -C config/mongrel_cluster.yml
62
+ Stop:
63
+ mongrel_rails cow_cluster::stop -C config/mongrel_cluster.yml
64
+ Restart:
65
+ mongrel_rails cow_cluster::restart -C config/mongrel_cluster.yml
66
+
67
+ == REQUIREMENTS:
68
+
69
+ gem_plugin >= 0.2.2
70
+ mongrel >= 1.0.1
71
+
72
+ == INSTALL:
73
+
74
+ sudo gem install mongrel_cow_cluster
75
+
76
+ == LICENSE:
77
+
78
+ cow_cluster is copyrighted free software by Eric Wong <normalperson@yhbt.net>.
79
+ You can redistribute it and/or modify it under either the terms of the GPL
80
+ version 2 (see the file GPL), or the conditions below:
81
+
82
+ 1. You may make and give away verbatim copies of the source form of the
83
+ software without restriction, provided that you duplicate all of the
84
+ original copyright notices and associated disclaimers.
85
+
86
+ 2. You may modify your copy of the software in any way, provided that
87
+ you do at least ONE of the following:
88
+
89
+ a) place your modifications in the Public Domain or otherwise
90
+ make them Freely Available, such as by posting said
91
+ modifications to Usenet or an equivalent medium, or by allowing
92
+ the author to include your modifications in the software.
93
+
94
+ b) use the modified software only within your corporation or
95
+ organization.
96
+
97
+ c) give non-standard binaries non-standard names, with
98
+ instructions on where to get the original software distribution.
99
+
100
+ d) make other distribution arrangements with the author.
101
+
102
+ 3. You may distribute the software in object code or binary form,
103
+ provided that you do at least ONE of the following:
104
+
105
+ a) distribute the binaries and library files of the software,
106
+ together with instructions (in the manual page or equivalent)
107
+ on where to get the original distribution.
108
+
109
+ b) accompany the distribution with the machine-readable source of
110
+ the software.
111
+
112
+ c) give non-standard binaries non-standard names, with
113
+ instructions on where to get the original software distribution.
114
+
115
+ d) make other distribution arrangements with the author.
116
+
117
+ 4. You may modify and include the part of the software into any other
118
+ software (possibly commercial). But some files in the distribution
119
+ are not written by the author, so that they are not under these terms.
120
+
121
+ For the list of those files and their copying conditions, see the
122
+ file LEGAL.
123
+
124
+ 5. The scripts and library files supplied as input to or produced as
125
+ output from the software do not automatically fall under the
126
+ copyright of the software, but belong to whomever generated them,
127
+ and may be sold commercially, and may be aggregated with this
128
+ software.
129
+
130
+ 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
131
+ IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
132
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
133
+ PURPOSE.
@@ -0,0 +1,437 @@
1
+ # Copyright (c) 2007 Eric Wong
2
+ # Based on code from Mongrel, Copyright (c) 2005 Zed A. Shaw
3
+ #
4
+ # You can redistribute it and/or modify it under the same terms as Ruby.
5
+ #
6
+ # Additional work donated by contributors.
7
+ # See http://mongrel.rubyforge.org/attributions.html for more information.
8
+
9
+ require 'gem_plugin'
10
+ require 'mongrel'
11
+ require 'net/http'
12
+
13
+ module Cow_Cluster
14
+ module Base
15
+
16
+ def read_options(settings)
17
+ if @config_file
18
+ settings.merge!(config_settings = YAML.load_file(@config_file))
19
+ # symbolize keys, mongrel_cluster uses string keys :(
20
+ keys = settings.keys.collect { |k| k.kind_of?(Symbol) ? nil : k }
21
+ keys.compact.each { |k| settings[k.to_sym] = settings.delete(k) }
22
+ STDERR.puts "** Loading settings from #{@config_file} " +
23
+ "(they override command line)."
24
+ if settings[:address] && ! config_settings[:host]
25
+ settings[:host] = settings[:address]
26
+ end
27
+ settings.each { |k,v| instance_variable_set("@#{k.to_s}", v) }
28
+ end
29
+
30
+ @file = { :pid => {}, :log => {} }
31
+ @file.keys.each { |f|
32
+ x = "#{f.to_s}_file".to_sym
33
+ next unless settings[x]
34
+ @file[f][:ext] = File.extname(settings[x])
35
+ @file[f][:base] = File.basename(settings[x], @file[f][:ext])
36
+ @file[f][:dir] = File.dirname(settings[x])
37
+ }
38
+ end
39
+
40
+ def each_port(settings, &block)
41
+ if settings[:only]
42
+ yield settings[:only]
43
+ else
44
+ max_port = settings[:port] + settings[:servers] - 1
45
+ (settings[:port]..max_port).each { |port|
46
+ yield port
47
+ }
48
+ end
49
+ end
50
+
51
+ def port_pid_file(port)
52
+ base = "#{@file[:pid][:base]}.#{port}#{@file[:pid][:ext]}"
53
+ File.join(@file[:pid][:dir], base)
54
+ end
55
+
56
+ def port_log_file(port)
57
+ base = "#{@file[:log][:base]}.#{port}#{@file[:log][:ext]}"
58
+ File.join(@file[:log][:dir], base)
59
+ end
60
+
61
+ def stop_options
62
+ [
63
+ ['-c', '--chdir PATH',
64
+ "Change to dir before starting (will be expanded)", :@cwd, Dir.pwd],
65
+ ['-C', '--config PATH', "Use a config file", :@config_file, nil],
66
+ ['-f', '--force', "Force the shutdown (kill -9).", :@force, false],
67
+ ['-o', '--only INT', 'Limit operation to only one port', :@only, nil ],
68
+ ['-w', '--wait SECONDS', "Wait SECONDS before forcing shutdown",
69
+ :@wait, "10"],
70
+ ['-p', '--port INT', "First port to bind to", :@port, 3000],
71
+ ['-s', '--servers INT', "Number of servers to start", :@servers, 2],
72
+ ['-P', '--pid FILE', "Where to write the PID", :@pid_file,
73
+ "log/mongrel.pid"],
74
+ ]
75
+ end
76
+
77
+ def validate_stop_options
78
+ if @config_file
79
+ valid_exists? @config_file, "Config file not there: #@config_file"
80
+ load_settings
81
+ end
82
+ @cwd = File.expand_path(@cwd)
83
+ valid_dir? @cwd, "Invalid path to change to during daemon mode: #@cwd"
84
+ Dir.chdir @cwd
85
+
86
+ @valid
87
+ end
88
+
89
+ def start_options(restart = false)
90
+ ret = [
91
+ ["-e", "--environment ENV", "Rails environment to run as",
92
+ :@environment, ENV['RAILS_ENV'] || "development"],
93
+ ['-p', '--port INT', "First port to bind to", :@port, 3000],
94
+ ['-s', '--servers INT', "Number of servers to start", :@servers, 2],
95
+ ['-a', '--address ADDR', "Address to bind to", :@address, "0.0.0.0"],
96
+ ['-l', '--log FILE', "Where to write log messages", :@log_file,
97
+ "log/mongrel.log"],
98
+ ['-P', '--pid FILE', "Where to write the PID", :@pid_file,
99
+ "log/mongrel.pid"],
100
+ ['-n', '--num-procs INT',
101
+ "Number of processors active before clients denied",
102
+ :@num_procs, 1024],
103
+ ['-t', '--timeout TIME',
104
+ "Timeout all requests after seconds time", :@timeout, 60],
105
+ ['-m', '--mime PATH', "A YAML file that lists additional MIME types",
106
+ :@mime_map, nil],
107
+ ['-c', '--chdir PATH',
108
+ "Change to dir before starting (will be expanded)", :@cwd, Dir.pwd],
109
+ ['-r', '--root PATH', "Set the document root (default 'public')",
110
+ :@docroot, "public"],
111
+ ['-B', '--debug', "Enable debugging mode", :@debug, false],
112
+ ['-C', '--config PATH', "Use a config file", :@config_file, nil],
113
+ ['-S', '--script PATH',
114
+ "Load the given file as an extra config script",
115
+ :@config_script, nil],
116
+ ['-o', '--only INT', 'Limit operation to only one port', :@only, nil ],
117
+ ['', '--user USER', "User to run as", :@user, nil],
118
+ ['', '--group GROUP', "Group to run as", :@group, nil],
119
+ ['', '--prefix PATH', "URL prefix for Rails app", :@prefix, nil]
120
+ ]
121
+ if restart
122
+ seen = {}
123
+ ret.each { |o| seen[o[1]] = true }
124
+ stop_options.each { |o|
125
+ ret << o unless seen[o[1]]
126
+ }
127
+ ret << [ '-i', '--rolling-interval SECONDS',
128
+ "Seconds to delay between each child restart",
129
+ :@rolling_interval, nil]
130
+ end
131
+ ret
132
+ end
133
+
134
+ def validate_start_options
135
+ if @config_file
136
+ valid_exists? @config_file, "Config file not there: #@config_file"
137
+ load_settings
138
+ end
139
+ @cwd = File.expand_path(@cwd)
140
+ valid_dir? @cwd, "Invalid path to change to during daemon mode: #@cwd"
141
+
142
+ # Change there to start, then we'll have to come back after daemonize
143
+ Dir.chdir(@cwd)
144
+
145
+ valid?(@prefix[0].chr == "/" && @prefix[-1].chr != "/",
146
+ "Prefix must begin with / and not end in /") if @prefix
147
+ valid_dir? File.dirname(@log_file),
148
+ "Path to log file not valid: #@log_file"
149
+ valid_dir? File.dirname(@pid_file),
150
+ "Path to pid file not valid: #@pid_file"
151
+ valid_dir? @docroot, "Path to docroot not valid: #@docroot"
152
+ valid_exists? @mime_map, "MIME mapping file does not exist: #@mime_map" \
153
+ if @mime_map
154
+ valid_user? @user if @user
155
+ valid_group? @group if @group
156
+
157
+ return @valid
158
+ end
159
+
160
+ def stop_child(settings, port, force = @force)
161
+ pid_file = port_pid_file(port)
162
+
163
+ if File.exist?(pid_file)
164
+ signal = force ? 'KILL' : 'TERM'
165
+ pid = File.open(pid_file).read.to_i
166
+ STDERR.print "Sending #{signal} to Mongrel at PID #{pid}..."
167
+ begin
168
+ Process.kill(signal, pid)
169
+ rescue Errno::ESRCH
170
+ STDERR.puts 'Process does not exist. Not running.'
171
+ File.unlink(pid_file)
172
+ end
173
+ if force
174
+ File.unlink(pid_file) rescue nil
175
+ else
176
+ @wait.to_i.times { |nr| sleep(1) if File.exist?(pid_file) }
177
+ end
178
+ STDERR.puts 'Done.'
179
+ else
180
+ STDERR.puts "#{pid_file} not found, skipping."
181
+ end
182
+ end
183
+
184
+ def load_settings
185
+ # Config file settings will override command line settings
186
+ settings = { :host => @address, :port => @port, :cwd => @cwd,
187
+ :log_file => @log_file, :pid_file => @pid_file,
188
+ :environment => @environment,
189
+ :docroot => @docroot, :mime_map => @mime_map,
190
+ :debug => @debug, :includes => ["mongrel"],
191
+ :config_script => @config_script,
192
+ :num_processors => @num_procs, :timeout => @timeout,
193
+ :servers => @servers,
194
+ :user => @user, :group => @group, :prefix => @prefix,
195
+ :only => @only, :rolling_interval => @rolling_interval,
196
+ :config_file => @config_file
197
+ }
198
+ read_options(settings)
199
+ settings
200
+ end
201
+
202
+ def restart_run(restart = false)
203
+ settings = load_settings
204
+ settings.merge(:force => @force, :wait => @wait) if restart
205
+ config = rails_preload(settings)
206
+ ObjectSpace.each_object(TCPServer) { |x| x.close rescue nil }
207
+
208
+ close_rails_connections
209
+
210
+ pid = fork {
211
+ File.umask 0000
212
+ Process.setsid
213
+ trap 'HUP', 'IGNORE'
214
+ Dir.chdir(@cwd)
215
+ ri = nil
216
+ each_port(settings) { |port|
217
+ if restart && settings[:rolling_interval]
218
+ if ri
219
+ STDERR.puts "Delaying next restart by #{ri} seconds " +
220
+ "(rolling-interval)"
221
+ sleep(ri)
222
+ else
223
+ ri = settings[:rolling_interval].to_f
224
+ end
225
+ end
226
+
227
+ GC.start
228
+ if restart
229
+ stop_child(settings, port)
230
+ GC.start
231
+ end
232
+
233
+ spawn_child(settings, port)
234
+ }
235
+ }
236
+ Process.waitpid(pid)
237
+ exit 0
238
+ end # restart_run
239
+
240
+ def write_child_pid(settings)
241
+ pid_file = settings[:pid_file]
242
+ if File.exist?(pid_file)
243
+ STDERR.puts "!!! PID file #{pid_file} already exists." +
244
+ " Mongrel could be running already. " +
245
+ "Check your #{settings[:log_file]} for errors."
246
+ STDERR.puts "!!! Exiting with error. " +
247
+ "You must stop mongrel and clear the .pid " +
248
+ "before I'll attempt a start."
249
+ exit 1
250
+ end
251
+
252
+ File.open(pid_file, 'w') { |fp| fp.puts $$.to_s }
253
+ end
254
+
255
+ def reopen_child_log(settings)
256
+ STDIN.reopen '/dev/null' rescue nil
257
+ STDOUT.reopen(settings[:log_file], 'a')
258
+ STDOUT.sync = true
259
+ STDERR.reopen(settings[:log_file], 'a')
260
+ STDERR.sync = true
261
+ end
262
+
263
+ def get_unbound_port
264
+ tmp_port = tmp_socket = nil
265
+ while ! tmp_socket do
266
+ begin
267
+ tmp_port = rand(32768) + 32768
268
+ tmp_socket = TCPServer.new('127.0.0.1', tmp_port)
269
+ rescue Errno::EADDRINUSE
270
+ STDERR.puts "Warning: failed temporarily bind to random port: " +
271
+ "#{tmp_port}, trying another..."
272
+ retry
273
+ end
274
+ end
275
+ tmp_socket.close
276
+ tmp_port
277
+ end
278
+
279
+ def rails_preload(settings)
280
+ GC.start
281
+
282
+ # start a random, temporary alternate port
283
+ settings = settings.dup
284
+ settings[:host] = '127.0.0.1'
285
+ settings[:port] = get_unbound_port
286
+ config = Mongrel::Rails::RailsConfigurator.new(settings) do
287
+ mime = {}
288
+ if defaults[:mime_map]
289
+ log "Loading additional MIME types from #{defaults[:mime_map]}"
290
+ mime = load_mime_map(defaults[:mime_map], mime)
291
+ end
292
+
293
+ listener do
294
+ uri defaults[:prefix] || "/",
295
+ :handler => rails(:mime => mime, :prefix => defaults[:prefix])
296
+ if defaults[:config_script]
297
+ log "Loading #{defaults[:config_script]} external config script"
298
+ run_config(defaults[:config_script])
299
+ end
300
+ log "Loading any Rails specific GemPlugins"
301
+ load_plugins
302
+ log "Rails loaded."
303
+ end
304
+ end # RailsConfigurator.new
305
+ config
306
+ end
307
+
308
+ def close_rails_connections
309
+ ActiveRecord::Base.connection.disconnect!
310
+ CACHE.reset if defined?(CACHE) && CACHE.respond_to?(:reset)
311
+ end
312
+
313
+ def open_rails_connections
314
+ ActiveRecord::Base.establish_connection
315
+ end
316
+
317
+ def wait_for_child_ready(address, port)
318
+ sleep 1
319
+ tries = 10
320
+ begin
321
+ http = Net::HTTP.new(address, port)
322
+ http.start
323
+ ret = http.get('/')
324
+ STDERR.puts "http://#{address}:#{port} ready: #{ret}"
325
+ rescue Errno::ECONNREFUSED => err
326
+ if (tries -= 1) > 0
327
+ STDERR.puts "Waiting for http://#{address}:#{port} to respond, " +
328
+ "#{tries} tries left"
329
+ sleep 1
330
+ retry
331
+ else
332
+ throw err
333
+ end
334
+ end
335
+ end
336
+
337
+ def spawn_child(settings, port)
338
+ fork {
339
+ GC.start
340
+ settings[:port] = port
341
+ settings[:pid_file] = port_pid_file(port)
342
+ settings[:log_file] = port_log_file(port)
343
+ write_child_pid(settings)
344
+ reopen_child_log(settings)
345
+
346
+ $0 << " -p #{port}"
347
+ open_rails_connections
348
+ config = Mongrel::Rails::RailsConfigurator.new(settings) do
349
+ if defaults[:debug]
350
+ log "Installing debugging prefixed filters. " +
351
+ "Look in log/mongrel_debug for the files."
352
+ debug "/"
353
+ end
354
+
355
+ listener do
356
+ uri defaults[:prefix] || "/", :handler => rails
357
+ if defaults[:config_script]
358
+ log "Loading #{defaults[:config_script]} external config script"
359
+ run_config(defaults[:config_script])
360
+ end
361
+ setup_rails_signals
362
+ end # listener
363
+
364
+ end # config
365
+ config.log "Mongrel available at #{settings[:host]}:#{port}"
366
+ config.run
367
+ GC.start
368
+ config.join
369
+ exit 0
370
+ } # fork
371
+ wait_for_child_ready(settings[:host], port)
372
+ rescue Object => err
373
+ STDERR.puts "Failed to spawn child on port #{port}: #{err.inspect}"
374
+ end # spawn_child
375
+ end
376
+
377
+
378
+ class Start < GemPlugin::Plugin "/commands"
379
+ include Mongrel::Command::Base
380
+ include Base
381
+
382
+ def configure
383
+ options start_options
384
+ end
385
+
386
+ def validate
387
+ validate_start_options
388
+ end
389
+
390
+ def run
391
+ restart_run(false)
392
+ end
393
+ end
394
+
395
+
396
+ class Stop < GemPlugin::Plugin "/commands"
397
+ include Mongrel::Command::Base
398
+ include Base
399
+
400
+ def configure
401
+ options stop_options
402
+ end
403
+
404
+ def validate
405
+ validate_stop_options
406
+ end
407
+
408
+ def run
409
+ settings = { :cwd => @cwd, :only => @only, :wait => @wait,
410
+ :port => @port, :servers => @servers,
411
+ :pid_file => @pid_file }
412
+ read_options(settings)
413
+
414
+ each_port(settings) { |port| stop_child(settings, port) }
415
+ end
416
+ end
417
+
418
+
419
+ class Restart < GemPlugin::Plugin "/commands"
420
+ include Mongrel::Command::Base
421
+ include Base
422
+
423
+ def configure
424
+ options start_options(true)
425
+ end
426
+
427
+ def validate
428
+ validate_stop_options && validate_start_options
429
+ end
430
+
431
+ def run
432
+ restart_run(true)
433
+ end
434
+ end
435
+
436
+ end
437
+
@@ -0,0 +1,47 @@
1
+
2
+ # Gem::Specification for Mongrel_cow_cluster-0.3.5
3
+ # Originally generated by Echoe
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = %q{mongrel_cow_cluster}
7
+ s.version = "0.3.5"
8
+
9
+ s.specification_version = 2 if s.respond_to? :specification_version=
10
+
11
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
+ s.authors = ["Eric Wong"]
13
+ s.date = %q{2008-02-24}
14
+ s.description = %q{A Mongrel plugin that uses copy-on-write to lower resource impact and handle rolling restarts of several Mongrel processes.}
15
+ s.email = %q{}
16
+ s.files = ["CHANGELOG", "README", "Manifest", "LICENSE", "lib/mongrel_cow_cluster/init.rb", "resources/defaults.yaml", "tools/rakehelp.rb", "mongrel_cow_cluster.gemspec"]
17
+ s.has_rdoc = true
18
+ s.homepage = %q{http://mongrel-cow.rubyforge.org}
19
+ s.require_paths = ["lib"]
20
+ s.rubyforge_project = %q{mongrel-cow}
21
+ s.rubygems_version = %q{0.9.4.7}
22
+ s.summary = %q{A Mongrel plugin that uses copy-on-write to lower resource impact and handle rolling restarts of several Mongrel processes.}
23
+
24
+ s.add_dependency(%q<mongrel>, [">= 0", "= 1.0.1"])
25
+ end
26
+
27
+
28
+ # # Original Rakefile source (requires the Echoe gem):
29
+ #
30
+ # require 'echoe'
31
+ # echoe = Echoe.new('mongrel_cow_cluster') do |p|
32
+ # p.author = 'Eric Wong'
33
+ # p.summary = 'A Mongrel plugin that uses copy-on-write to lower ' \
34
+ # 'resource impact and handle rolling restarts of ' \
35
+ # 'several Mongrel processes.'
36
+ # p.url = 'http://mongrel-cow.rubyforge.org'
37
+ # p.rubyforge_name = 'mongrel-cow'
38
+ # p.dependencies = [ 'mongrel >= 1.0.1' ]
39
+ # end
40
+ #
41
+ # task :eric_release => [:clean, :package] do
42
+ # sh %{git log > pkg/#{echoe.name}-changelog}
43
+ # FileUtils.rmtree "pkg/#{echoe.name}-#{echoe.version}"
44
+ # sh %{git tag -s -u normalperson@yhbt.net v#{echoe.version}}
45
+ # sh %{git push bogomips}
46
+ # sh %{rsync -av pkg/ bogomips.org:/srv/bogomips/ruby/}
47
+ # end
@@ -0,0 +1,2 @@
1
+ ---
2
+ :debug: false
@@ -0,0 +1,123 @@
1
+
2
+ def make(makedir)
3
+ Dir.chdir(makedir) do
4
+ sh(PLATFORM =~ /win32/ ? 'nmake' : 'make')
5
+ end
6
+ end
7
+
8
+
9
+ def extconf(dir)
10
+ Dir.chdir(dir) do ruby "extconf.rb" end
11
+ end
12
+
13
+
14
+ def setup_tests
15
+ Rake::TestTask.new do |t|
16
+ t.libs << "test"
17
+ t.test_files = FileList['test/test*.rb']
18
+ t.verbose = true
19
+ end
20
+ end
21
+
22
+
23
+ def setup_clean otherfiles
24
+ files = ['build/*', '**/*.o', '**/*.so', '**/*.a', 'lib/*-*', '**/*.log'] + otherfiles
25
+ CLEAN.include(files)
26
+ end
27
+
28
+
29
+ def setup_rdoc files
30
+ Rake::RDocTask.new do |rdoc|
31
+ rdoc.rdoc_dir = 'doc/rdoc'
32
+ rdoc.options << '--line-numbers'
33
+ rdoc.rdoc_files.add(files)
34
+ end
35
+ end
36
+
37
+
38
+ def setup_extension(dir, extension)
39
+ ext = "ext/#{dir}"
40
+ ext_so = "#{ext}/#{extension}.#{Config::CONFIG['DLEXT']}"
41
+ ext_files = FileList[
42
+ "#{ext}/*.c",
43
+ "#{ext}/*.h",
44
+ "#{ext}/extconf.rb",
45
+ "#{ext}/Makefile",
46
+ "lib"
47
+ ]
48
+
49
+ task "lib" do
50
+ directory "lib"
51
+ end
52
+
53
+ desc "Builds just the #{extension} extension"
54
+ task extension.to_sym => ["#{ext}/Makefile", ext_so ]
55
+
56
+ file "#{ext}/Makefile" => ["#{ext}/extconf.rb"] do
57
+ extconf "#{ext}"
58
+ end
59
+
60
+ file ext_so => ext_files do
61
+ make "#{ext}"
62
+ cp ext_so, "lib"
63
+ end
64
+ end
65
+
66
+
67
+ def base_gem_spec(pkg_name, pkg_version)
68
+ pkg_version = pkg_version
69
+ pkg_name = pkg_name
70
+ pkg_file_name = "#{pkg_name}-#{pkg_version}"
71
+ Gem::Specification.new do |s|
72
+ s.name = pkg_name
73
+ s.version = pkg_version
74
+ s.platform = Gem::Platform::RUBY
75
+ s.has_rdoc = true
76
+ s.extra_rdoc_files = [ "README.txt" ]
77
+
78
+ s.files = %w(COPYING README.txt Rakefile) +
79
+ Dir.glob("{bin,doc/rdoc,test,lib}/**/*") +
80
+ Dir.glob("ext/**/*.{h,c,rb}") +
81
+ Dir.glob("examples/**/*.rb") +
82
+ Dir.glob("tools/*.rb")
83
+
84
+ s.require_path = "lib"
85
+ s.extensions = FileList["ext/**/extconf.rb"].to_a
86
+ s.bindir = "bin"
87
+ end
88
+ end
89
+
90
+ def setup_gem(pkg_name, pkg_version)
91
+ spec = base_gem_spec(pkg_name, pkg_version)
92
+ yield spec if block_given?
93
+
94
+ Rake::GemPackageTask.new(spec) do |p|
95
+ p.gem_spec = spec
96
+ # win32 chokes on this
97
+ p.need_tar = true if RUBY_PLATFORM !~ /mswin/
98
+ end
99
+ end
100
+
101
+ def setup_win32_gem(pkg_name, pkg_version)
102
+ spec = base_gem_spec(pkg_name, pkg_version)
103
+ yield spec if block_given?
104
+
105
+ Gem::Builder.new(spec).build
106
+ end
107
+
108
+
109
+
110
+
111
+
112
+
113
+
114
+
115
+
116
+
117
+
118
+
119
+
120
+
121
+
122
+
123
+
metadata ADDED
@@ -0,0 +1,71 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.4.7
3
+ specification_version: 2
4
+ name: mongrel_cow_cluster
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.3.5
7
+ date: 2008-02-24 00:00:00 -08:00
8
+ summary: A Mongrel plugin that uses copy-on-write to lower resource impact and handle rolling restarts of several Mongrel processes.
9
+ require_paths:
10
+ - lib
11
+ email: ""
12
+ homepage: http://mongrel-cow.rubyforge.org
13
+ rubyforge_project: mongrel-cow
14
+ description: A Mongrel plugin that uses copy-on-write to lower resource impact and handle rolling restarts of several Mongrel processes.
15
+ autorequire:
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ required_rubygems_version: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: "0"
30
+ version:
31
+ platform: ruby
32
+ signing_key:
33
+ cert_chain: []
34
+
35
+ post_install_message:
36
+ authors:
37
+ - Eric Wong
38
+ files:
39
+ - CHANGELOG
40
+ - README
41
+ - Manifest
42
+ - LICENSE
43
+ - lib/mongrel_cow_cluster/init.rb
44
+ - resources/defaults.yaml
45
+ - tools/rakehelp.rb
46
+ - mongrel_cow_cluster.gemspec
47
+ test_files: []
48
+
49
+ rdoc_options: []
50
+
51
+ extra_rdoc_files: []
52
+
53
+ executables: []
54
+
55
+ extensions: []
56
+
57
+ requirements: []
58
+
59
+ dependencies:
60
+ - !ruby/object:Gem::Dependency
61
+ name: mongrel
62
+ version_requirement:
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: "0"
68
+ - - "="
69
+ - !ruby/object:Gem::Version
70
+ version: 1.0.1
71
+ version: