rq-ruby1.8 3.4.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. data/Gemfile +22 -0
  2. data/Gemfile.lock +22 -0
  3. data/INSTALL +166 -0
  4. data/LICENSE +10 -0
  5. data/Makefile +6 -0
  6. data/README +1183 -0
  7. data/Rakefile +37 -0
  8. data/TODO +24 -0
  9. data/TUTORIAL +230 -0
  10. data/VERSION +1 -0
  11. data/bin/rq +902 -0
  12. data/bin/rqmailer +865 -0
  13. data/example/a.rb +7 -0
  14. data/extconf.rb +198 -0
  15. data/gemspec.rb +40 -0
  16. data/install.rb +210 -0
  17. data/lib/rq.rb +155 -0
  18. data/lib/rq/arrayfields.rb +371 -0
  19. data/lib/rq/backer.rb +31 -0
  20. data/lib/rq/configfile.rb +82 -0
  21. data/lib/rq/configurator.rb +40 -0
  22. data/lib/rq/creator.rb +54 -0
  23. data/lib/rq/cron.rb +144 -0
  24. data/lib/rq/defaultconfig.txt +5 -0
  25. data/lib/rq/deleter.rb +51 -0
  26. data/lib/rq/executor.rb +40 -0
  27. data/lib/rq/feeder.rb +527 -0
  28. data/lib/rq/ioviewer.rb +48 -0
  29. data/lib/rq/job.rb +51 -0
  30. data/lib/rq/jobqueue.rb +947 -0
  31. data/lib/rq/jobrunner.rb +110 -0
  32. data/lib/rq/jobrunnerdaemon.rb +193 -0
  33. data/lib/rq/lister.rb +47 -0
  34. data/lib/rq/locker.rb +43 -0
  35. data/lib/rq/lockfile.rb +564 -0
  36. data/lib/rq/logging.rb +124 -0
  37. data/lib/rq/mainhelper.rb +189 -0
  38. data/lib/rq/orderedautohash.rb +39 -0
  39. data/lib/rq/orderedhash.rb +240 -0
  40. data/lib/rq/qdb.rb +733 -0
  41. data/lib/rq/querier.rb +98 -0
  42. data/lib/rq/rails.rb +80 -0
  43. data/lib/rq/recoverer.rb +28 -0
  44. data/lib/rq/refresher.rb +80 -0
  45. data/lib/rq/relayer.rb +283 -0
  46. data/lib/rq/resource.rb +22 -0
  47. data/lib/rq/resourcemanager.rb +40 -0
  48. data/lib/rq/resubmitter.rb +100 -0
  49. data/lib/rq/rotater.rb +98 -0
  50. data/lib/rq/sleepcycle.rb +46 -0
  51. data/lib/rq/snapshotter.rb +40 -0
  52. data/lib/rq/sqlite.rb +286 -0
  53. data/lib/rq/statuslister.rb +48 -0
  54. data/lib/rq/submitter.rb +113 -0
  55. data/lib/rq/toucher.rb +182 -0
  56. data/lib/rq/updater.rb +94 -0
  57. data/lib/rq/usage.rb +1222 -0
  58. data/lib/rq/util.rb +304 -0
  59. data/rdoc.sh +17 -0
  60. data/rq-ruby1.8.gemspec +120 -0
  61. data/test/.gitignore +1 -0
  62. data/test/test_rq.rb +145 -0
  63. data/white_box/crontab +2 -0
  64. data/white_box/joblist +8 -0
  65. data/white_box/killrq +18 -0
  66. data/white_box/rq_killer +27 -0
  67. metadata +208 -0
