homeq 1.1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. data/CHANGELOG +103 -0
  2. data/COPYING +348 -0
  3. data/README.rdoc +64 -0
  4. data/Rakefile +131 -0
  5. data/bin/hq +6 -0
  6. data/config/boot.rb +224 -0
  7. data/config/databases/frontbase.yml +28 -0
  8. data/config/databases/mysql.yml +54 -0
  9. data/config/databases/oracle.yml +39 -0
  10. data/config/databases/postgresql.yml +48 -0
  11. data/config/databases/sqlite2.yml +16 -0
  12. data/config/databases/sqlite3.yml +19 -0
  13. data/config/environment.rb +20 -0
  14. data/config/environments/development.cfg +35 -0
  15. data/config/environments/production.cfg +35 -0
  16. data/config/environments/test.cfg +35 -0
  17. data/config/generators/job/templates/job.rb.erb +20 -0
  18. data/config/generators/message/templates/messages/MESSAGE.proto.erb +12 -0
  19. data/config/generators/model/templates/models/MODEL.rb.erb +3 -0
  20. data/config/generators/service/templates/services/SERVICE.rb.erb +43 -0
  21. data/config/homeq.cfg +35 -0
  22. data/extras/consumer.rb +85 -0
  23. data/extras/homeq.cfg +49 -0
  24. data/extras/hqd.rb +33 -0
  25. data/extras/producer.rb +79 -0
  26. data/extras/simple_consumer.rb +53 -0
  27. data/lib/homeq/base/base.rb +44 -0
  28. data/lib/homeq/base/commando.rb +81 -0
  29. data/lib/homeq/base/config.rb +99 -0
  30. data/lib/homeq/base/exception.rb +48 -0
  31. data/lib/homeq/base/histogram.rb +141 -0
  32. data/lib/homeq/base/logger.rb +185 -0
  33. data/lib/homeq/base/ohash.rb +297 -0
  34. data/lib/homeq/base/options.rb +171 -0
  35. data/lib/homeq/base/poolable.rb +100 -0
  36. data/lib/homeq/base/system.rb +446 -0
  37. data/lib/homeq/cli.rb +35 -0
  38. data/lib/homeq/cp/commands.rb +71 -0
  39. data/lib/homeq/cp/connection.rb +97 -0
  40. data/lib/homeq/cp/cp.rb +30 -0
  41. data/lib/homeq/cp/server.rb +105 -0
  42. data/lib/homeq/sobs/client.rb +119 -0
  43. data/lib/homeq/sobs/connection.rb +635 -0
  44. data/lib/homeq/sobs/foreman.rb +237 -0
  45. data/lib/homeq/sobs/job.rb +66 -0
  46. data/lib/homeq/sobs/message.rb +49 -0
  47. data/lib/homeq/sobs/queue.rb +224 -0
  48. data/lib/homeq/sobs/sender.rb +150 -0
  49. data/lib/homeq/sobs/server.rb +654 -0
  50. data/lib/homeq/sobs/sobs.rb +45 -0
  51. data/lib/homeq/sobs/topology.rb +111 -0
  52. data/lib/homeq.rb +106 -0
  53. data/lib/tasks/Rakefile +49 -0
  54. data/lib/tasks/database.rake +387 -0
  55. data/lib/tasks/gem.rake +9 -0
  56. data/lib/tasks/generate.rake +192 -0
  57. data/lib/tasks/hq.rake +171 -0
  58. data/lib/tasks/testing.rake +95 -0
  59. data/lib/tasks/utility.rb +17 -0
  60. data/script/console.rb +45 -0
  61. data/script/generate +7 -0
  62. data/test/unittest.rb +51 -0
  63. metadata +222 -0
