pwrake 0.9.9.2 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/CHANGES_V2.md +90 -0
  4. data/{LICENSE.txt → MIT-LICENSE} +2 -3
  5. data/README +12 -0
  6. data/README.md +75 -52
  7. data/bin/gfwhere-pipe +23 -12
  8. data/bin/pwrake +22 -29
  9. data/bin/pwrake_branch +24 -0
  10. data/lib/pwrake/branch.rb +22 -0
  11. data/lib/pwrake/branch/branch.rb +213 -0
  12. data/lib/pwrake/branch/branch_application.rb +53 -0
  13. data/lib/pwrake/branch/fiber_queue.rb +36 -0
  14. data/lib/pwrake/branch/file_utils.rb +101 -0
  15. data/lib/pwrake/branch/shell.rb +231 -0
  16. data/lib/pwrake/{profiler.rb → branch/shell_profiler.rb} +28 -27
  17. data/lib/pwrake/branch/worker_communicator.rb +104 -0
  18. data/lib/pwrake/{gfarm_feature.rb → gfarm/gfarm_path.rb} +2 -100
  19. data/lib/pwrake/gfarm/gfarm_postprocess.rb +53 -0
  20. data/lib/pwrake/iomux/channel.rb +70 -0
  21. data/lib/pwrake/iomux/handler.rb +124 -0
  22. data/lib/pwrake/iomux/handler_set.rb +35 -0
  23. data/lib/pwrake/iomux/runner.rb +62 -0
  24. data/lib/pwrake/logger.rb +3 -150
  25. data/lib/pwrake/master.rb +30 -137
  26. data/lib/pwrake/master/fiber_pool.rb +69 -0
  27. data/lib/pwrake/master/idle_cores.rb +30 -0
  28. data/lib/pwrake/master/master.rb +345 -0
  29. data/lib/pwrake/master/master_application.rb +150 -0
  30. data/lib/pwrake/master/postprocess.rb +16 -0
  31. data/lib/pwrake/{graphviz.rb → misc/graphviz.rb} +0 -0
  32. data/lib/pwrake/{mcgp.rb → misc/mcgp.rb} +63 -42
  33. data/lib/pwrake/option/host_map.rb +158 -0
  34. data/lib/pwrake/option/option.rb +357 -0
  35. data/lib/pwrake/option/option_filesystem.rb +112 -0
  36. data/lib/pwrake/queue/locality_aware_queue.rb +158 -0
  37. data/lib/pwrake/queue/no_action_queue.rb +67 -0
  38. data/lib/pwrake/queue/queue_array.rb +366 -0
  39. data/lib/pwrake/queue/task_queue.rb +164 -0
  40. data/lib/pwrake/report.rb +1 -0
  41. data/lib/pwrake/report/parallelism.rb +9 -3
  42. data/lib/pwrake/report/report.rb +50 -103
  43. data/lib/pwrake/report/task_stat.rb +83 -0
  44. data/lib/pwrake/task/task_algorithm.rb +107 -0
  45. data/lib/pwrake/task/task_manager.rb +32 -0
  46. data/lib/pwrake/task/task_property.rb +98 -0
  47. data/lib/pwrake/task/task_rank.rb +48 -0
  48. data/lib/pwrake/task/task_wrapper.rb +296 -0
  49. data/lib/pwrake/version.rb +1 -1
  50. data/lib/pwrake/worker/executor.rb +169 -0
  51. data/lib/pwrake/worker/gfarm_directory.rb +90 -0
  52. data/lib/pwrake/worker/invoker.rb +199 -0
  53. data/lib/pwrake/worker/load.rb +14 -0
  54. data/lib/pwrake/worker/log_executor.rb +73 -0
  55. data/lib/pwrake/worker/shared_directory.rb +74 -0
  56. data/lib/pwrake/worker/worker_main.rb +14 -0
  57. data/lib/pwrake/worker/writer.rb +59 -0
  58. data/setup.rb +1212 -1502
  59. data/spec/003/Rakefile +2 -2
  60. data/spec/008/Rakefile +2 -1
  61. data/spec/009/Rakefile +1 -1
  62. data/spec/009/pwrake_conf.yaml +1 -3
  63. data/spec/hosts +0 -2
  64. data/spec/pwrake_spec.rb +9 -8
  65. metadata +50 -21
  66. data/lib/pwrake.rb +0 -19
  67. data/lib/pwrake/application.rb +0 -232
  68. data/lib/pwrake/counter.rb +0 -54
  69. data/lib/pwrake/file_utils.rb +0 -98
  70. data/lib/pwrake/gfwhere_pool.rb +0 -109
  71. data/lib/pwrake/host_list.rb +0 -88
  72. data/lib/pwrake/locality_aware_queue.rb +0 -413
  73. data/lib/pwrake/option.rb +0 -400
  74. data/lib/pwrake/rake_modify.rb +0 -14
  75. data/lib/pwrake/shell.rb +0 -186
  76. data/lib/pwrake/task_algorithm.rb +0 -475
  77. data/lib/pwrake/task_queue.rb +0 -633
  78. data/lib/pwrake/timer.rb +0 -22
