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.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/CHANGES_V2.md +90 -0
- data/{LICENSE.txt → MIT-LICENSE} +2 -3
- data/README +12 -0
- data/README.md +75 -52
- data/bin/gfwhere-pipe +23 -12
- data/bin/pwrake +22 -29
- data/bin/pwrake_branch +24 -0
- data/lib/pwrake/branch.rb +22 -0
- data/lib/pwrake/branch/branch.rb +213 -0
- data/lib/pwrake/branch/branch_application.rb +53 -0
- data/lib/pwrake/branch/fiber_queue.rb +36 -0
- data/lib/pwrake/branch/file_utils.rb +101 -0
- data/lib/pwrake/branch/shell.rb +231 -0
- data/lib/pwrake/{profiler.rb → branch/shell_profiler.rb} +28 -27
- data/lib/pwrake/branch/worker_communicator.rb +104 -0
- data/lib/pwrake/{gfarm_feature.rb → gfarm/gfarm_path.rb} +2 -100
- data/lib/pwrake/gfarm/gfarm_postprocess.rb +53 -0
- data/lib/pwrake/iomux/channel.rb +70 -0
- data/lib/pwrake/iomux/handler.rb +124 -0
- data/lib/pwrake/iomux/handler_set.rb +35 -0
- data/lib/pwrake/iomux/runner.rb +62 -0
- data/lib/pwrake/logger.rb +3 -150
- data/lib/pwrake/master.rb +30 -137
- data/lib/pwrake/master/fiber_pool.rb +69 -0
- data/lib/pwrake/master/idle_cores.rb +30 -0
- data/lib/pwrake/master/master.rb +345 -0
- data/lib/pwrake/master/master_application.rb +150 -0
- data/lib/pwrake/master/postprocess.rb +16 -0
- data/lib/pwrake/{graphviz.rb → misc/graphviz.rb} +0 -0
- data/lib/pwrake/{mcgp.rb → misc/mcgp.rb} +63 -42
- data/lib/pwrake/option/host_map.rb +158 -0
- data/lib/pwrake/option/option.rb +357 -0
- data/lib/pwrake/option/option_filesystem.rb +112 -0
- data/lib/pwrake/queue/locality_aware_queue.rb +158 -0
- data/lib/pwrake/queue/no_action_queue.rb +67 -0
- data/lib/pwrake/queue/queue_array.rb +366 -0
- data/lib/pwrake/queue/task_queue.rb +164 -0
- data/lib/pwrake/report.rb +1 -0
- data/lib/pwrake/report/parallelism.rb +9 -3
- data/lib/pwrake/report/report.rb +50 -103
- data/lib/pwrake/report/task_stat.rb +83 -0
- data/lib/pwrake/task/task_algorithm.rb +107 -0
- data/lib/pwrake/task/task_manager.rb +32 -0
- data/lib/pwrake/task/task_property.rb +98 -0
- data/lib/pwrake/task/task_rank.rb +48 -0
- data/lib/pwrake/task/task_wrapper.rb +296 -0
- data/lib/pwrake/version.rb +1 -1
- data/lib/pwrake/worker/executor.rb +169 -0
- data/lib/pwrake/worker/gfarm_directory.rb +90 -0
- data/lib/pwrake/worker/invoker.rb +199 -0
- data/lib/pwrake/worker/load.rb +14 -0
- data/lib/pwrake/worker/log_executor.rb +73 -0
- data/lib/pwrake/worker/shared_directory.rb +74 -0
- data/lib/pwrake/worker/worker_main.rb +14 -0
- data/lib/pwrake/worker/writer.rb +59 -0
- data/setup.rb +1212 -1502
- data/spec/003/Rakefile +2 -2
- data/spec/008/Rakefile +2 -1
- data/spec/009/Rakefile +1 -1
- data/spec/009/pwrake_conf.yaml +1 -3
- data/spec/hosts +0 -2
- data/spec/pwrake_spec.rb +9 -8
- metadata +50 -21
- data/lib/pwrake.rb +0 -19
- data/lib/pwrake/application.rb +0 -232
- data/lib/pwrake/counter.rb +0 -54
- data/lib/pwrake/file_utils.rb +0 -98
- data/lib/pwrake/gfwhere_pool.rb +0 -109
- data/lib/pwrake/host_list.rb +0 -88
- data/lib/pwrake/locality_aware_queue.rb +0 -413
- data/lib/pwrake/option.rb +0 -400
- data/lib/pwrake/rake_modify.rb +0 -14
- data/lib/pwrake/shell.rb +0 -186
- data/lib/pwrake/task_algorithm.rb +0 -475
- data/lib/pwrake/task_queue.rb +0 -633
- data/lib/pwrake/timer.rb +0 -22
@@ -0,0 +1,22 @@
|
|
1
|
+
require "logger"
|
2
|
+
require 'csv'
|
3
|
+
|
4
|
+
require "pwrake/logger"
|
5
|
+
|
6
|
+
require "pwrake/iomux/channel"
|
7
|
+
require "pwrake/iomux/handler"
|
8
|
+
require "pwrake/iomux/handler_set"
|
9
|
+
require "pwrake/iomux/runner"
|
10
|
+
|
11
|
+
require "pwrake/branch/branch_application"
|
12
|
+
require "pwrake/branch/branch"
|
13
|
+
require "pwrake/branch/fiber_queue"
|
14
|
+
require "pwrake/branch/file_utils"
|
15
|
+
|
16
|
+
require 'pwrake/branch/shell_profiler'
|
17
|
+
require "pwrake/branch/shell"
|
18
|
+
require "pwrake/branch/worker_communicator"
|
19
|
+
|
20
|
+
require "pwrake/option/option"
|
21
|
+
require "pwrake/option/option_filesystem"
|
22
|
+
require "pwrake/option/host_map"
|
@@ -0,0 +1,213 @@
|
|
1
|
+
module Pwrake
|
2
|
+
|
3
|
+
class Branch
|
4
|
+
|
5
|
+
def initialize(opts,r,w)
|
6
|
+
#Thread.abort_on_exception = true
|
7
|
+
@option = opts
|
8
|
+
@task_q = {} # worker_id => FiberQueue.new
|
9
|
+
@shells = []
|
10
|
+
@ior = r
|
11
|
+
@iow = w
|
12
|
+
@runner = Runner.new(@option['HEARTBEAT'])
|
13
|
+
@master_hdl = Handler.new(@runner,@ior,@iow)
|
14
|
+
@master_chan = Channel.new(@master_hdl)
|
15
|
+
@wk_comm = {}
|
16
|
+
@wk_hdl_set = HandlerSet.new
|
17
|
+
@shell_start_interval = @option['SHELL_START_INTERVAL']
|
18
|
+
end
|
19
|
+
|
20
|
+
# Rakefile is loaded after 'init' before 'run'
|
21
|
+
|
22
|
+
def run
|
23
|
+
setup_worker
|
24
|
+
setup_shell
|
25
|
+
setup_fiber
|
26
|
+
setup_master_channel
|
27
|
+
@runner.run
|
28
|
+
Log.debug "Brandh#run end"
|
29
|
+
end
|
30
|
+
|
31
|
+
attr_reader :logger
|
32
|
+
|
33
|
+
def init_logger
|
34
|
+
if dir = @option['LOG_DIR']
|
35
|
+
logfile = File.join(dir,@option['LOG_FILE'])
|
36
|
+
@logger = Logger.new(logfile)
|
37
|
+
else
|
38
|
+
if @option['DEBUG']
|
39
|
+
@logger = Logger.new($stderr)
|
40
|
+
else
|
41
|
+
@logger = Logger.new(File::NULL)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
if @option['DEBUG']
|
46
|
+
@logger.level = Logger::DEBUG
|
47
|
+
elsif @option['TRACE']
|
48
|
+
@logger.level = Logger::INFO
|
49
|
+
else
|
50
|
+
@logger.level = Logger::WARN
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def setup_worker
|
55
|
+
s = @ior.gets
|
56
|
+
if s.chomp != "host_list_begin"
|
57
|
+
raise "Branch#setup_worker: recv=#{s.chomp} expected=host_list_begin"
|
58
|
+
end
|
59
|
+
|
60
|
+
if dir = @option['LOG_DIR']
|
61
|
+
fn = File.join(dir,@option["COMMAND_CSV_FILE"])
|
62
|
+
Shell.profiler.open(fn,@option['GNU_TIME'],@option['PLOT_PARALLELISM'])
|
63
|
+
end
|
64
|
+
|
65
|
+
worker_code = WorkerCommunicator.read_worker_progs(@option)
|
66
|
+
|
67
|
+
while s = @ior.gets
|
68
|
+
s.chomp!
|
69
|
+
break if s == "host_list_end"
|
70
|
+
if /^host:(\d+) (\S+) ([+-]?\d+)?$/ =~ s
|
71
|
+
id, host, ncore = $1,$2,$3
|
72
|
+
ncore &&= ncore.to_i
|
73
|
+
comm = WorkerCommunicator.new(id,host,ncore,@runner,@option)
|
74
|
+
comm.setup_connection(worker_code)
|
75
|
+
@wk_comm[id] = comm
|
76
|
+
@wk_hdl_set << comm.handler
|
77
|
+
@task_q[id] = FiberQueue.new
|
78
|
+
else
|
79
|
+
raise "Branch#setup_worker: recv=#{s.chomp} expected=host:id hostname ncore"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
errors = []
|
84
|
+
|
85
|
+
@wk_comm.values.each do |comm|
|
86
|
+
Fiber.new do
|
87
|
+
while true
|
88
|
+
if s = comm.channel.get_line
|
89
|
+
break unless comm.ncore_proc(s)
|
90
|
+
else
|
91
|
+
errors << comm
|
92
|
+
break
|
93
|
+
end
|
94
|
+
end
|
95
|
+
Log.debug "Branch#setup_worker: fiber end of ncore_proc"
|
96
|
+
end.resume
|
97
|
+
end
|
98
|
+
|
99
|
+
@runner.run
|
100
|
+
|
101
|
+
if !errors.empty?
|
102
|
+
errors.each{|comm| @wk_hdl_set.delete(comm.handler)}
|
103
|
+
hosts = errors.map{|comm| comm.host}.join(",")
|
104
|
+
raise RuntimeError,"Failed to connect to workers: #{hosts}"
|
105
|
+
end
|
106
|
+
|
107
|
+
# ncore
|
108
|
+
@wk_comm.each_value do |comm|
|
109
|
+
# set WorkerChannel#ncore at Master
|
110
|
+
@master_hdl.put_line "ncore:#{comm.id}:#{comm.ncore}"
|
111
|
+
end
|
112
|
+
@master_hdl.put_line "ncore:done"
|
113
|
+
end
|
114
|
+
|
115
|
+
def setup_shell
|
116
|
+
@shells = []
|
117
|
+
errors = []
|
118
|
+
shell_id = 0
|
119
|
+
@wk_comm.each_value do |comm|
|
120
|
+
comm.ncore.times do
|
121
|
+
chan = Channel.new(comm.handler,shell_id)
|
122
|
+
shell_id += 1
|
123
|
+
shell = Shell.new(chan,@task_q[comm.id],@option.worker_option)
|
124
|
+
@shells << shell
|
125
|
+
# wait for remote shell open
|
126
|
+
Fiber.new do
|
127
|
+
if !shell.open
|
128
|
+
errors << [comm.host,s]
|
129
|
+
end
|
130
|
+
Log.debug "Branch#setup_shells: end of fiber to open shell"
|
131
|
+
end.resume
|
132
|
+
sleep @shell_start_interval
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
@runner.run
|
137
|
+
|
138
|
+
if !errors.empty?
|
139
|
+
raise RuntimeError,"Failed to start workers: #{errors.inspect}"
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def setup_fiber
|
144
|
+
# start fibers
|
145
|
+
@shells.each do |shell|
|
146
|
+
shell.create_fiber(@master_hdl).resume
|
147
|
+
end
|
148
|
+
Log.debug "all fiber started"
|
149
|
+
|
150
|
+
@wk_comm.each_value do |comm|
|
151
|
+
#comm.start_default_fiber
|
152
|
+
Fiber.new do
|
153
|
+
while s = comm.channel.get_line
|
154
|
+
break unless comm.common_line(s)
|
155
|
+
end
|
156
|
+
Log.debug "Branch#setup_fiber: end of fiber for default channel"
|
157
|
+
end.resume
|
158
|
+
end
|
159
|
+
|
160
|
+
# setup end
|
161
|
+
@wk_comm.values.each do |comm|
|
162
|
+
comm.handler.put_line "setup_end"
|
163
|
+
end
|
164
|
+
|
165
|
+
@master_hdl.put_line "branch_setup:done"
|
166
|
+
Log.debug "Branch#setup_fiber: setup end"
|
167
|
+
end
|
168
|
+
|
169
|
+
def setup_master_channel
|
170
|
+
Fiber.new do
|
171
|
+
while s = @master_chan.get_line
|
172
|
+
# receive command from main pwrake
|
173
|
+
Log.debug "Branch:recv #{s.inspect} from master"
|
174
|
+
case s
|
175
|
+
#
|
176
|
+
when /^(\d+):(.+)$/o
|
177
|
+
id, tname = $1,$2
|
178
|
+
@task_q[id].enq(tname)
|
179
|
+
#
|
180
|
+
when /^exit$/
|
181
|
+
@task_q.each_value{|q| q.finish}
|
182
|
+
@shells.each{|shell| shell.close}
|
183
|
+
@runner.finish
|
184
|
+
break
|
185
|
+
#
|
186
|
+
when /^kill:(.*)$/o
|
187
|
+
sig = $1
|
188
|
+
kill(sig)
|
189
|
+
else
|
190
|
+
Log.debug "Branch: invalid line from master: #{s}"
|
191
|
+
end
|
192
|
+
end
|
193
|
+
Log.debug "Branch#setup_master_channel: end of fiber for master channel"
|
194
|
+
end.resume
|
195
|
+
end
|
196
|
+
|
197
|
+
def kill(sig="INT")
|
198
|
+
Log.warn "Branch#kill #{sig}"
|
199
|
+
@wk_hdl_set.kill(sig)
|
200
|
+
end
|
201
|
+
|
202
|
+
def finish
|
203
|
+
return if @finished
|
204
|
+
@finished = true
|
205
|
+
Log.debug "Branch#finish: begin"
|
206
|
+
@wk_hdl_set.exit
|
207
|
+
Log.debug "Branch#finish: worker exited"
|
208
|
+
@master_hdl.put_line "exited"
|
209
|
+
Log.debug "Branch#finish: sent 'exited' to master"
|
210
|
+
end
|
211
|
+
|
212
|
+
end # Pwrake::Branch
|
213
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Pwrake
|
2
|
+
|
3
|
+
# The TaskManager module is a mixin for managing tasks.
|
4
|
+
module BranchApplication
|
5
|
+
|
6
|
+
def logger
|
7
|
+
@branch.logger
|
8
|
+
end
|
9
|
+
|
10
|
+
def run_branch(r,w)
|
11
|
+
#standard_exception_handling do
|
12
|
+
init("pwrake_branch")
|
13
|
+
opts = Marshal.load(r)
|
14
|
+
if !opts.kind_of?(Hash)
|
15
|
+
raise "opts is not a Hash: opts=#{opts.inspect}"
|
16
|
+
end
|
17
|
+
@branch = Branch.new(opts,r,w)
|
18
|
+
@branch.init_logger
|
19
|
+
opts.feedback_options
|
20
|
+
load_rakefile
|
21
|
+
w.puts "pwrake_branch start"
|
22
|
+
w.flush
|
23
|
+
begin
|
24
|
+
@branch.run
|
25
|
+
rescue => e
|
26
|
+
Log.fatal e
|
27
|
+
$stderr.puts e
|
28
|
+
$stderr.puts e.backtrace
|
29
|
+
@branch.kill
|
30
|
+
ensure
|
31
|
+
@branch.finish
|
32
|
+
end
|
33
|
+
#end
|
34
|
+
end
|
35
|
+
|
36
|
+
def run_branch_in_thread(r,w,opts)
|
37
|
+
#standard_exception_handling do
|
38
|
+
@branch = Branch.new(opts,r,w)
|
39
|
+
begin
|
40
|
+
@branch.run
|
41
|
+
rescue => e
|
42
|
+
Log.fatal e
|
43
|
+
$stderr.puts e
|
44
|
+
$stderr.puts e.backtrace
|
45
|
+
@branch.kill
|
46
|
+
ensure
|
47
|
+
@branch.finish
|
48
|
+
end
|
49
|
+
#end
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'fiber'
|
2
|
+
|
3
|
+
module Pwrake
|
4
|
+
|
5
|
+
class FiberQueue
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@q = []
|
9
|
+
@waiter = []
|
10
|
+
@finished = false
|
11
|
+
end
|
12
|
+
|
13
|
+
def enq(x)
|
14
|
+
@q.push(x)
|
15
|
+
f = @waiter.shift
|
16
|
+
f.resume if f
|
17
|
+
end
|
18
|
+
|
19
|
+
def deq
|
20
|
+
while @q.empty?
|
21
|
+
return nil if @finished
|
22
|
+
@waiter.push(Fiber.current)
|
23
|
+
Fiber.yield
|
24
|
+
end
|
25
|
+
return @q.shift
|
26
|
+
end
|
27
|
+
|
28
|
+
def finish
|
29
|
+
@finished = true
|
30
|
+
while f = @waiter.shift
|
31
|
+
f.resume
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
module Pwrake
|
2
|
+
|
3
|
+
module FileUtils
|
4
|
+
module_function
|
5
|
+
|
6
|
+
def sh(*cmd, &block)
|
7
|
+
options = (Hash === cmd.last) ? cmd.pop : {}
|
8
|
+
unless block_given?
|
9
|
+
show_command = cmd.join(" ")
|
10
|
+
show_command = show_command[0,42] + "..."
|
11
|
+
block = lambda { |ok, status|
|
12
|
+
ok or fail "Command failed with status (#{status.exitstatus}): [#{show_command}]"
|
13
|
+
}
|
14
|
+
end
|
15
|
+
if RakeFileUtils.verbose_flag == :default
|
16
|
+
options[:verbose] = true
|
17
|
+
else
|
18
|
+
options[:verbose] ||= RakeFileUtils.verbose_flag
|
19
|
+
end
|
20
|
+
options[:noop] ||= RakeFileUtils.nowrite_flag
|
21
|
+
Rake.rake_check_options options, :noop, :verbose
|
22
|
+
Rake.rake_output_message cmd.join(" ") if options[:verbose]
|
23
|
+
#Pwrake::Log.stderr_puts cmd.join(" ") if options[:verbose]
|
24
|
+
unless options[:noop]
|
25
|
+
res,status = Pwrake::FileUtils.pwrake_system(*cmd)
|
26
|
+
block.call(res, status)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def bq(*cmd, &block)
|
31
|
+
options = (Hash === cmd.last) ? cmd.pop : {}
|
32
|
+
unless block_given?
|
33
|
+
show_command = cmd.join(" ")
|
34
|
+
show_command = show_command[0,42] + "..."
|
35
|
+
block = lambda { |ok, status|
|
36
|
+
ok or fail "Command failed with status (#{status.exitstatus}): [#{show_command}]"
|
37
|
+
}
|
38
|
+
end
|
39
|
+
if RakeFileUtils.verbose_flag == :default
|
40
|
+
options[:verbose] = true
|
41
|
+
else
|
42
|
+
options[:verbose] ||= RakeFileUtils.verbose_flag
|
43
|
+
end
|
44
|
+
options[:noop] ||= RakeFileUtils.nowrite_flag
|
45
|
+
Rake.rake_check_options options, :noop, :verbose
|
46
|
+
Rake.rake_output_message cmd.join(" ") if options[:verbose]
|
47
|
+
#Pwrake::Log.stderr_puts cmd.join(" ") if options[:verbose]
|
48
|
+
unless options[:noop]
|
49
|
+
res,status = Pwrake::FileUtils.pwrake_backquote(*cmd)
|
50
|
+
block.call(res, status)
|
51
|
+
end
|
52
|
+
res
|
53
|
+
end
|
54
|
+
|
55
|
+
def pwrake_system(*cmd)
|
56
|
+
cmd_log = cmd.join(" ").inspect
|
57
|
+
#tm = Pwrake::Timer.new("sh",cmd_log)
|
58
|
+
|
59
|
+
conn = Pwrake::Shell.current
|
60
|
+
if conn.kind_of?(Pwrake::Shell)
|
61
|
+
res = conn.system(*cmd)
|
62
|
+
status = Rake::PseudoStatus.new(conn.status)
|
63
|
+
else
|
64
|
+
res = system(*cmd)
|
65
|
+
status = $?
|
66
|
+
status = Rake::PseudoStatus.new(1) if !res && status.nil?
|
67
|
+
end
|
68
|
+
|
69
|
+
#tm.finish("status=%s cmd=%s"%[status.exitstatus,cmd_log])
|
70
|
+
[res,status]
|
71
|
+
end
|
72
|
+
|
73
|
+
# Pwrake version of backquote command
|
74
|
+
def pwrake_backquote(cmd)
|
75
|
+
cmd_log = cmd.inspect
|
76
|
+
#tm = Pwrake::Timer.new("bq",cmd_log)
|
77
|
+
|
78
|
+
conn = Pwrake::Shell.current
|
79
|
+
if conn.kind_of?(Pwrake::Shell)
|
80
|
+
res = conn.backquote(*cmd)
|
81
|
+
status = Rake::PseudoStatus.new(conn.status)
|
82
|
+
else
|
83
|
+
res = `#{cmd}`
|
84
|
+
status = $?
|
85
|
+
status = Rake::PseudoStatus.new(1) if status.nil?
|
86
|
+
end
|
87
|
+
|
88
|
+
#tm.finish("status=%s cmd=%s"%[status.exitstatus,cmd_log])
|
89
|
+
[res,status]
|
90
|
+
end
|
91
|
+
|
92
|
+
end # module Pwrake::FileUtils
|
93
|
+
end
|
94
|
+
|
95
|
+
module Rake
|
96
|
+
module DSL
|
97
|
+
include Pwrake::FileUtils
|
98
|
+
private(*Pwrake::FileUtils.instance_methods(false))
|
99
|
+
end
|
100
|
+
end
|
101
|
+
self.extend Rake::DSL
|
@@ -0,0 +1,231 @@
|
|
1
|
+
module Pwrake
|
2
|
+
|
3
|
+
class DummyMutex
|
4
|
+
def synchronize
|
5
|
+
yield
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class Shell
|
10
|
+
|
11
|
+
OPEN_LIST={}
|
12
|
+
BY_FIBER={}
|
13
|
+
@@profiler = ShellProfiler.new
|
14
|
+
|
15
|
+
def self.profiler
|
16
|
+
@@profiler
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.current
|
20
|
+
BY_FIBER[Fiber.current]
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize(chan,task_q,opt={})
|
24
|
+
@chan = chan
|
25
|
+
@host = chan.handler.host
|
26
|
+
@task_q = task_q
|
27
|
+
@lock = DummyMutex.new
|
28
|
+
@id = chan.id
|
29
|
+
#
|
30
|
+
@option = opt
|
31
|
+
@work_dir = @option[:work_dir] || Dir.pwd
|
32
|
+
end
|
33
|
+
|
34
|
+
attr_reader :id, :host, :status, :profile
|
35
|
+
|
36
|
+
def open
|
37
|
+
if @opened
|
38
|
+
Log.warn "already opened: host=#{@host} id=#{@id}"
|
39
|
+
end
|
40
|
+
_puts("open")
|
41
|
+
if (s = _gets) == "open"
|
42
|
+
OPEN_LIST[__id__] = self
|
43
|
+
@opened = true
|
44
|
+
true
|
45
|
+
else
|
46
|
+
Log.error("Shell#open failed: recieve #{s.inspect}")
|
47
|
+
false
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def close
|
52
|
+
if !@opened
|
53
|
+
Log.warn "already closed: host=#{@host} id=#{@id}"
|
54
|
+
end
|
55
|
+
_puts("exit")
|
56
|
+
if (s = _gets) == "exit"
|
57
|
+
OPEN_LIST.delete(__id__)
|
58
|
+
@opened = false
|
59
|
+
true
|
60
|
+
else
|
61
|
+
Log.warn("Shell#close failed: recieve #{s.inspect}")
|
62
|
+
false
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def set_current_task(task_id,task_name)
|
67
|
+
@task_id = task_id
|
68
|
+
@task_name = task_name
|
69
|
+
end
|
70
|
+
|
71
|
+
def backquote(*command)
|
72
|
+
command = command.join(' ')
|
73
|
+
@lock.synchronize do
|
74
|
+
a = []
|
75
|
+
_execute(command){|x| a << x}
|
76
|
+
a.join("\n")
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def system(*command)
|
81
|
+
command = command.join(' ')
|
82
|
+
@lock.synchronize do
|
83
|
+
_execute(command){|x| print x+"\n"}
|
84
|
+
end
|
85
|
+
@status == 0
|
86
|
+
end
|
87
|
+
|
88
|
+
def cd(dir="")
|
89
|
+
_system("cd #{dir}") or die
|
90
|
+
end
|
91
|
+
|
92
|
+
def die
|
93
|
+
raise "Failed at #{@host}, id=#{@id}, cmd='#{@cmd}'"
|
94
|
+
end
|
95
|
+
|
96
|
+
at_exit {
|
97
|
+
Shell.profiler.close
|
98
|
+
}
|
99
|
+
|
100
|
+
private
|
101
|
+
|
102
|
+
def _puts(s)
|
103
|
+
#Log.debug "Shell#_puts(host=#{@host},id=#{@id}): #{s.inspect}"
|
104
|
+
@chan.put_line(s)
|
105
|
+
end
|
106
|
+
|
107
|
+
def _gets
|
108
|
+
s = @chan.get_line
|
109
|
+
#Log.debug "Shell#_gets(host=#{@host},id=#{@id}): #{s.inspect}"
|
110
|
+
if s.nil?
|
111
|
+
begin
|
112
|
+
raise
|
113
|
+
rescue => e
|
114
|
+
Log.debug e
|
115
|
+
end
|
116
|
+
end
|
117
|
+
s
|
118
|
+
end
|
119
|
+
|
120
|
+
def _system(cmd)
|
121
|
+
@cmd = cmd
|
122
|
+
#raise "@chan is closed" if @chan.closed?
|
123
|
+
@lock.synchronize do
|
124
|
+
_puts(cmd)
|
125
|
+
status = io_read_loop{}
|
126
|
+
Integer(status||1) == 0
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def _backquote(cmd)
|
131
|
+
@cmd = cmd
|
132
|
+
#raise "@chan is closed" if @chan.closed?
|
133
|
+
a = []
|
134
|
+
@lock.synchronize do
|
135
|
+
_puts(cmd)
|
136
|
+
status = io_read_loop{|x| a << x}
|
137
|
+
end
|
138
|
+
a.join("\n")
|
139
|
+
end
|
140
|
+
|
141
|
+
def _execute(cmd,quote=nil,&block)
|
142
|
+
@cmd = cmd
|
143
|
+
if !@opened
|
144
|
+
raise "closed"
|
145
|
+
end
|
146
|
+
status = nil
|
147
|
+
start_time = Time.now
|
148
|
+
begin
|
149
|
+
_puts(cmd)
|
150
|
+
@status = io_read_loop(&block)
|
151
|
+
ensure
|
152
|
+
end_time = Time.now
|
153
|
+
@status = @@profiler.profile(@task_id, @task_name, cmd,
|
154
|
+
start_time, end_time, host, @status)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def io_read_loop
|
159
|
+
while s = _gets
|
160
|
+
case s
|
161
|
+
when /^(\w+):(.*)$/
|
162
|
+
x = [$1,$2]
|
163
|
+
case x[0]
|
164
|
+
when "o"
|
165
|
+
yield x[1]
|
166
|
+
next
|
167
|
+
when "e"
|
168
|
+
$stderr.print x[1]+"\n"
|
169
|
+
next
|
170
|
+
when "z"
|
171
|
+
# see Executor#status_to_str
|
172
|
+
status = x[1]
|
173
|
+
case status
|
174
|
+
when /^\d+$/
|
175
|
+
status = status.to_i
|
176
|
+
end
|
177
|
+
return status
|
178
|
+
when "err"
|
179
|
+
# see Executor#status_to_str
|
180
|
+
status = x[1]
|
181
|
+
case status
|
182
|
+
when /^\d+$/
|
183
|
+
status = status.to_i
|
184
|
+
end
|
185
|
+
return status
|
186
|
+
end
|
187
|
+
end
|
188
|
+
msg = "Shell#io_read_loop: Invalid result: #{s.inspect}"
|
189
|
+
$stderr.puts(msg)
|
190
|
+
Log.error(msg)
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
public
|
195
|
+
|
196
|
+
def create_fiber(hdl)
|
197
|
+
if !@opened
|
198
|
+
Log.warn "not opened: host=#{@host} id=#{@id}"
|
199
|
+
end
|
200
|
+
Fiber.new do
|
201
|
+
BY_FIBER[Fiber.current] = self
|
202
|
+
Log.debug "shell start id=#{@id} host=#{@host}"
|
203
|
+
begin
|
204
|
+
while task_str = @task_q.deq
|
205
|
+
#Log.debug "task_str=#{task_str}"
|
206
|
+
if /^(\d+):(.*)$/ =~ task_str
|
207
|
+
task_id, task_name = $1.to_i, $2
|
208
|
+
else
|
209
|
+
raise RuntimeError, "invalid task_str: #{task_str}"
|
210
|
+
end
|
211
|
+
@task_id = task_id
|
212
|
+
@task_name = task_name
|
213
|
+
task = Rake.application[task_name]
|
214
|
+
begin
|
215
|
+
task.execute(task.arguments) if task.needed?
|
216
|
+
result = "taskend:#{@id}:#{task.name}"
|
217
|
+
rescue Exception=>e
|
218
|
+
Rake.application.display_error_message(e)
|
219
|
+
Log.error e
|
220
|
+
result = "taskfail:#{@id}:#{task.name}"
|
221
|
+
end
|
222
|
+
hdl.put_line result
|
223
|
+
end
|
224
|
+
ensure
|
225
|
+
Log.debug "shell id=#{@id} fiber end"
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
end
|
231
|
+
end
|