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
@@ -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