homeq 1.1.4

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 (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