@@ -0,0 +1,304 @@
1
+ unless defined? $__rq_util__
2
+ module RQ
3
+ #--{{{
4
+ LIBDIR = File::dirname(File::expand_path(__FILE__)) + File::SEPARATOR unless
5
+ defined? LIBDIR
6
+
7
+ require 'pathname'
8
+ require 'socket'
9
+ require 'tmpdir'
10
+
11
+ #
12
+ # of course - all the rest goes here
13
+ #
14
+ module Util
15
+ #--{{{
16
+ class << self
17
+ def export sym
18
+ #--{{{
19
+ sym = "#{ sym }".intern
20
+ module_function sym
21
+ public sym
22
+ #--}}}
23
+ end
24
+ def append_features c
25
+ #--{{{
26
+ super
27
+ c.extend Util
28
+ #--}}}
29
+ end
30
+ end
31
+ def mcp obj
32
+ #--{{{
33
+ Marshal.load(Marshal.dump(obj))
34
+ #--}}}
35
+ end
36
+ export 'mcp'
37
+ def klass
38
+ #--{{{
39
+ self.class
40
+ #--}}}
41
+ end
42
+ export 'klass'
43
+ def realpath path
44
+ #--{{{
45
+ path = File::expand_path "#{ path }"
46
+ begin
47
+ Pathname::new(path).realpath.to_s
48
+ rescue Errno::ENOENT, Errno::ENOTDIR
49
+ path
50
+ end
51
+ #--}}}
52
+ end
53
+ export 'realpath'
54
+ def hashify(*hashes)
55
+ #--{{{
56
+ hashes.inject(accum={}){|accum,hash| accum.update hash}
57
+ #--}}}
58
+ end
59
+ export 'hashify'
60
+ def getopt opt, hash, default = nil
61
+ #--{{{
62
+ key = opt
63
+ return hash[key] if hash.has_key? key
64
+
65
+ key = "#{ key }"
66
+ return hash[key] if hash.has_key? key
67
+
68
+ key = key.intern
69
+ return hash[key] if hash.has_key? key
70
+
71
+ return default
72
+ #--}}}
73
+ end
74
+ export 'getopt'
75
+ def alive? pid
76
+ #--{{{
77
+ pid = Integer("#{ pid }")
78
+ begin
79
+ Process.kill 0, pid
80
+ true
81
+ rescue Errno::ESRCH
82
+ false
83
+ end
84
+ #--}}}
85
+ end
86
+ export 'alive?'
87
+ def maim(pid, opts = {})
88
+ #--{{{
89
+ sigs = getopt('signals', opts) || %w(SIGTERM SIGQUIT SIGKILL)
90
+ suspend = getopt('suspend', opts) || 4
91
+ pid = Integer("#{ pid }")
92
+ sigs.each do |sig|
93
+ begin
94
+ Process.kill(sig, pid)
95
+ rescue Errno::ESRCH
96
+ return nil
97
+ end
98
+ sleep 0.2
99
+ unless alive?(pid)
100
+ break
101
+ else
102
+ sleep suspend
103
+ end
104
+ end
105
+ not alive?(pid)
106
+ #--}}}
107
+ end
108
+ export 'maim'
109
+ def timestamp time = Time.now
110
+ #--{{{
111
+ usec = "#{ time.usec }"
112
+ usec << ('0' * (6 - usec.size)) if usec.size < 6
113
+ time.strftime('%Y-%m-%d %H:%M:%S.') << usec
114
+ #--}}}
115
+ end
116
+ export 'timestamp'
117
+ def stamptime string, local = true
118
+ #--{{{
119
+ string = "#{ string }"
120
+ pat = %r/^\s*(\d\d\d\d)-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d).(\d\d\d\d\d\d)\s*$/o
121
+ match = pat.match string
122
+ raise ArgumentError, "<#{ string.inspect }>" unless match
123
+ yyyy,mm,dd,h,m,s,u = match.to_a[1..-1].map{|m| m.to_i}
124
+ if local
125
+ Time.local yyyy,mm,dd,h,m,s,u
126
+ else
127
+ Time.gm yyyy,mm,dd,h,m,s,u
128
+ end
129
+ #--}}}
130
+ end
131
+ export 'stamptime'
132
+ def escape! s, char, esc
133
+ #--{{{
134
+ re = %r/([#{0x5c.chr << esc}]*)#{char}/
135
+ s.gsub!(re) do
136
+ (($1.size % 2 == 0) ? ($1 << esc) : $1) + char
137
+ end
138
+ #--}}}
139
+ end
140
+ export 'escape!'
141
+ def escape s, char, esc
142
+ #--{{{
143
+ ss = "#{ s }"
144
+ escape! ss, char, esc
145
+ ss
146
+ #--}}}
147
+ end
148
+ export 'escape'
149
+ def fork(*args, &block)
150
+ #--{{{
151
+ begin
152
+ verbose = $VERBOSE
153
+ $VERBOSE = nil
154
+ Process::fork(*args, &block)
155
+ ensure
156
+ $VERBOSE = verbose
157
+ end
158
+ #--}}}
159
+ end
160
+ export 'fork'
161
+ def exec(*args, &block)
162
+ #--{{{
163
+ begin
164
+ verbose = $VERBOSE
165
+ $VERBOSE = nil
166
+ Kernel::exec(*args, &block)
167
+ ensure
168
+ $VERBOSE = verbose
169
+ end
170
+ #--}}}
171
+ end
172
+ export 'exec'
173
+ def system(*args, &block)
174
+ #--{{{
175
+ begin
176
+ verbose = $VERBOSE
177
+ $VERBOSE = nil
178
+ Kernel::system(*args, &block)
179
+ ensure
180
+ $VERBOSE = verbose
181
+ end
182
+ #--}}}
183
+ end
184
+ export 'system'
185
+ def hostname
186
+ #--{{{
187
+ @__hostname__ ||= Socket::gethostname
188
+ #--}}}
189
+ end
190
+ export 'hostname'
191
+ def host
192
+ #--{{{
193
+ @__host__ ||= Socket::gethostname.gsub(%r/\..*$/o,'')
194
+ #--}}}
195
+ end
196
+ export 'host'
197
+ def emsg e
198
+ #--{{{
199
+ "#{ e.message } - (#{ e.class })"
200
+ #--}}}
201
+ end
202
+ export 'emsg'
203
+ def btrace e
204
+ #--{{{
205
+ (e.backtrace or []).join("\n")
206
+ #--}}}
207
+ end
208
+ export 'btrace'
209
+ def errmsg e
210
+ #--{{{
211
+ emsg(e) << "\n" << btrace(e)
212
+ #--}}}
213
+ end
214
+ export 'errmsg'
215
+ def erreq a, b
216
+ #--{{{
217
+ a.class == b.class and
218
+ a.message == b.message and
219
+ a.backtrace == b.backtrace
220
+ #--}}}
221
+ end
222
+ export 'erreq'
223
+ def tmpnam dir = Dir.tmpdir, seed = File::basename($0)
224
+ #--{{{
225
+ pid = Process.pid
226
+ path = "%s_%s_%s_%s_%d" %
227
+ [Util::hostname, seed, pid, Util::timestamp.gsub(/\s+/o,'_'), rand(101010)]
228
+ File::join(dir, path)
229
+ #--}}}
230
+ end
231
+ export 'tmpnam'
232
+ def uncache file
233
+ #--{{{
234
+ refresh = nil
235
+ begin
236
+ is_a_file = File === file
237
+ path = (is_a_file ? file.path : file.to_s)
238
+ stat = (is_a_file ? file.stat : File::stat(file.to_s))
239
+ refresh = tmpnam(File::dirname(path))
240
+ File::link path, refresh rescue File::symlink path, refresh
241
+ File::chmod stat.mode, path
242
+ File::utime stat.atime, stat.mtime, path
243
+ ensure
244
+ begin
245
+ File::unlink refresh if refresh
246
+ rescue Errno::ENOENT
247
+ end
248
+ end
249
+ #--}}}
250
+ end
251
+ export 'uncache'
252
+ def columnize buf, width = 80, indent = 0
253
+ #--{{{
254
+ column = []
255
+ words = buf.split %r/\s+/o
256
+ row = ' ' * indent
257
+ while((word = words.shift))
258
+ if((row.size + word.size) < (width - 1))
259
+ row << word
260
+ else
261
+ column << row
262
+ row = ' ' * indent
263
+ row << word
264
+ end
265
+ row << ' ' unless row.size == (width - 1)
266
+ end
267
+ column << row unless row.strip.empty?
268
+ column.join "\n"
269
+ #--}}}
270
+ end
271
+ export 'columnize'
272
+ def defval var, default = nil
273
+ #--{{{
274
+ v = "#{ var }"
275
+ c = "DEFAULT_#{ v }".upcase
276
+ begin
277
+ klass.send(v) || klass.const_get(c)
278
+ rescue NameError
279
+ default
280
+ end
281
+ #--}}}
282
+ end
283
+ export 'defval'
284
+ def hms s
285
+ #--{{{
286
+ h, s = s.divmod 3600
287
+ m, s = s.divmod 60
288
+ [h.to_i, m.to_i, s]
289
+ #--}}}
290
+ end
291
+ export 'hms'
292
+ def which_ruby
293
+ #--{{{
294
+ c = ::Config::CONFIG
295
+ realpath( File::join(c['bindir'], c['ruby_install_name']) << c['EXEEXT'] )
296
+ #--}}}
297
+ end
298
+ export 'which_ruby'
299
+ #--}}}
300
+ end # module Util
301
+ #--}}}
302
+ end # module RQ
303
+ $__rq_util__ = __FILE__
304
+ end
data/rdoc.sh ADDED
@@ -0,0 +1,17 @@
1
+ #!/bin/sh
2
+
3
+ #
4
+ # workaround so bin/* gets doc'd as ruby files
5
+ #
6
+
7
+ pushd .
8
+ cd bin
9
+ for f in *; do ln -s $f "$f.rb"; done
10
+ popd
11
+
12
+ rdoc -a -d -F -S -m README -I jpg -N [A-Z]* bin/rq.rb lib/rq.rb lib/*/*
13
+
14
+ pushd .
15
+ cd bin
16
+ for f in *rb; do rm -f $f; done
17
+ popd
@@ -0,0 +1,120 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{rq-ruby1.8}
8
+ s.version = "3.4.3"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Pjotr Prins"]
12
+ s.date = %q{2011-07-21}
13
+ s.description = %q{Zero configuration job scheduler for computer clusters}
14
+ s.email = %q{pjotr.public01@thebird.nl}
15
+ s.executables = ["rqmailer", "rq"]
16
+ s.extra_rdoc_files = [
17
+ "LICENSE",
18
+ "README",
19
+ "TODO"
20
+ ]
21
+ s.files = [
22
+ "Gemfile",
23
+ "Gemfile.lock",
24
+ "INSTALL",
25
+ "LICENSE",
26
+ "Makefile",
27
+ "README",
28
+ "Rakefile",
29
+ "TODO",
30
+ "TUTORIAL",
31
+ "VERSION",
32
+ "bin/rq",
33
+ "bin/rqmailer",
34
+ "example/a.rb",
35
+ "extconf.rb",
36
+ "gemspec.rb",
37
+ "install.rb",
38
+ "lib/rq.rb",
39
+ "lib/rq/arrayfields.rb",
40
+ "lib/rq/backer.rb",
41
+ "lib/rq/configfile.rb",
42
+ "lib/rq/configurator.rb",
43
+ "lib/rq/creator.rb",
44
+ "lib/rq/cron.rb",
45
+ "lib/rq/defaultconfig.txt",
46
+ "lib/rq/deleter.rb",
47
+ "lib/rq/executor.rb",
48
+ "lib/rq/feeder.rb",
49
+ "lib/rq/ioviewer.rb",
50
+ "lib/rq/job.rb",
51
+ "lib/rq/jobqueue.rb",
52
+ "lib/rq/jobrunner.rb",
53
+ "lib/rq/jobrunnerdaemon.rb",
54
+ "lib/rq/lister.rb",
55
+ "lib/rq/locker.rb",
56
+ "lib/rq/lockfile.rb",
57
+ "lib/rq/logging.rb",
58
+ "lib/rq/mainhelper.rb",
59
+ "lib/rq/orderedautohash.rb",
60
+ "lib/rq/orderedhash.rb",
61
+ "lib/rq/qdb.rb",
62
+ "lib/rq/querier.rb",
63
+ "lib/rq/rails.rb",
64
+ "lib/rq/recoverer.rb",
65
+ "lib/rq/refresher.rb",
66
+ "lib/rq/relayer.rb",
67
+ "lib/rq/resource.rb",
68
+ "lib/rq/resourcemanager.rb",
69
+ "lib/rq/resubmitter.rb",
70
+ "lib/rq/rotater.rb",
71
+ "lib/rq/sleepcycle.rb",
72
+ "lib/rq/snapshotter.rb",
73
+ "lib/rq/sqlite.rb",
74
+ "lib/rq/statuslister.rb",
75
+ "lib/rq/submitter.rb",
76
+ "lib/rq/toucher.rb",
77
+ "lib/rq/updater.rb",
78
+ "lib/rq/usage.rb",
79
+ "lib/rq/util.rb",
80
+ "rdoc.sh",
81
+ "rq-ruby1.8.gemspec",
82
+ "test/.gitignore",
83
+ "test/test_rq.rb",
84
+ "white_box/crontab",
85
+ "white_box/joblist",
86
+ "white_box/killrq",
87
+ "white_box/rq_killer"
88
+ ]
89
+ s.homepage = %q{http://github.com/pjotrp/rq}
90
+ s.licenses = ["BSD"]
91
+ s.require_paths = ["lib"]
92
+ s.rubygems_version = %q{1.3.7}
93
+ s.summary = %q{Ruby Queue scheduler}
94
+
95
+ if s.respond_to? :specification_version then
96
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
97
+ s.specification_version = 3
98
+
99
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
100
+ s.add_runtime_dependency(%q<posixlock>, [">= 0"])
101
+ s.add_runtime_dependency(%q<arrayfields>, [">= 0"])
102
+ s.add_runtime_dependency(%q<lockfile>, [">= 0"])
103
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.15"])
104
+ s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
105
+ else
106
+ s.add_dependency(%q<posixlock>, [">= 0"])
107
+ s.add_dependency(%q<arrayfields>, [">= 0"])
108
+ s.add_dependency(%q<lockfile>, [">= 0"])
109
+ s.add_dependency(%q<bundler>, ["~> 1.0.15"])
110
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
111
+ end
112
+ else
113
+ s.add_dependency(%q<posixlock>, [">= 0"])
114
+ s.add_dependency(%q<arrayfields>, [">= 0"])
115
+ s.add_dependency(%q<lockfile>, [">= 0"])
116
+ s.add_dependency(%q<bundler>, ["~> 1.0.15"])
117
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
118
+ end
119
+ end
120
+
@@ -0,0 +1 @@
1
+ test_queue
@@ -0,0 +1,145 @@
1
+ #!/usr/bin/ruby
2
+ #
3
+ # Test frame work for rq - tests submitting jobs to a queue,
4
+ # and the handling of them. Does not test NFS (yet).
5
+ #
6
+ # Copyright (C) 2011 Pjotr Prins <pjotr.prins@thebird.nl>
7
+
8
+ require 'yaml'
9
+
10
+ print "rq integration test suite by Pjotr Prins 2011\n"
11
+
12
+ src = File.join('..',File.dirname(__FILE__))
13
+ $rq = File.join(src,'bin','rq');
14
+ raise "Run from test folder!" if !File.executable?($rq)
15
+ $queue = './test_queue'
16
+
17
+ def rq_exec(args)
18
+ cmd = $rq + ' ' + $queue + ' ' + args
19
+ print "====> ",cmd," <===="
20
+ system(cmd)
21
+ end
22
+
23
+ def rq_status()
24
+ cmd = $rq + ' ' + $queue + ' status'
25
+ YAML.load(`#{cmd}`)
26
+ end
27
+
28
+ def error(line, msg)
29
+ p rq_status()
30
+ rq_exec('shutdown')
31
+ $stderr.print(__FILE__," ",line,": ",msg)
32
+ exit 1
33
+ end
34
+
35
+ def test_equal(line,s1,s2)
36
+ error(line,"#{s1} does not equal #{s2}") if s1 != s2
37
+ end
38
+
39
+ def kill_rq()
40
+ pstab = `ps xau|grep rq`
41
+ pstab.grep(/#{$rq}/) do | s |
42
+ # rq_exec('shutdown')
43
+ s =~ /\S+\s+(\d+)/
44
+ pid = $1
45
+ print "+++#{pid}+++\n"
46
+ system("kill -9 #{pid}")
47
+ sleep(1)
48
+ end
49
+ print `rm -rf #{$queue}`
50
+ pstab = `ps xau|grep rq`
51
+ pstab.grep(/#{$rq}/) do | s |
52
+ error(__LINE__,"Sorry, still running:\n"+s)
53
+ end
54
+ pstab = `ps xau|grep rq`
55
+ pstab.grep(/rq_jobrunnerdaemon/) do | s |
56
+ s =~ /\S+\s+(\d+)/
57
+ pid = $1
58
+ print "+++#{pid}+++\n"
59
+ system("kill -9 #{pid}")
60
+ sleep(1)
61
+ end
62
+ pstab = `ps xau|grep rq`
63
+ pstab.grep(/rq_jobrunnerdaemon/) do | s |
64
+ error(__LINE__,"Still running "+s)
65
+ end
66
+ end
67
+
68
+
69
+ # Check dependencies
70
+ print "Running tests...\n"
71
+
72
+ # $:.unshift '/var/lib/gems/1.8/gems/sqlite-ruby-2.2.3/lib/'
73
+ # test_equal(__LINE__,SQLite::Version::STRING,"2.2.3")
74
+
75
+ gempath = '/var/lib/gems/1.8/gems/sqlite-1.3.1/lib'
76
+ error("Expect "+gempath) if !File.directory?(gempath)
77
+ $:.unshift gempath
78
+ require 'sqlite'
79
+
80
+ kill_rq()
81
+
82
+ # In the first step we set up the queue
83
+ print `rm -rf #{$queue}`
84
+ rq_exec("create")
85
+ p rq_status()
86
+
87
+ # get status
88
+ status = rq_status()
89
+ test_equal(__LINE__,status["exit_status"],{"failures"=>0, "ok"=>0, "successes"=>0})
90
+
91
+ # submit short job
92
+ rq_exec('submit "/bin/ls /etc"')
93
+
94
+ # first time is pending
95
+ test_equal(__LINE__,rq_status()['jobs']['pending'],1)
96
+
97
+ rq_exec('submit "/bin/ls /etc"')
98
+ p rq_status()
99
+ test_equal(__LINE__,rq_status()['jobs']['total'],2)
100
+
101
+ # fire up daemon
102
+ rq_exec("feed --daemon --log=rq.log --max_feed=1 --min_sleep 1 --max_sleep 1")
103
+ 5
104
+ sleep(2)
105
+ test_equal(__LINE__,rq_status()['jobs']['total'],2)
106
+
107
+ # get status
108
+ status = rq_status()
109
+ p status
110
+ test_equal(__LINE__,status["jobs"]['total'],2)
111
+
112
+ # Now add longer jobs
113
+ rq_exec('submit "sleep 15"') # does not finish
114
+ sleep(1)
115
+ status = rq_status()
116
+ test_equal(__LINE__,status['jobs']['pending']+status['jobs']['running'],1)
117
+ rq_exec('submit "sleep 15"') # will be removed
118
+ p rq_status()
119
+ test_equal(__LINE__,rq_status()['jobs']['total'],4)
120
+
121
+ # Delete last job
122
+ rq_exec('delete 4')
123
+ sleep(2)
124
+ print "\n---\n"
125
+ print rq_exec('query state=pending')
126
+ p rq_status
127
+
128
+ # Kill rq
129
+ rq_exec('shutdown')
130
+ status = rq_status()
131
+ test_equal(__LINE__,status['jobs']['pending']+status['jobs']['running'],1)
132
+ sleep(1)
133
+ p rq_status
134
+
135
+ # Done!
136
+ print <<MSG
137
+
138
+ Congratulations, all tests passed!
139
+
140
+ This means rq accepts and executes jobs. Note, the tests
141
+ are not exhaustive, but passing them is a good sign.
142
+
143
+ MSG
144
+
145
+