rq 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,63 @@
1
+ unless defined? $__rq_jobrunner__
2
+ module RQ
3
+ #{{{
4
+ LIBDIR = File::dirname(File::expand_path(__FILE__)) + File::SEPARATOR unless
5
+ defined? LIBDIR
6
+
7
+ require 'drb/drb'
8
+
9
+ require LIBDIR + 'util'
10
+
11
+ class JobRunner
12
+ #{{{
13
+ include DRbUndumped
14
+ attr :job
15
+ attr :jid
16
+ attr :cid
17
+ attr :shell
18
+ attr :command
19
+ alias pid cid
20
+ def initialize job
21
+ #{{{
22
+ @job = job
23
+ @jid = job['jid']
24
+ @command = job['command']
25
+ @shell = job['shell'] || 'bash'
26
+ @r,@w = IO::pipe
27
+ @env = {}
28
+ @job.fields.each do |field|
29
+ key = "RQ_#{ field }".upcase.gsub(%r/\s+/,'_')
30
+ val = @job[field]
31
+ @env[key] = "#{ val }"
32
+ end
33
+ @cid =
34
+ Util::fork do
35
+ begin
36
+ @env.each{|k,v| ENV[k] = v}
37
+ ENV['RQ_PID'] = "#{ $$ }"
38
+ @w.close
39
+ STDIN.reopen @r
40
+ if File::basename(@shell) == 'bash' || File::basename(@shell) == 'sh'
41
+ exec [@shell, "__rq_job__#{ @jid }__#{ File::basename(@shell) }__"], '--login'
42
+ else
43
+ exec [@shell, "__rq_job__#{ @jid }__#{ File::basename(@shell) }__"], '-l'
44
+ end
45
+ rescue Exception => e
46
+ STDERR.puts(Util::errmsg(e))
47
+ end
48
+ end
49
+ @r.close
50
+ #}}}
51
+ end
52
+ def run
53
+ #{{{
54
+ @w.puts @command
55
+ @w.close
56
+ #}}}
57
+ end
58
+ #}}}
59
+ end # class JobRunner
60
+ #}}}
61
+ end # module RQ
62
+ $__rq_jobrunner__ = __FILE__
63
+ end
@@ -0,0 +1,179 @@
1
+ unless defined? $__rq_jobrunnerdaemon__
2
+ module RQ
3
+ #{{{
4
+ LIBDIR = File::dirname(File::expand_path(__FILE__)) + File::SEPARATOR unless
5
+ defined? LIBDIR
6
+
7
+ require 'drb/drb'
8
+ require 'fileutils'
9
+ require 'tmpdir'
10
+ require 'tempfile'
11
+
12
+ require LIBDIR + 'job'
13
+ require LIBDIR + 'jobrunner'
14
+
15
+ class JobRunnerDaemon
16
+ #{{{
17
+ include Logging
18
+
19
+ class << self
20
+ #{{{
21
+ def daemon(*a,&b)
22
+ #{{{
23
+ jrd = new(*a, &b)
24
+
25
+ r, w = IO::pipe
26
+
27
+ unless((pid = fork)) # child
28
+ $0 = "#{ self }".gsub(%r/[^a-zA-Z]+/,'_').downcase
29
+ begin
30
+ r.close
31
+ n = 0
32
+ uri = nil
33
+ socket = nil
34
+
35
+ 42.times do
36
+ begin
37
+ s = "%s/%s_%s_%s_%s" %
38
+ [Dir::tmpdir, File::basename($0), Process::ppid, n, rand(42)]
39
+ u = "drbunix://#{ s }"
40
+ DRb::start_service u, jrd
41
+ socket = s
42
+ uri = u
43
+ rescue Errno::EADDRINUSE
44
+ n += 1
45
+ end
46
+ end
47
+
48
+ if socket and uri
49
+ w.write socket
50
+ w.close
51
+ pid = Process::pid
52
+ ppid = Process::ppid
53
+ cur = Thread::current
54
+ Thread::new(pid, ppid, cur) do |pid, ppid, cur|
55
+ loop do
56
+ begin
57
+ Process::kill 0, ppid
58
+ sleep 42
59
+ rescue
60
+ cur.raise "parent <#{ ppid }> died unexpectedly"
61
+ end
62
+ end
63
+ end
64
+ DRb::thread.join
65
+ else
66
+ w.close
67
+ end
68
+ ensure
69
+ exit!
70
+ end
71
+ else # parent
72
+ w.close
73
+ socket = r.read
74
+ r.close
75
+
76
+ if socket and File::exist?(socket)
77
+ at_exit{ FileUtils::rm_f socket }
78
+ uri = "drbunix://#{ socket }"
79
+ DRb::start_service 'druby://localhost:0', nil
80
+ jrd = DRbObject::new nil, uri
81
+ jrd.pid = pid
82
+ jrd.uri = uri
83
+ else
84
+ raise "failed to start job runner daemon"
85
+ end
86
+ end
87
+
88
+ return jrd
89
+ #}}}
90
+ end
91
+ #}}}
92
+ end
93
+ attr :runners
94
+ attr :pid, true
95
+ attr :uri, true
96
+ def initialize
97
+ #{{{
98
+ @runners = {}
99
+ @uri = nil
100
+ @pid = Process::pid
101
+ #}}}
102
+ end
103
+ def runner job
104
+ #{{{
105
+ r = nil
106
+ retried = false
107
+ begin
108
+ r = JobRunner::new job
109
+ rescue Errno::ENOMEM, Errno::EAGAIN
110
+ GC::start
111
+ unless retried
112
+ retried = true
113
+ retry
114
+ else
115
+ raise
116
+ end
117
+ end
118
+ @runners[r.pid] = r
119
+ r
120
+ #}}}
121
+ end
122
+ def wait
123
+ #{{{
124
+ pid = Process::wait
125
+ @runners.delete pid
126
+ pid
127
+ #}}}
128
+ end
129
+ def wait2
130
+ #{{{
131
+ pid, status = Process::wait2
132
+ @runners.delete pid
133
+ [pid, status]
134
+ #}}}
135
+ end
136
+ def waitpid pid = -1, flags = 0
137
+ #{{{
138
+ pid = pid.pid if pid.respond_to? 'pid'
139
+ pid = Process::waitpid pid, flags
140
+ @runners.delete pid
141
+ pid
142
+ #}}}
143
+ end
144
+ def waitpid2 pid = -1, flags = 0
145
+ #{{{
146
+ pid = pid.pid if pid.respond_to? 'pid'
147
+ pid, status = Process::waitpid2 pid, flags
148
+ @runners.delete pid
149
+ [pid, status]
150
+ #}}}
151
+ end
152
+ def shutdown
153
+ #{{{
154
+ @death =
155
+ Thread::new do
156
+ begin
157
+ while not @runners.empty?
158
+ pid = Process::wait
159
+ @runners.delete pid
160
+ end
161
+ ensure
162
+ sleep 4.2
163
+ DRb::thread.kill
164
+ Thread::main exit!
165
+ end
166
+ end
167
+ #}}}
168
+ end
169
+ def install_signal_handlers
170
+ #{{{
171
+ %w(TERM INT HUP).each{|sig| trap sig, 'SIG_IGN'}
172
+ #}}}
173
+ end
174
+ #}}}
175
+ end # class JobRunnerDaemon
176
+ #}}}
177
+ end # module RQ
178
+ $__rq_jobrunnerdaemon__ = __FILE__
179
+ end
@@ -0,0 +1,22 @@
1
+ unless defined? $__rq_lister__
2
+ module RQ
3
+ #{{{
4
+ LIBDIR = File::dirname(File::expand_path(__FILE__)) + File::SEPARATOR unless
5
+ defined? LIBDIR
6
+
7
+ require LIBDIR + 'mainhelper'
8
+
9
+ class Lister < MainHelper
10
+ #{{{
11
+ def list
12
+ #{{{
13
+ set_q
14
+ @q.list(*@argv)
15
+ #}}}
16
+ end
17
+ #}}}
18
+ end # class Lister
19
+ #}}}
20
+ end # module RQ
21
+ $__rq_lister__ = __FILE__
22
+ end
@@ -0,0 +1,37 @@
1
+ unless defined? $__rq_locker__
2
+ module RQ
3
+ #{{{
4
+ LIBDIR = File::dirname(File::expand_path(__FILE__)) + File::SEPARATOR unless
5
+ defined? LIBDIR
6
+
7
+ require LIBDIR + 'util'
8
+ require LIBDIR + 'locker'
9
+
10
+ class Locker < MainHelper
11
+ #{{{
12
+ def lock
13
+ #{{{
14
+ set_q
15
+ ltype = @argv.shift
16
+ debug{ "ltype <#{ ltype }>" }
17
+ read_only =
18
+ case ltype
19
+ when /^\s*r(?:ead)?|^\s*sh(?:ared)?/io
20
+ true
21
+ when /^\s*w(?:rite)?|^\s*ex(?:clusive)?/io
22
+ false
23
+ else
24
+ raise "lock type must be one of (r)ead|(sh)ared|(w)rite|(ex)clusive, not <#{ ltype }>"
25
+ end
26
+ cmd = @argv.join(' ').strip
27
+ raise "no command given for lock type <#{ ltype }>" if cmd.empty?
28
+ debug{ "cmd <#{ cmd }>" }
29
+ @q.lock(:read_only => read_only){ Util::system cmd }
30
+ #}}}
31
+ end
32
+ #}}}
33
+ end # class Locker
34
+ #}}}
35
+ end # module RQ
36
+ $__rq_locker__ = __FILE__
37
+ end
@@ -0,0 +1,117 @@
1
+ unless defined? $__rq_logging__
2
+ module RQ
3
+ #{{{
4
+ LIBDIR = File::dirname(File::expand_path(__FILE__)) + File::SEPARATOR unless
5
+ defined? LIBDIR
6
+
7
+ require "logger"
8
+
9
+ require LIBDIR + 'util'
10
+ #
11
+ # module which adds logging methods to classes
12
+ #
13
+ module Logging
14
+ #{{{
15
+ #
16
+ # a module that adds an accessor to Logging objects in ored to fix a bug where
17
+ # not all logging devices are put into sync mode, resulting in improper log
18
+ # rolling. this is a hack.
19
+ #
20
+ module LoggerExt
21
+ #{{{
22
+ attr :logdev
23
+ #}}}
24
+ end # module LoggerExt
25
+ #
26
+ # implementations of the methods shared by both classes and objects of classes
27
+ # which include Logging
28
+ #
29
+ module LogMethods
30
+ #{{{
31
+ def logger
32
+ #{{{
33
+ if defined?(@logger) and @logger
34
+ @logger
35
+ else
36
+ if Class === self
37
+ @logger = self.default_logger
38
+ else
39
+ @logger = self::class::logger
40
+ end
41
+ raise "@logger is undefined!" unless defined?(@logger) and @logger
42
+ @logger
43
+ end
44
+ #}}}
45
+ end
46
+ def logger= log
47
+ #{{{
48
+ @logger = log
49
+ @logger.extend LoggerExt
50
+ @logger.logdev.dev.sync = true
51
+ @logger
52
+ #}}}
53
+ end
54
+ def debug(*args, &block); logger.debug(*args, &block); end
55
+ def info(*args, &block); logger.info(*args, &block) ; end
56
+ def warn(*args, &block); logger.warn(*args, &block) ; end
57
+ def error(*args, &block); logger.error(*args, &block); end
58
+ def fatal(*args, &block); logger.fatal(*args, &block); end
59
+ def logerr e
60
+ #{{{
61
+ if logger.debug?
62
+ error{ Util::errmsg e }
63
+ else
64
+ error{ Util::emsg e }
65
+ end
66
+ #}}}
67
+ end
68
+ #}}}
69
+ end # module LogMethods
70
+ EOL = "\n"
71
+ DIV0 = ("." * 79) << EOL
72
+ DIV1 = ("-" * 79) << EOL
73
+ DIV2 = ("=" * 79) << EOL
74
+ DIV3 = ("#" * 79) << EOL
75
+ SEC0 = ("." * 16) << EOL
76
+ SEC1 = ("-" * 16) << EOL
77
+ SEC2 = ("=" * 16) << EOL
78
+ SEC3 = ("#" * 16) << EOL
79
+ class << self
80
+ #{{{
81
+ def append_features c
82
+ #{{{
83
+ ret = super
84
+ c.extend LogMethods
85
+ class << c
86
+ def default_logger
87
+ #{{{
88
+ if defined?(@default_logger) and @default_logger
89
+ @default_logger
90
+ else
91
+ self.default_logger = Logger.new STDOUT
92
+ @default_logger.debug{ "<#{ self }> using default logger"}
93
+ @default_logger
94
+ end
95
+ #}}}
96
+ end
97
+ def default_logger= log
98
+ #{{{
99
+ @default_logger = log
100
+ @default_logger.extend LoggerExt
101
+ @default_logger.logdev.dev.sync = true
102
+ @default_logger
103
+ #}}}
104
+ end
105
+ end
106
+ ret
107
+ #}}}
108
+ end
109
+ #}}}
110
+ end
111
+ include LogMethods
112
+ #}}}
113
+ end # module Logging
114
+ #}}}
115
+ end # module rq
116
+ $__rq_logging__ = __FILE__
117
+ end
@@ -0,0 +1,53 @@
1
+ unless defined? $__rq_mainhelper__
2
+ module RQ
3
+ #{{{
4
+ LIBDIR = File::dirname(File::expand_path(__FILE__)) + File::SEPARATOR unless
5
+ defined? LIBDIR
6
+
7
+ require LIBDIR + 'util'
8
+ require LIBDIR + 'logging'
9
+
10
+ class MainHelper
11
+ #{{{
12
+ include Util
13
+ include Logging
14
+ attr :main
15
+ attr :logger
16
+ attr :argv
17
+ attr :env
18
+ attr :cmd
19
+ attr :options
20
+ attr :qpath
21
+ attr :mode
22
+ attr :q
23
+ def initialize main
24
+ #{{{
25
+ @main = main
26
+ @logger = main.logger
27
+ @argv = main.argv
28
+ @env = main.env
29
+ @cmd = main.cmd
30
+ @options = main.options
31
+ @qpath = main.qpath
32
+ @mode = main.mode
33
+ @q = nil
34
+ #}}}
35
+ end
36
+ def set_q
37
+ #{{{
38
+ raise "q <#{ @qpath }> does not exist" unless test ?d, @qpath
39
+ @q = JobQueue::new @qpath, 'logger' => @logger
40
+ if @options['snapshot']
41
+ ss = "#{ $0 }_#{ Process::pid }_#{ Thread::current.id.abs }_#{ rand Time::now.to_i }".gsub(%r|/|o,'_')
42
+ qtmp = File::join Dir::tmpdir, ss
43
+ @q = @q.snapshot qtmp, @options['retries']
44
+ at_exit{ FileUtils::rm_rf qtmp }
45
+ end
46
+ #}}}
47
+ end
48
+ #}}}
49
+ end # class MainHelper
50
+ #}}}
51
+ end # module RQ
52
+ $__rq_mainhelper__ = __FILE__
53
+ end