@@ -1,400 +0,0 @@
1
- module Pwrake
2
-
3
- START_TIME = Time.now
4
-
5
- module Option
6
-
7
- DEFAULT_CONFFILES = ["pwrake_conf.yaml","PwrakeConf.yaml"]
8
-
9
- def format_time_pid(v)
10
- START_TIME.strftime(v).sub("%$","%05d"%Process.pid)
11
- end
12
-
13
- def parse_opt(s)
14
- case s
15
- when /^(false|nil|off)$/i
16
- false
17
- when /^(true|on)$/i
18
- true
19
- else
20
- s
21
- end
22
- end
23
-
24
- def option_data
25
- [
26
- 'DRYRUN',
27
- 'IGNORE_SYSTEM',
28
- 'IGNORE_DEPRECATE',
29
- 'LOAD_SYSTEM',
30
- 'NOSEARCH',
31
- 'RAKELIB',
32
- 'SHOW_PREREQS',
33
- 'SILENT',
34
- 'TRACE',
35
- 'TRACE_RULES',
36
-
37
- 'FILESYSTEM',
38
- 'SSH_OPTION',
39
- 'PASS_ENV',
40
- 'GNU_TIME',
41
- 'DEBUG',
42
- 'PLOT_PARALLELISM',
43
- 'HALT_QUEUE_WHILE_SEARCH',
44
- 'SHOW_CONF',
45
- 'FAILED_TARGET', # rename(default), delete, leave
46
- 'QUEUE_PRIORITY', # RANK(default), FIFO, LIFO, DFS
47
- 'NOACTION_QUEUE_PRIORITY', # FIFO(default), LIFO, RAND
48
- 'NUM_NOACTION_THREADS', # default=4 when gfarm, else 1
49
- 'STEAL_WAIT',
50
- 'STEAL_WAIT_MAX',
51
- 'GRAPH_PARTITION',
52
- 'PLOT_PARTITION',
53
-
54
- ['HOSTFILE','HOSTS'],
55
- ['LOGFILE','LOG',
56
- proc{|v|
57
- if v
58
- # turn trace option on
59
- Rake.application.options.trace = true
60
- if v == "" || !v.kind_of?(String)
61
- v = "Pwrake%Y%m%d-%H%M%S_%$.log"
62
- end
63
- format_time_pid(v)
64
- end
65
- }],
66
- ['TASKLOG',
67
- proc{|v|
68
- if v
69
- if v == "" || !v.kind_of?(String)
70
- v = "Pwrake%Y%m%d-%H%M%S_%$.task"
71
- end
72
- format_time_pid(v)
73
- end
74
- }],
75
- ['PROFILE',
76
- proc{|v|
77
- if v
78
- if v == "" || !v.kind_of?(String)
79
- v = "Pwrake%Y%m%d-%H%M%S_%$.csv"
80
- end
81
- format_time_pid(v)
82
- end
83
- }],
84
- ['GC_PROFILE',
85
- proc{|v|
86
- if v
87
- if v == "" || !v.kind_of?(String)
88
- v = "Pwrake%Y%m%d-%H%M%S_%$.gcprof"
89
- end
90
- format_time_pid(v)
91
- end
92
- }],
93
- ['NUM_THREADS', proc{|v| v && v.to_i}],
94
- ['THREAD_CREATE_INTERVAL', proc{|v| (v || 0.010).to_f}],
95
- ['DISABLE_AFFINITY', proc{|v| v || ENV['AFFINITY']=='off'}],
96
- ['DISABLE_STEAL', proc{|v| v || ENV['STEAL']=='off'}],
97
- ['GFARM_BASEDIR', proc{|v| v || '/tmp'}],
98
- ['GFARM_PREFIX', proc{|v| v || "pwrake_#{ENV['USER']}"}],
99
- ['GFARM_SUBDIR', proc{|v| v || '/'}],
100
- ['MAX_GFWHERE_WORKER', proc{|v| (v || 8).to_i}],
101
- ['MASTER_HOSTNAME', proc{|v| (v || begin;`hostname -f`;rescue;end || '').chomp}],
102
- ['WORK_DIR',proc{|v|
103
- v ||= '$HOME/%CWD_RELATIVE_TO_HOME'
104
- v.sub('%CWD_RELATIVE_TO_HOME',cwd_relative_to_home)
105
- }],
106
- ]
107
- end
108
-
109
-
110
- # ----- init -----
111
-
112
- def init_option
113
- init_options
114
- init_pass_env
115
- init_logger
116
- Log.info "Options:"
117
- @opts.each do |k,v|
118
- Log.info " #{k} = #{v.inspect}"
119
- end
120
- if @opts['SHOW_CONF']
121
- require "yaml"
122
- YAML.dump(@opts,$stdout)
123
- exit
124
- end
125
- if @opts['GC_PROFILE']
126
- GC::Profiler.enable
127
- end
128
- @counter = Counter.new
129
- end
130
-
131
- attr_reader :host_list
132
- attr_reader :counter
133
- attr_reader :logfile
134
- attr_reader :queue_class
135
- attr_reader :shell_class
136
- attr_reader :task_logger
137
-
138
- def pwrake_options
139
- @opts
140
- end
141
-
142
- def init_options
143
- # Read pwrake_conf
144
- @pwrake_conf = Rake.application.options.pwrake_conf
145
-
146
- if @pwrake_conf
147
- if !File.exist?(@pwrake_conf)
148
- raise "Configuration file not found: #{@pwrake_conf}"
149
- end
150
- else
151
- @pwrake_conf = DEFAULT_CONFFILES.find{|fn| File.exist?(fn)}
152
- end
153
-
154
- if @pwrake_conf.nil?
155
- @yaml = {}
156
- else
157
- Log.debug "--- @pwrake_conf=#{@pwrake_conf}"
158
- require "yaml"
159
- @yaml = open(@pwrake_conf){|f| YAML.load(f) }
160
- end
161
-
162
- @opts = { 'PWRAKE_CONF' => @pwrake_conf, }
163
-
164
- option_data.each do |a|
165
- prc = nil
166
- keys = []
167
- case a
168
- when String
169
- keys << a
170
- when Array
171
- a.each do |x|
172
- case x
173
- when String
174
- keys << x
175
- when Proc
176
- prc = x
177
- end
178
- end
179
- end
180
- key = keys[0]
181
- val = search_opts(keys)
182
- val = prc.call(val) if prc
183
- @opts[key] = val if !val.nil?
184
- instance_variable_set("@"+key.downcase, val)
185
- end
186
-
187
- feedback_options [
188
- 'DRYRUN',
189
- 'IGNORE_SYSTEM',
190
- 'IGNORE_DEPRECATE',
191
- 'LOAD_SYSTEM',
192
- 'NOSEARCH',
193
- 'RAKELIB',
194
- 'SHOW_PREREQS',
195
- 'SILENT',
196
- 'TRACE',
197
- 'TRACE_RULES']
198
- Rake.verbose(false) if Rake.application.options.silent
199
- end
200
-
201
- def feedback_options(a)
202
- a.each do |k|
203
- if v=@opts[k]
204
- m = (k.downcase+"=").to_sym
205
- Rake.application.options.send(m,v)
206
- end
207
- end
208
- end
209
-
210
- # Option order:
211
- # command_option > ENV > pwrake_conf > DEFAULT_OPTIONS
212
- def search_opts(keys)
213
- val = Rake.application.options.send(keys[0].downcase.to_sym)
214
- return parse_opt(val) if !val.nil?
215
- #
216
- keys.each do |k|
217
- val = ENV[k.upcase]
218
- return parse_opt(val) if !val.nil?
219
- end
220
- #
221
- return nil if !@yaml
222
- keys.each do |k|
223
- val = @yaml[k.upcase]
224
- return val if !val.nil?
225
- end
226
- nil
227
- end
228
-
229
- def cwd_relative_to_home
230
- Pathname.pwd.relative_path_from(Pathname.new(ENV['HOME'])).to_s
231
- end
232
-
233
- def cwd_relative_if_under_home
234
- home = Pathname.new(ENV['HOME']).realpath
235
- path = pwd = Pathname.pwd.realpath
236
- while path != home
237
- if path.root?
238
- return pwd.to_s
239
- end
240
- path = path.parent
241
- end
242
- return pwd.relative_path_from(home).to_s
243
- end
244
-
245
- def init_pass_env
246
- if envs = @opts['PASS_ENV']
247
- pass_env = {}
248
-
249
- case envs
250
- when Array
251
- envs.each do |k|
252
- k = k.to_s
253
- if v = ENV[k]
254
- pass_env[k] = v
255
- end
256
- end
257
- when Hash
258
- envs.each do |k,v|
259
- k = k.to_s
260
- if v = ENV[k] || v
261
- pass_env[k] = v
262
- end
263
- end
264
- else
265
- raise "invalid option for PASS_ENV in pwrake_conf.yaml"
266
- end
267
-
268
- if pass_env.empty?
269
- @opts.delete('PASS_ENV')
270
- else
271
- @opts['PASS_ENV'] = pass_env
272
- end
273
- end
274
- end
275
-
276
- def init_logger
277
- if Rake.application.options.debug
278
- Log.level = Log::DEBUG
279
- elsif Rake.application.options.trace
280
- Log.level = Log::INFO
281
- else
282
- Log.level = Log::WARN
283
- end
284
-
285
- if @logfile
286
- logdir = File.dirname(@logfile)
287
- if !File.directory?(logdir)
288
- mkdir_p logdir
289
- end
290
- Log.open(@logfile)
291
- else
292
- Log.open($stdout)
293
- end
294
-
295
- if @tasklog
296
- @task_logger = File.open(@tasklog,'w')
297
- h = %w[
298
- task_id task_name start_time end_time elap_time preq preq_host
299
- exec_host shell_id has_action executed file_size file_mtime file_host
300
- ].join(',')+"\n"
301
- @task_logger.print h
302
- end
303
- end
304
-
305
- # ----- setup -----
306
-
307
- def setup_option
308
- set_hosts
309
- set_filesystem
310
- end
311
-
312
- def set_hosts
313
- if @hostfile && @num_threads
314
- raise "Cannot set `hostfile' and `num_threads' simultaneously"
315
- end
316
- @host_list = HostList.new(@hostfile || @num_threads)
317
- Log.info "num_cores=#{@host_list.size}"
318
- end
319
-
320
- def set_filesystem
321
- if fn = @opts["PROFILE"]
322
- Shell.profiler.open(fn,@opts['GNU_TIME'],@opts['PLOT_PARALLELISM'])
323
- end
324
-
325
- @shell_opt = {
326
- :work_dir => @opts['WORK_DIR'],
327
- :pass_env => @opts['PASS_ENV'],
328
- :ssh_opt => @opts['SSH_OPTION']
329
- }
330
-
331
- if @filesystem.nil?
332
- case mount_type
333
- when /gfarm2fs/
334
- @opts['FILESYSTEM'] = @filesystem = 'gfarm'
335
- end
336
- end
337
-
338
- n_noaction_th = @opts['NUM_NOACTION_THREADS']
339
-
340
- case @filesystem
341
- when 'gfarm'
342
- require "pwrake/locality_aware_queue"
343
- require "pwrake/gfarm_feature"
344
- GfarmPath.subdir = @opts['GFARM_SUBDIR']
345
- @filesystem = 'gfarm'
346
- @shell_class = GfarmShell
347
- @shell_opt.merge!({
348
- :work_dir => Dir.pwd,
349
- :single_mp => @opts['GFARM_SINGLE_MP'],
350
- :basedir => @opts['GFARM_BASEDIR'],
351
- :prefix => @opts['GFARM_PREFIX']
352
- })
353
- if @opts['DISABLE_AFFINITY']
354
- @queue_class = TaskQueue
355
- else
356
- @queue_class = LocalityAwareQueue
357
- end
358
- @num_noaction_threads = (n_noaction_th || [8,@host_list.num_threads].max).to_i
359
- @postprocess = GfarmPostprocess.new
360
- Log.debug "--- @queue_class=#{@queue_class}"
361
- else
362
- @filesystem = 'nfs'
363
- @shell_class = Shell
364
- @queue_class = TaskQueue
365
- @num_noaction_threads = (n_noaction_th || 1).to_i
366
- end
367
- end
368
-
369
- def mount_type(d=nil)
370
- mtab = '/etc/mtab'
371
- if File.exist?(mtab)
372
- d ||= mountpoint_of_cwd
373
- open(mtab,'r') do |f|
374
- f.each_line do |l|
375
- if /#{d} (?:type )?(\S+)/o =~ l
376
- return $1
377
- end
378
- end
379
- end
380
- end
381
- nil
382
- end
383
-
384
- def mountpoint_of_cwd
385
- d = Pathname.pwd
386
- while !d.mountpoint?
387
- d = d.parent
388
- end
389
- d
390
- end
391
-
392
- # ----- finish -----
393
-
394
- def finish_option
395
- @task_logger.close if @task_logger
396
- Log.close
397
- end
398
-
399
- end
400
- end
@@ -1,14 +0,0 @@
1
- module Rake
2
-
3
- class Task
4
- include Pwrake::TaskAlgorithm
5
-
6
- alias invoke_orig :invoke
7
-
8
- def invoke(*args)
9
- invoke_modify(*args)
10
- end
11
-
12
- end
13
-
14
- end # module Rake
@@ -1,186 +0,0 @@
1
- module Pwrake
2
-
3
- class Shell
4
- CHARS='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
5
- TLEN=32
6
-
7
- OPEN_LIST={}
8
-
9
- def self.nice=(nice)
10
- @@nice=nice
11
- end
12
-
13
- def self.reset_id
14
- @@current_id = 0
15
- end
16
-
17
- @@nice = "nice"
18
- @@shell = "sh"
19
- @@current_id = 0
20
- @@profiler = Profiler.new
21
-
22
- def self.profiler
23
- @@profiler
24
- end
25
-
26
- def initialize(host,opt={})
27
- @host = host || 'localhost'
28
- @lock = Mutex.new
29
- @@current_id += 1
30
- @id = @@current_id
31
- @option = opt
32
- @work_dir = @option[:work_dir] || Dir.pwd
33
- @pass_env = @option[:pass_env]
34
- @ssh_opt = @option[:ssh_opt]
35
- @terminator = ""
36
- TLEN.times{ @terminator << CHARS[rand(CHARS.length)] }
37
- end
38
-
39
- attr_reader :id, :host
40
- attr_accessor :current_task
41
-
42
- def system_cmd(*arg)
43
- if ['localhost','localhost.localdomain','127.0.0.1'].include? @host
44
- [@@nice,@@shell].join(' ')
45
- else
46
- "ssh -x -T -q #{@ssh_opt} #{@host} #{@@nice} #{@@shell}"
47
- end
48
- end
49
-
50
- def start
51
- open(system_cmd)
52
- cd_work_dir
53
- end
54
-
55
- def open(cmd,path=nil)
56
- if path.nil?
57
- path = ENV['PATH']
58
- end
59
- @io = IO.popen( cmd, "r+" )
60
- OPEN_LIST[__id__] = self
61
- _system "export PATH='#{path}'"
62
- if @pass_env
63
- @pass_env.each do |k,v|
64
- _system "export #{k}='#{v}'"
65
- end
66
- end
67
- end
68
-
69
- attr_reader :host, :status, :profile
70
-
71
- def finish
72
- close
73
- end
74
-
75
- def close
76
- @lock.synchronize do
77
- if !@io.closed?
78
- @io.puts("exit")
79
- @io.close
80
- end
81
- OPEN_LIST.delete(__id__)
82
- end
83
- end
84
-
85
- def backquote(*command)
86
- command = command.join(' ')
87
- @lock.synchronize do
88
- a = []
89
- _execute(command){|x| a << x}
90
- a.join("\n")
91
- end
92
- end
93
-
94
- def system(*command)
95
- command = command.join(' ')
96
- Log.debug "--- command=#{command.inspect}"
97
- @lock.synchronize do
98
- _execute(command){|x| Log.stdout_puts x}
99
- end
100
- @status == 0
101
- end
102
-
103
- def cd_work_dir
104
- _system("cd #{@work_dir}") or die
105
- end
106
-
107
- def cd(dir="")
108
- _system("cd #{dir}") or die
109
- end
110
-
111
- def die
112
- raise "Failed at #{@host}, id=#{@id}, cmd='#{@cmd}'"
113
- end
114
-
115
- END {
116
- OPEN_LIST.map do |k,v|
117
- v.close
118
- end
119
- Shell.profiler.close
120
- }
121
-
122
- private
123
-
124
- def _system(cmd)
125
- @cmd = cmd
126
- raise "@io is closed" if @io.closed?
127
- @lock.synchronize do
128
- @io.puts(cmd+"\necho '#{@terminator}':$? ")
129
- @io.flush
130
- status = io_read_loop{}
131
- Integer(status||1) == 0
132
- end
133
- end
134
-
135
- def _backquote(cmd)
136
- @cmd = cmd
137
- raise "@io is closed" if @io.closed?
138
- a = []
139
- @lock.synchronize do
140
- @io.puts(cmd+"\necho '#{@terminator}':$? ")
141
- status = io_read_loop{|x| a << x}
142
- end
143
- a.join("\n")
144
- end
145
-
146
- def _execute(cmd,quote=nil,&block)
147
- @cmd = cmd
148
- raise "@io is closed" if @io.closed?
149
- status = nil
150
-
151
- start_time = Time.now
152
- begin
153
- @io.puts @@profiler.command(cmd,@terminator)
154
- status = io_read_loop(&block)
155
- ensure
156
- end_time = Time.now
157
- @status = @@profiler.profile(@current_task, cmd,
158
- start_time, end_time, host, status)
159
- end
160
- end
161
-
162
- def io_read_loop
163
- while x = @io.gets
164
- x.chomp!
165
- if x[0,TLEN] == @terminator
166
- return x[TLEN+1..-1]
167
- end
168
- yield x
169
- end
170
- end
171
- end
172
-
173
-
174
- class NoActionShell < Shell
175
- def initialize()
176
- @host = '(noaction)'
177
- @@current_id += 1
178
- @id = @@current_id
179
- end
180
- def start
181
- end
182
- def finish
183
- end
184
- end
185
-
186
- end # module Pwrake