pwrake 0.9.3
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.
- data/.gitignore +30 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +57 -0
- data/Rakefile +1 -0
- data/bin/pwrake +36 -0
- data/lib/pwrake/application.rb +187 -0
- data/lib/pwrake/counter.rb +54 -0
- data/lib/pwrake/file_utils.rb +70 -0
- data/lib/pwrake/gfarm_feature.rb +229 -0
- data/lib/pwrake/graphviz.rb +113 -0
- data/lib/pwrake/locality_aware_queue.rb +254 -0
- data/lib/pwrake/logger.rb +153 -0
- data/lib/pwrake/master.rb +109 -0
- data/lib/pwrake/option.rb +367 -0
- data/lib/pwrake/profiler.rb +88 -0
- data/lib/pwrake/rake_modify.rb +14 -0
- data/lib/pwrake/shell.rb +151 -0
- data/lib/pwrake/task_algorithm.rb +171 -0
- data/lib/pwrake/task_queue.rb +167 -0
- data/lib/pwrake/timer.rb +22 -0
- data/lib/pwrake/version.rb +3 -0
- data/lib/pwrake.rb +18 -0
- data/pwrake.gemspec +19 -0
- data/setup.rb +1585 -0
- data/spec/001/Rakefile +5 -0
- data/spec/002/Rakefile +19 -0
- data/spec/003/Rakefile +9 -0
- data/spec/004/Rakefile +7 -0
- data/spec/005/Rakefile +11 -0
- data/spec/006/Rakefile +3 -0
- data/spec/006/pwrake_conf.yaml +3 -0
- data/spec/007/Rakefile +22 -0
- data/spec/008/Rakefile +3 -0
- data/spec/008/pwrake_conf.yaml +3 -0
- data/spec/009/Rakefile +18 -0
- data/spec/009/pwrake_conf.yaml +2 -0
- data/spec/helper.rb +82 -0
- data/spec/hosts +3 -0
- data/spec/pwrake_spec.rb +83 -0
- metadata +119 -0
@@ -0,0 +1,113 @@
|
|
1
|
+
module Pwrake
|
2
|
+
|
3
|
+
class Graphviz
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@nodes = []
|
7
|
+
@edges = []
|
8
|
+
# @node_id = {}
|
9
|
+
@filenode_id = {}
|
10
|
+
@tasknode_id = {}
|
11
|
+
@node_name = {}
|
12
|
+
@count = 0
|
13
|
+
@traced = {}
|
14
|
+
end
|
15
|
+
|
16
|
+
attr_reader :filenode_id, :tasknode_id, :node_name
|
17
|
+
|
18
|
+
def trace( name = :default, target = nil )
|
19
|
+
traced_cond = @traced[name]
|
20
|
+
|
21
|
+
task = Rake.application[name]
|
22
|
+
|
23
|
+
#if task.kind_of?(Rake::FileTask)
|
24
|
+
if task.kind_of?(Rake::Task)
|
25
|
+
push_filenode( name )
|
26
|
+
if !task.actions.empty? and !traced_cond
|
27
|
+
push_tasknode( name )
|
28
|
+
push_taskedge( name )
|
29
|
+
end
|
30
|
+
push_fileedge( name, target )
|
31
|
+
target = name
|
32
|
+
end
|
33
|
+
@traced[name] = true
|
34
|
+
|
35
|
+
if !traced_cond
|
36
|
+
task.prerequisites.each_with_index do |prereq,i|
|
37
|
+
trace( prereq, target )
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def trim( name )
|
43
|
+
name = name.to_s
|
44
|
+
name = File.basename(name)
|
45
|
+
name.sub(/H\d+/,'').sub(/object\d+/,"")
|
46
|
+
end
|
47
|
+
|
48
|
+
def push_filenode( name )
|
49
|
+
if @filenode_id[name].nil?
|
50
|
+
tag = "T#{@count}"
|
51
|
+
@count += 1
|
52
|
+
@filenode_id[name] = tag
|
53
|
+
@node_name[tag] = name
|
54
|
+
@nodes.push "#{tag} [label=\"#{trim(name)}\", shape=box];"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def push_tasknode( name )
|
59
|
+
if @tasknode_id[name].nil?
|
60
|
+
tag = "T#{@count}"
|
61
|
+
@count += 1
|
62
|
+
@tasknode_id[name] = tag
|
63
|
+
@node_name[tag] = name
|
64
|
+
label = Rake.application[name].comment
|
65
|
+
@nodes.push "#{tag} [label=\"#{label}\", shape=ellipse];"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def push_fileedge( name, target )
|
70
|
+
if target
|
71
|
+
if n2 = @tasknode_id[target]
|
72
|
+
n1 = @filenode_id[name]
|
73
|
+
elsif n1 = @tasknode_id[name]
|
74
|
+
n2 = @filenode_id[target]
|
75
|
+
else
|
76
|
+
n1 = @filenode_id[name]
|
77
|
+
n2 = @filenode_id[target]
|
78
|
+
end
|
79
|
+
@edges.push "#{n1} -> #{n2};"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def push_taskedge( name )
|
84
|
+
if n1 = @tasknode_id[name]
|
85
|
+
n2 = @filenode_id[name]
|
86
|
+
@edges.push "#{n1} -> #{n2};"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def write(file)
|
91
|
+
open(file, "w") do |w|
|
92
|
+
#w.puts "digraph sample {\ngraph [size=\"12,100\",ranksep=1.5,nodesep=0.2];"
|
93
|
+
w.puts "digraph sample {"
|
94
|
+
w.puts "graph [size=\"70,70\", rankdir=LR];"
|
95
|
+
@nodes.each do |x|
|
96
|
+
w.puts x
|
97
|
+
end
|
98
|
+
@edges.each do |x|
|
99
|
+
w.puts x
|
100
|
+
end
|
101
|
+
w.puts "}"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
task "graphviz", :file do |t,a|
|
108
|
+
file = a[:file] || 'pwrake.dot'
|
109
|
+
g = Pwrake::Graphviz.new
|
110
|
+
g.trace
|
111
|
+
g.write(file)
|
112
|
+
$stderr.puts "Wrote task graph to `#{file}'"
|
113
|
+
end
|
@@ -0,0 +1,254 @@
|
|
1
|
+
module Pwrake
|
2
|
+
|
3
|
+
module TaskAlgorithm
|
4
|
+
def assigned
|
5
|
+
@assigned ||= []
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
|
10
|
+
class LocalityAwareQueue < TaskQueue
|
11
|
+
|
12
|
+
class Throughput
|
13
|
+
|
14
|
+
def initialize(list=nil)
|
15
|
+
@interdomain_list = {}
|
16
|
+
@interhost_list = {}
|
17
|
+
if list
|
18
|
+
values = []
|
19
|
+
list.each do |x,y,v|
|
20
|
+
hash_x = (@interdomain_list[x] ||= {})
|
21
|
+
hash_x[y] = n = v.to_f
|
22
|
+
values << n
|
23
|
+
end
|
24
|
+
@min_value = values.min
|
25
|
+
else
|
26
|
+
@min_value = 1
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def interdomain(x,y)
|
31
|
+
hash_x = (@interdomain_list[x] ||= {})
|
32
|
+
if v = hash_x[y]
|
33
|
+
return v
|
34
|
+
elsif v = (@interdomain_list[y] || {})[x]
|
35
|
+
hash_x[y] = v
|
36
|
+
else
|
37
|
+
if x == y
|
38
|
+
hash_x[y] = 1
|
39
|
+
else
|
40
|
+
hash_x[y] = 0.1
|
41
|
+
end
|
42
|
+
end
|
43
|
+
hash_x[y]
|
44
|
+
end
|
45
|
+
|
46
|
+
def interhost(x,y)
|
47
|
+
return @min_value if !x
|
48
|
+
hash_x = (@interhost_list[x] ||= {})
|
49
|
+
if v = hash_x[y]
|
50
|
+
return v
|
51
|
+
elsif v = (@interhost_list[y] || {})[x]
|
52
|
+
hash_x[y] = v
|
53
|
+
else
|
54
|
+
x_short, x_domain = parse_hostname(x)
|
55
|
+
y_short, y_domain = parse_hostname(y)
|
56
|
+
v = interdomain(x_domain,y_domain)
|
57
|
+
hash_x[y] = v
|
58
|
+
end
|
59
|
+
hash_x[y]
|
60
|
+
end
|
61
|
+
|
62
|
+
def parse_hostname(host)
|
63
|
+
/^([^.]*)\.?(.*)$/ =~ host
|
64
|
+
[$1,$2]
|
65
|
+
end
|
66
|
+
|
67
|
+
end # class Throughput
|
68
|
+
|
69
|
+
|
70
|
+
def initialize(hosts,opt={})
|
71
|
+
super(opt)
|
72
|
+
@hosts = hosts
|
73
|
+
@throughput = Throughput.new
|
74
|
+
@size = 0
|
75
|
+
@q = nil
|
76
|
+
@q1 = []
|
77
|
+
@q2 = {}
|
78
|
+
@hosts.each{|h| @q2[h]=[]}
|
79
|
+
@q2[nil] = []
|
80
|
+
@enable_steal = !opt['disable_steal']
|
81
|
+
@time_prev = Time.now
|
82
|
+
|
83
|
+
@thread = Thread.new{thread_loop}
|
84
|
+
end
|
85
|
+
|
86
|
+
attr_reader :size
|
87
|
+
|
88
|
+
|
89
|
+
def thread_loop
|
90
|
+
while !@finished
|
91
|
+
bulk_mvq
|
92
|
+
sleep # time_out
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
def time_out
|
98
|
+
if @size == 0
|
99
|
+
if @q1.size == 1
|
100
|
+
0.25
|
101
|
+
else
|
102
|
+
0.5
|
103
|
+
end
|
104
|
+
else
|
105
|
+
if @q1.size > @size
|
106
|
+
0.5
|
107
|
+
elsif @q1.size > @size/2
|
108
|
+
1.0
|
109
|
+
else
|
110
|
+
3.0
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
|
116
|
+
def bulk_mvq
|
117
|
+
a = nil
|
118
|
+
@mutex.synchronize do
|
119
|
+
return if @q1.empty?
|
120
|
+
|
121
|
+
time_now = Time.now
|
122
|
+
interval = time_now-@time_prev
|
123
|
+
return if time_now-@time_prev < time_out
|
124
|
+
|
125
|
+
log_bulk_mvq
|
126
|
+
@time_prev = time_now
|
127
|
+
|
128
|
+
a = @q1
|
129
|
+
@q1 = []
|
130
|
+
end
|
131
|
+
|
132
|
+
where(a)
|
133
|
+
|
134
|
+
@mutex.synchronize do
|
135
|
+
while t = a.shift
|
136
|
+
mvq(t)
|
137
|
+
end
|
138
|
+
@cv.broadcast
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def log_bulk_mvq
|
143
|
+
msg = @q1[0..2].map{|t| t.name}.inspect
|
144
|
+
msg.sub!(/]$/,",...") if @q1.size > 3
|
145
|
+
Log.info "-- bulk_mvq interval=%.6fs @size=#{@size} @q1.size=#{@q1.size} @q1=#{msg}"%(Time.now-@time_prev)
|
146
|
+
end
|
147
|
+
|
148
|
+
|
149
|
+
def where(task_list)
|
150
|
+
# implemented in child class
|
151
|
+
end
|
152
|
+
|
153
|
+
|
154
|
+
def mvq(t)
|
155
|
+
stored = false
|
156
|
+
if t.respond_to? :location
|
157
|
+
t.location.each do |h|
|
158
|
+
if q = @q2[h]
|
159
|
+
t.assigned.push(h)
|
160
|
+
q.push(t)
|
161
|
+
stored = true
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
if !stored
|
166
|
+
@q2[@hosts[rand(@hosts.size)]].push(t)
|
167
|
+
# @q2[nil].push(t)
|
168
|
+
end
|
169
|
+
@size += 1
|
170
|
+
end
|
171
|
+
|
172
|
+
|
173
|
+
def enq_impl(item,hint=nil)
|
174
|
+
#Log.debug "--- #{self.class}#enq_impl #{item.inspect}"
|
175
|
+
@q1.push(item)
|
176
|
+
end
|
177
|
+
|
178
|
+
def enq_finish
|
179
|
+
@thread.run if @thread.alive?
|
180
|
+
end
|
181
|
+
|
182
|
+
def deq_impl(host,n)
|
183
|
+
@thread.run if @thread.alive?
|
184
|
+
|
185
|
+
if t = deq_locate(host)
|
186
|
+
Log.info "-- deq_locate n=#{n} task=#{t.name} host=#{host}"
|
187
|
+
return t
|
188
|
+
end
|
189
|
+
|
190
|
+
if @enable_steal && n > 1
|
191
|
+
if t = deq_steal(host)
|
192
|
+
Log.info "-- deq_steal n=#{n} task=#{t.name} host=#{host}"
|
193
|
+
return t
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
m = 0.05*(2**([n,5].min))
|
198
|
+
@cv.wait(@mutex,m)
|
199
|
+
nil
|
200
|
+
end
|
201
|
+
|
202
|
+
|
203
|
+
def deq_locate(host)
|
204
|
+
q = @q2[host]
|
205
|
+
if q && !q.empty?
|
206
|
+
t = q.shift
|
207
|
+
t.assigned.each{|x| @q2[x].delete_if{|x| t.equal? x}}
|
208
|
+
@size -= 1
|
209
|
+
return t
|
210
|
+
else
|
211
|
+
nil
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
def deq_steal(host)
|
216
|
+
# select a task based on many and close
|
217
|
+
max_host = nil
|
218
|
+
max_num = 0
|
219
|
+
@q2.each do |h,a|
|
220
|
+
if !a.empty?
|
221
|
+
d = @throughput.interhost(host,h) * a.size
|
222
|
+
if d > max_num
|
223
|
+
max_host = h
|
224
|
+
max_num = d
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
if max_host
|
229
|
+
deq_locate(max_host)
|
230
|
+
else
|
231
|
+
deq_locate(nil)
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
def size
|
236
|
+
@q1.size + @size
|
237
|
+
end
|
238
|
+
|
239
|
+
def clear
|
240
|
+
@q1.clear
|
241
|
+
@hosts.each{|h| @q2[h].clear}
|
242
|
+
end
|
243
|
+
|
244
|
+
def empty?
|
245
|
+
@q1.empty? && @hosts.all?{|h| @q2[h].empty?}
|
246
|
+
end
|
247
|
+
|
248
|
+
def finish
|
249
|
+
super
|
250
|
+
@thread.run if @thread.alive?
|
251
|
+
end
|
252
|
+
|
253
|
+
end
|
254
|
+
end
|
@@ -0,0 +1,153 @@
|
|
1
|
+
module Pwrake
|
2
|
+
|
3
|
+
LOCK = Mutex.new
|
4
|
+
|
5
|
+
class Logger
|
6
|
+
|
7
|
+
attr_accessor :level
|
8
|
+
|
9
|
+
module Severity
|
10
|
+
# Low-level information, mostly for developers
|
11
|
+
DEBUG = 0
|
12
|
+
INFO = 1
|
13
|
+
WARN = 2
|
14
|
+
ERROR = 3
|
15
|
+
FATAL = 4
|
16
|
+
UNKNOWN = 5
|
17
|
+
end
|
18
|
+
include Severity
|
19
|
+
|
20
|
+
def initialize
|
21
|
+
@level = WARN
|
22
|
+
@out = nil
|
23
|
+
@filename = nil
|
24
|
+
@lock = Mutex.new
|
25
|
+
end
|
26
|
+
|
27
|
+
def open(file)
|
28
|
+
close if @out
|
29
|
+
case file
|
30
|
+
when IO
|
31
|
+
@out = file
|
32
|
+
@filename = nil
|
33
|
+
when String
|
34
|
+
@out = File.open(file,"w")
|
35
|
+
@filename = file
|
36
|
+
else
|
37
|
+
raise "file arg must be IO or String"
|
38
|
+
end
|
39
|
+
@start_time = Time.now
|
40
|
+
info "LogStart=" + fmt_time(@start_time)
|
41
|
+
info "logfile=#{@filename}" if @filename
|
42
|
+
end
|
43
|
+
|
44
|
+
def finish(str, start_time)
|
45
|
+
if @out
|
46
|
+
finish_time = Time.now
|
47
|
+
t1 = Log.fmt_time(start_time)
|
48
|
+
t2 = Log.fmt_time(finish_time)
|
49
|
+
elap = finish_time - start_time
|
50
|
+
info "#{str} : start=#{t1} end=#{t2} elap=#{elap}"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def add(severity, message)
|
55
|
+
if !severity || severity >= @level
|
56
|
+
if @out
|
57
|
+
@lock.synchronize do
|
58
|
+
@out.write(message+"\n")
|
59
|
+
end
|
60
|
+
else
|
61
|
+
LOCK.synchronize do
|
62
|
+
$stderr.write(message+"\n")
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
true
|
67
|
+
end
|
68
|
+
alias log add
|
69
|
+
|
70
|
+
def info(msg)
|
71
|
+
add(INFO, msg)
|
72
|
+
end
|
73
|
+
|
74
|
+
def debug(msg)
|
75
|
+
add(DEBUG, msg)
|
76
|
+
end
|
77
|
+
|
78
|
+
def warn(msg)
|
79
|
+
add(WARN, msg)
|
80
|
+
end
|
81
|
+
|
82
|
+
def fmt_time(t)
|
83
|
+
t.strftime("%Y-%m-%dT%H:%M:%S.%%06d") % t.usec
|
84
|
+
end
|
85
|
+
|
86
|
+
def timer(prefix,*args)
|
87
|
+
Timer.new(prefix,*args)
|
88
|
+
end
|
89
|
+
|
90
|
+
def close
|
91
|
+
finish "LogEnd", @start_time
|
92
|
+
@lock.synchronize do
|
93
|
+
@out.close if @filename
|
94
|
+
@out=nil
|
95
|
+
end
|
96
|
+
@filename=nil
|
97
|
+
end
|
98
|
+
|
99
|
+
end # class Logger
|
100
|
+
|
101
|
+
|
102
|
+
LOGGER = Logger.new
|
103
|
+
|
104
|
+
module Log
|
105
|
+
include Logger::Severity
|
106
|
+
|
107
|
+
module_function
|
108
|
+
|
109
|
+
def open(file)
|
110
|
+
LOGGER.open(file)
|
111
|
+
end
|
112
|
+
|
113
|
+
def close
|
114
|
+
LOGGER.close
|
115
|
+
end
|
116
|
+
|
117
|
+
def info(s)
|
118
|
+
LOGGER.info(s)
|
119
|
+
end
|
120
|
+
|
121
|
+
def debug(s)
|
122
|
+
LOGGER.debug(s)
|
123
|
+
end
|
124
|
+
|
125
|
+
def warn(s)
|
126
|
+
LOGGER.warn(s)
|
127
|
+
end
|
128
|
+
|
129
|
+
def level
|
130
|
+
LOGGER.level
|
131
|
+
end
|
132
|
+
|
133
|
+
def level=(x)
|
134
|
+
LOGGER.level = x
|
135
|
+
end
|
136
|
+
|
137
|
+
def fmt_time(t)
|
138
|
+
t.strftime("%Y-%m-%dT%H:%M:%S.%%06d") % t.usec
|
139
|
+
end
|
140
|
+
|
141
|
+
def timer(prefix,*args)
|
142
|
+
Timer.new(prefix,*args)
|
143
|
+
end
|
144
|
+
|
145
|
+
def output_message(message)
|
146
|
+
LOCK.synchronize do
|
147
|
+
$stderr.write(message+"\n")
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
end
|
152
|
+
|
153
|
+
end # module Pwrake
|
@@ -0,0 +1,109 @@
|
|
1
|
+
module Pwrake
|
2
|
+
|
3
|
+
def current_shell
|
4
|
+
Thread.current[:shell]
|
5
|
+
end
|
6
|
+
|
7
|
+
def current_shell=(a)
|
8
|
+
Thread.current[:shell] = a
|
9
|
+
end
|
10
|
+
|
11
|
+
module_function :current_shell, :current_shell=
|
12
|
+
|
13
|
+
|
14
|
+
class Master
|
15
|
+
include Pwrake::Option
|
16
|
+
|
17
|
+
attr_reader :task_queue
|
18
|
+
attr_reader :shell_set
|
19
|
+
|
20
|
+
def initialize
|
21
|
+
end
|
22
|
+
|
23
|
+
def init
|
24
|
+
init_option # Pwrake::Option
|
25
|
+
end
|
26
|
+
|
27
|
+
def setup
|
28
|
+
setup_option # Pwrake::Option
|
29
|
+
end
|
30
|
+
|
31
|
+
def start
|
32
|
+
@counter = Counter.new
|
33
|
+
@task_queue = @queue_class.new(@core_list)
|
34
|
+
@task_queue.enable_steal = !Rake.application.options.disable_steal
|
35
|
+
@shell_set = []
|
36
|
+
@core_list.each_with_index do |h,i|
|
37
|
+
@shell_set << @shell_class.new(h,@shell_opt)
|
38
|
+
end
|
39
|
+
start_threads
|
40
|
+
end
|
41
|
+
|
42
|
+
def finish
|
43
|
+
Log.debug "-- Master#finish called"
|
44
|
+
@task_queue.finish if @task_queue
|
45
|
+
@threads.each{|t| t.join }
|
46
|
+
@counter.print
|
47
|
+
finish_option # Pwrake::Option
|
48
|
+
end
|
49
|
+
|
50
|
+
def start_threads
|
51
|
+
Thread.abort_on_exception = true
|
52
|
+
@threads = []
|
53
|
+
@shell_set.each do |c|
|
54
|
+
@threads << Thread.new(c) do |conn|
|
55
|
+
Pwrake.current_shell = conn
|
56
|
+
conn.start
|
57
|
+
begin
|
58
|
+
thread_loop(conn)
|
59
|
+
ensure
|
60
|
+
Log.info "-- worker[#{conn.id}] ensure : closing #{conn.host}"
|
61
|
+
conn.finish
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def thread_loop(conn,last=nil)
|
68
|
+
@task_queue.reserve(last) if last
|
69
|
+
hint = (conn) ? conn.host : nil
|
70
|
+
standard_exception_handling do
|
71
|
+
while t = @task_queue.deq(hint)
|
72
|
+
Log.debug "-- Master#thread_loop deq t=#{t.inspect}"
|
73
|
+
t.pw_invoke
|
74
|
+
return if t == last
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# Provide standard execption handling for the given block.
|
80
|
+
def standard_exception_handling
|
81
|
+
begin
|
82
|
+
yield
|
83
|
+
rescue SystemExit => ex
|
84
|
+
# Exit silently with current status
|
85
|
+
@task_queue.stop
|
86
|
+
raise
|
87
|
+
rescue OptionParser::InvalidOption => ex
|
88
|
+
# Exit silently
|
89
|
+
@task_queue.stop
|
90
|
+
exit(false)
|
91
|
+
rescue Exception => ex
|
92
|
+
# Exit with error message
|
93
|
+
name = "pwrake"
|
94
|
+
$stderr.puts "#{name} aborted!"
|
95
|
+
$stderr.puts ex.message
|
96
|
+
if Rake.application.options.trace
|
97
|
+
$stderr.puts ex.backtrace.join("\n")
|
98
|
+
else
|
99
|
+
$stderr.puts ex.backtrace.find {|str| str =~ /#{@rakefile}/ } || ""
|
100
|
+
$stderr.puts "(See full trace by running task with --trace)"
|
101
|
+
end
|
102
|
+
@task_queue.stop
|
103
|
+
exit(false)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
end # module Pwrake
|