pwrake 0.9.9.2 → 2.0.0
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.
- 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
|