@@ -0,0 +1,171 @@
1
+ #############################################################################
2
+ #
3
+ # $Id: options.rb 42 2008-10-24 05:53:35Z colin $
4
+ #
5
+ # Author:: Colin Steele (colin@colinsteele.org)
6
+ # Homepage::
7
+ #
8
+ # TODO: info
9
+ #
10
+ #----------------------------------------------------------------------------
11
+ #
12
+ # Copyright (C) 2008 by Colin Steele. All Rights Reserved.
13
+ # colin@colinsteele.org
14
+ #
15
+ # This program is free software; you can redistribute it and/or modify
16
+ # it under the terms of either: 1) the GNU General Public License
17
+ # as published by the Free Software Foundation; either version 2 of the
18
+ # License, or (at your option) any later version; or 2) Ruby's License.
19
+ #
20
+ # See the file COPYING for complete licensing information.
21
+ #
22
+ #---------------------------------------------------------------------------
23
+ #
24
+ #
25
+ #############################################################################
26
+
27
+ require 'optparse'
28
+ require 'optparse/time'
29
+ require 'ostruct'
30
+ require 'singleton'
31
+ require 'pp'
32
+
33
+ module HomeQ
34
+
35
+ module Base
36
+
37
+ module Options
38
+
39
+ def options
40
+ @options ||= Options.instance.parse
41
+ end
42
+
43
+ class Options
44
+ include Singleton
45
+
46
+ attr :options, true
47
+ attr :parser, true
48
+
49
+ def initialize
50
+ @options = OpenStruct.new
51
+ @options.log_level = false
52
+ @options.config_file = File.join(HOMEQ_APP_ROOT,
53
+ '/config/homeq.cfg')
54
+ @options.queue_name = nil
55
+ @options.cp_port = nil
56
+ @options.foreground = false
57
+ @options.pid_file = false
58
+ @options.log_file = false
59
+ @options.dump_topology = false
60
+ @options.enable_debugging = false
61
+
62
+ @parser = OptionParser.new do |opts|
63
+ opts.banner = "Usage: #{File.basename($0)} [options]"
64
+
65
+ opts.separator ""
66
+ opts.separator "HOMEQ options:"
67
+
68
+ # Mandatory argument.
69
+ opts.on("-c", "--config-file FILE",
70
+ "Configuration file; defaults to \n\
71
+ #{@options.config_file}") { |c|
72
+ @options.config_file = c
73
+ }
74
+ opts.on("-q", "--queuename NAME",
75
+ "This process's queue name") { |q|
76
+ @options.queue_name = q
77
+ }
78
+ opts.on("-p", "--port PORT",
79
+ Integer,
80
+ "Control port to listen on.") { |p|
81
+ @options.cp_port = p
82
+ }
83
+ opts.on("-l", "--[no-]log-file LOGFILE",
84
+ "Log to this file; defaults to \n\
85
+ #{@options.log_file}") { |o|
86
+ @options.log_file = o
87
+ }
88
+ opts.on("-P", "--pid-file FILE",
89
+ "Write pid to this file;\n \
90
+ defaults to " +
91
+ "/var/run/hq_<queuename>.pid") { |p|
92
+ @options.pid_file = p
93
+ }
94
+
95
+ # Boolean switches
96
+
97
+ opts.on("-v",
98
+ "--[no-]verbose",
99
+ "Run verbosely. Additively -vvv") do |v|
100
+ @options.log_level = 0 unless @options.log_level
101
+ @options.log_level += 1
102
+ end
103
+ opts.on("-f", "--[no-]foreground", "Run in the foreground") do |o|
104
+ @options.foreground = o
105
+ end
106
+ opts.on("-T", "--print-topology",
107
+ "Using command line options and config file,\n \
108
+ dump a topology in YAML format.") do |o|
109
+ @options.dump_topology = o
110
+ end
111
+ opts.on("-E", "--print-homeq-env",
112
+ "Using command line options and config file,\n \
113
+ display currently set HOMEQ_ENV.") do |o|
114
+ @options.dump_env = o
115
+ end
116
+ opts.on("-D", "--enable-debugging",
117
+ "Enable rdebug debugging") do |o|
118
+ @options.enable_debugging = o
119
+ end
120
+
121
+ opts.separator ""
122
+ opts.separator "Common options:"
123
+
124
+ opts.on("-h", "--help", "Show this message") do
125
+ puts opts
126
+ exit
127
+ end
128
+
129
+ # Another typical switch to print the version.
130
+ opts.on("--version", "Show version") do
131
+ puts OptionParser::Version.join('.')
132
+ Kernel::exit
133
+ end
134
+ end
135
+ end
136
+
137
+ #
138
+ # Return a structure describing the options.
139
+ #
140
+ def parse
141
+ # The options specified on the command line will be
142
+ # collected in *options*. We set default values here.
143
+
144
+ begin
145
+ @parser.parse!(ARGV)
146
+ rescue OptionParser::ParseError => pe
147
+ puts @parser
148
+ raise
149
+ end
150
+
151
+ # Add our cute little override method
152
+ class << @options
153
+ def set_configuration(config)
154
+ @table.each { |k,v|
155
+ if config.respond_to?(k) && v
156
+ config.send(k, v)
157
+ end
158
+ }
159
+ end
160
+ end
161
+
162
+ @options
163
+ end # parse()
164
+
165
+ end # class Options
166
+
167
+ end # module Options
168
+
169
+ end # module Base
170
+
171
+ end # module HomeQ
@@ -0,0 +1,100 @@
1
+ #!/usr/bin/ruby
2
+
3
+ #############################################################################
4
+ #
5
+ # $Id: homeq.rb 8 2008-08-27 20:15:22Z colin $
6
+ #
7
+ # Author:: Colin Steele (colin@colinsteele.org)
8
+ # Homepage::
9
+ #
10
+ # TODO: info
11
+ #
12
+ #----------------------------------------------------------------------------
13
+ #
14
+ # Copyright (C) 2008 by Colin Steele. All Rights Reserved.
15
+ # colin@colinsteele.org
16
+ #
17
+ # This program is free software; you can redistribute it and/or modify
18
+ # it under the terms of either: 1) the GNU General Public License
19
+ # as published by the Free Software Foundation; either version 2 of the
20
+ # License, or (at your option) any later version; or 2) Ruby's License.
21
+ #
22
+ # See the file COPYING for complete licensing information.
23
+ #
24
+ #---------------------------------------------------------------------------
25
+ #
26
+ #
27
+ #############################################################################
28
+
29
+ module HomeQ
30
+
31
+ module Poolable
32
+ def self.included(base)
33
+ base.extend(ClassMethods)
34
+ end
35
+ def recycle
36
+ deinitialize
37
+ if self.class.pool.size < self.class.pool_size
38
+ self.class.pool.push(self)
39
+ end
40
+ end
41
+ def deinitialize
42
+ raise "Must be overridden"
43
+ end
44
+ module ClassMethods
45
+ attr :pool, false
46
+ attr :pool_size, false
47
+ def pool_init(size)
48
+ @pool_size = size
49
+ @pool = []
50
+ end
51
+ def new(*args)
52
+ if @pool.any?
53
+ o = @pool.shift
54
+ o.send(:reinitialize, *args)
55
+ return o
56
+ end
57
+ super(*args)
58
+ end
59
+ end
60
+
61
+ end # module Poolable
62
+
63
+ end # module HomeQ
64
+
65
+ if $0 == __FILE__
66
+
67
+ require 'test/unit/testsuite'
68
+ require 'test/unit'
69
+
70
+ class Foo
71
+ include HomeQ::Poolable
72
+ pool_init(1)
73
+ attr :x, true
74
+ def initialize(x)
75
+ @x = x
76
+ end
77
+ alias_method :reinitialize, :initialize
78
+ def deinitialize
79
+ instance_variables.each {|v|
80
+ eval "#{v} = nil"
81
+ }
82
+ end
83
+ end
84
+
85
+ class TC_MyTest < Test::Unit::TestCase
86
+ def test_simple
87
+ f1 = Foo.new(23)
88
+ assert_equal(23, f1.x)
89
+ assert_equal(0, Foo.pool.size)
90
+ f1.recycle
91
+ assert_equal(1, Foo.pool.size)
92
+ assert_equal(nil, f1.x)
93
+ f2 = Foo.new(19)
94
+ assert_equal(19, f2.x)
95
+ assert_equal(f1.object_id, f2.object_id)
96
+ assert_equal(0, Foo.pool.size)
97
+ end
98
+ end
99
+
100
+ end
@@ -0,0 +1,446 @@
1
+ #############################################################################
2
+ #
3
+ # $Id: system.rb 48 2008-11-19 05:11:59Z colin $
4
+ #
5
+ # Author:: Colin Steele (colin@colinsteele.org)
6
+ # Homepage::
7
+ #
8
+ # TODO: info
9
+ #
10
+ #----------------------------------------------------------------------------
11
+ #
12
+ # Copyright (C) 2008 by Colin Steele. All Rights Reserved.
13
+ # colin@colinsteele.org
14
+ #
15
+ # This program is free software; you can redistribute it and/or modify
16
+ # it under the terms of either: 1) the GNU General Public License
17
+ # as published by the Free Software Foundation; either version 2 of the
18
+ # License, or (at your option) any later version; or 2) Ruby's License.
19
+ #
20
+ # See the file COPYING for complete licensing information.
21
+ #
22
+ #---------------------------------------------------------------------------
23
+ #
24
+ #
25
+ #############################################################################
26
+
27
+ require 'singleton'
28
+ require 'observer'
29
+ require 'ruby-prof'
30
+
31
+ module HomeQ
32
+
33
+ module Base
34
+
35
+ class System
36
+
37
+ # Run periodic tasks every so many seconds
38
+ PERIOD_TASK_INTERVAL = 60
39
+
40
+ module HomeQ::Base::Commando::InstanceMethods
41
+ def start_profiling
42
+ sys.start_profiling
43
+ end
44
+ def stop_profiling
45
+ sys.stop_profiling
46
+ end
47
+ document_command "start_profiling", "Begin profiling"
48
+ document_command "stop_profiling", "End profiling. Results to STDOUT."
49
+ def enable_debugging(*args)
50
+ sys.enable_debugging
51
+ end
52
+ def disable_debugging
53
+ sys.disable_debugging
54
+ end
55
+ def debug_now
56
+ sys.debug_now
57
+ end
58
+ def add_breakpoint(file, line, expr)
59
+ sys.add_breakpoint(file, line, expr)
60
+ end
61
+ def pid_file(filename=nil)
62
+ return sys.pid_file unless filename
63
+ sys.pid_file = filename
64
+ end
65
+ def config_file(filename=nil)
66
+ return sys.config_file unless filename
67
+ sys.config_file = filename
68
+ end
69
+ document_command "enable_debugging", "Begin debugging"
70
+ document_command("disable_debugging",
71
+ "End debugging. Results to STDOUT.")
72
+ document_command "debug_now", "Drop into debugger."
73
+ document_command "add_breakpoint(file,line,expr)", "Set a breakpoint."
74
+ config_accessor :foreground
75
+ config_accessor :dump_topology, 'Cough up topology in YAML format.'
76
+ config_accessor :dump_env, 'Cough up HOMEQ_ENV.'
77
+ config_accessor(:period_task_interval,
78
+ "Run periodic tasks every so many seconds")
79
+
80
+ def show_queue(queuename)
81
+ unless queuename.is_a?(String)
82
+ return "Supply a queue name in string format, plz."
83
+ end
84
+ found = sys.servers.find { |s|
85
+ s.queue_name == queuename
86
+ }
87
+ found ||= sys.queues.find { |s|
88
+ s.queue_name == queuename
89
+ }
90
+ found || "Can't find that queue"
91
+ end
92
+ def show_queue_list
93
+ sys.servers.to_s + "\n" + sys.queues.to_s
94
+ end
95
+ document_command "show_queue(qname)", "Display info about a queue"
96
+ document_command :show_queue_list, "List queues"
97
+ end
98
+
99
+ include Singleton
100
+ include Observable
101
+ include Base::Configuration
102
+ include Base::Logging
103
+ include Base::Options
104
+
105
+ attr :servers, true
106
+ attr :queues, true
107
+ attr :config_file, true
108
+ attr :cp_server, true
109
+ attr :handlers, true
110
+ attr :topology, true
111
+ attr :pid_file, true
112
+
113
+ def initialize
114
+ @handlers = {}
115
+ @servers = []
116
+ @queues = []
117
+ @topology = HomeQ::SOBS::Topology::Topology.new
118
+ @state = Statemachine.build do
119
+ state :start do
120
+ event :init, :waiting_to_run, :delayed_init
121
+ event :error, :stopped
122
+ end
123
+ state :waiting_to_run do
124
+ on_entry :broadcast_change
125
+ event :init, :waiting_to_run
126
+ event :started, :running
127
+ event :stop, :stopped
128
+ end
129
+ state :running do
130
+ on_entry :broadcast_change
131
+ event :error, :stopped
132
+ event :stop, :stopped
133
+ end
134
+ state :stopped do
135
+ on_entry :shutdown
136
+ event :start, :running
137
+ event :stop, :stopped
138
+ event :started, :stopped
139
+ event :init, :running
140
+ end
141
+ state :exit do
142
+ end
143
+ end
144
+ @state.context = self
145
+
146
+ catch_signals
147
+
148
+ setup_em
149
+ end
150
+
151
+ # Set the system in motion. Initializes, reading command line
152
+ # args and config file, calls EventMachine::run. If called with
153
+ # a block, it will yield to the block inside the block passed to
154
+ # EventMachine::run, so application code will have a chance to
155
+ # do any startup tasks inside the EventMachine::run block.
156
+ #
157
+ # After yielding to your application code (while still in the
158
+ # EventMachine::run block), it starts the server, queues, and
159
+ # the control port, and then away we go.
160
+ def start
161
+ @state.init
162
+ if @state.state == :waiting_to_run
163
+ EventMachine::set_descriptor_table_size(10000)
164
+ # TODO Hmm. Use this?
165
+ # EventMachine::set_effective_user("nobody")
166
+ logger.info {
167
+ "Starting Eventmachine. Pid: #{Process.pid} " +
168
+ "HOMEQ_ENV: #{HOMEQ_ENV} HOMEQ_APP_ROOT: #{HOMEQ_APP_ROOT}"
169
+ }
170
+ EventMachine::run {
171
+ yield if block_given?
172
+ HomeQ::SOBS::Server.create_home_queue(config.queue_name,
173
+ @handlers[config.queue_name])
174
+ HomeQ::SOBS::Queue.create_queues_from_topology(config.queue_name)
175
+ @cp_server = CP::Server.new(config.cp_host, config.cp_port)
176
+
177
+ @cp_server.start
178
+ start_servers
179
+ start_queues
180
+ start_periodic_tasks
181
+
182
+ @state.started
183
+ }
184
+ end
185
+ end
186
+
187
+ # Start a graceful shutdown.
188
+ def stop
189
+ @state.stop
190
+ end
191
+
192
+ # We don't do any nice cleanup, just go down fast.
193
+ def die(msg=nil, exit_status=-1)
194
+ logger.fatal(msg) if msg
195
+ exit!(exit_status)
196
+ end
197
+
198
+ # If debugging is already enabled (via enable_debugging), then
199
+ # call 'debugger'.
200
+ def debug_now
201
+ if @debugging
202
+ debugger
203
+ else
204
+ logger.info {
205
+ "Debugging not started."
206
+ }
207
+ end
208
+ end
209
+
210
+ # If not already enabled, setup for debugging by doing a
211
+ # require 'ruby-debug', and then a Debugger.start_remote()
212
+ def enable_debugging
213
+ if !@debugging
214
+ logger.info {
215
+ "Enabled debugging."
216
+ }
217
+ @debugging = true
218
+ require 'ruby-debug'
219
+ Debugger.start_remote
220
+ end
221
+ end
222
+
223
+ # If already debugging, disable it and call Debugger.stop().
224
+ def disable_debugging
225
+ if @debugging
226
+ logger.info {
227
+ "Disabled debugging"
228
+ }
229
+ @debugging = false
230
+ Debugger.stop
231
+ end
232
+ end
233
+
234
+ # Tell the debugger to break at the supplied file and line.
235
+ def add_breakpoint(file, line, expr)
236
+ Debugger.add_breakpoint(file, line, expr)
237
+ end
238
+
239
+ # Begin profiling
240
+ def start_profiling
241
+ if !@profiling
242
+ logger.info {
243
+ 'Beginning profiling'
244
+ }
245
+ @profiling = true
246
+ RubyProf.start
247
+ end
248
+ end
249
+
250
+ # End profiling. Results are printed to STDOUT.
251
+ def stop_profiling
252
+ if @profiling
253
+ logger.info {
254
+ 'Ending profiling'
255
+ }
256
+ @profiling = false
257
+ result = RubyProf.stop
258
+ printer = RubyProf::GraphPrinter.new(result)
259
+ printer.print(STDOUT, 0)
260
+ end
261
+ end
262
+
263
+ protected
264
+
265
+ # Make sure EventMachine is configured to our liking.
266
+ def setup_em
267
+ EventMachine::set_max_timers(1000000)
268
+ end
269
+
270
+ # Tell folks something.
271
+ def broadcast_change
272
+ changed
273
+ notify_observers(self, @state.state)
274
+ end
275
+
276
+ # Lazy initialization; called from start()
277
+ def delayed_init
278
+ begin
279
+ # The queue name and config file name are settings we need
280
+ # "early", during initialization. If they're set on the
281
+ # command line, grab them now.
282
+ options.config_file && (@config_file = options.config_file)
283
+ options.queue_name && (config.queue_name = options.queue_name)
284
+
285
+ raise "No config file set?!" unless config_file
286
+ config.read_config_file(config_file)
287
+ options.set_configuration(config)
288
+
289
+ if options.dump_topology
290
+ puts topology.to_yaml
291
+ exit
292
+ elsif options.dump_env
293
+ puts HOMEQ_ENV
294
+ exit
295
+ end
296
+
297
+ if config.foreground
298
+ HomeQ::Base::Logging::Logger.instance.stdout
299
+ else
300
+ demonize
301
+ end
302
+
303
+ rescue OptionParser::ParseError => e
304
+ STDERR.puts e.message
305
+ exit(-1)
306
+ rescue SystemExit
307
+ exit
308
+ rescue Exception => e
309
+ raise
310
+ end
311
+ end
312
+
313
+ # Stop servers, queues and the control port. Wait for everthing
314
+ # to wind down, then exit.
315
+ def shutdown
316
+ stop_servers
317
+ stop_queues
318
+ @cp_server.stop if @cp_server
319
+ bye_if_done
320
+ end
321
+
322
+ # Wait for everything to wind down.
323
+ def bye_if_done
324
+ EventMachine::next_tick {
325
+ if (!@queues.find { |q| q.connected? } &&
326
+ !@servers.find { |s| s.connections.any? })
327
+ EventMachine::stop_event_loop
328
+ else
329
+ @queues.find { |q| q.connected? }.class
330
+ @servers.find { |s| s.connections.any? }.class
331
+ bye_if_done
332
+ end
333
+ }
334
+ end
335
+
336
+ # Start period tasks timer
337
+ def start_periodic_tasks
338
+ interval = config.period_task_interval || PERIOD_TASK_INTERVAL
339
+ EventMachine::add_periodic_timer(interval) {
340
+ sys.run_periodic_tasks
341
+ }
342
+ end
343
+
344
+ # Do any period tasks
345
+ def run_periodic_tasks
346
+ logger.debug4 {
347
+ "Running periodic tasks."
348
+ }
349
+ end
350
+
351
+ # Call each server in turn, telling it to start.
352
+ def start_servers
353
+ @servers.each { |s|
354
+ s.start
355
+ }
356
+ end
357
+
358
+ # Call each queue in turn, telling it to start.
359
+ def start_queues
360
+ @queues.each { |q|
361
+ q.start
362
+ if @handlers[q.queue_name]
363
+ q.handler = @handlers[q.queue_name]
364
+ end
365
+ }
366
+ end
367
+
368
+ def stop_servers
369
+ logger.debug {
370
+ "Stopping servers"
371
+ }
372
+ @servers.each { |s|
373
+ s.stop
374
+ }
375
+ end
376
+
377
+ def stop_queues
378
+ logger.debug {
379
+ "Stopping queues"
380
+ }
381
+ @queues.each { |q|
382
+ q.stop
383
+ }
384
+ end
385
+
386
+ def demonize
387
+ # Detach from controlling tty
388
+ parent = fork
389
+ exit! if parent
390
+ Process.setsid
391
+
392
+ # We want to be the grandchild. This is probably redundant in
393
+ # everything but some old weird SysV systems. But it seems to
394
+ # be the UNIX WAY(tm).
395
+ parent = fork
396
+ exit! if parent
397
+
398
+ store_pid
399
+ File.umask 0000
400
+ STDIN.reopen "/dev/null"
401
+ if options.log_file
402
+ STDOUT.reopen options.log_file, "a"
403
+ else
404
+ STDOUT.reopen "/dev/null", "a"
405
+ end
406
+ STDERR.reopen STDOUT
407
+ end
408
+
409
+ def store_pid
410
+ begin
411
+ filename = config.pid_file || "/var/log/hq_#{config.queue_name}.pid"
412
+ if File.exists?(filename)
413
+ die "Already running?! Pid file #{filename}."
414
+ end
415
+ File.open(filename, 'w') { |f|
416
+ f.puts Process.pid.to_s
417
+ }
418
+ rescue Errno::EACCES
419
+ die "Insufficient permissions to write pid file '#{filename}'"
420
+ end
421
+ end
422
+
423
+ def catch_signals
424
+ Signal.trap("INT") {
425
+ logger.info {
426
+ "Caught SIGINT; shutting down soon."
427
+ }
428
+ @state.stop
429
+ }
430
+ Signal.trap("USR1") {
431
+ @profiling ? stop_profiling : start_profiling
432
+ }
433
+ Signal.trap("USR2") {
434
+ logger.info {
435
+ "Caught SIGUSR2."
436
+ }
437
+ enable_debugging if !@debugging
438
+ debug_now
439
+ }
440
+ end
441
+
442
+ end # class System
443
+
444
+ end # module Base
445
+
446
+ end # HomeQ