scout-essentials 1.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 +7 -0
- data/.document +5 -0
- data/.vimproject +78 -0
- data/Gemfile +14 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +18 -0
- data/Rakefile +47 -0
- data/VERSION +1 -0
- data/lib/scout/cmd.rb +348 -0
- data/lib/scout/concurrent_stream.rb +284 -0
- data/lib/scout/config.rb +168 -0
- data/lib/scout/exceptions.rb +77 -0
- data/lib/scout/indiferent_hash/case_insensitive.rb +30 -0
- data/lib/scout/indiferent_hash/options.rb +115 -0
- data/lib/scout/indiferent_hash.rb +96 -0
- data/lib/scout/log/color.rb +224 -0
- data/lib/scout/log/color_class.rb +269 -0
- data/lib/scout/log/fingerprint.rb +69 -0
- data/lib/scout/log/progress/report.rb +244 -0
- data/lib/scout/log/progress/util.rb +173 -0
- data/lib/scout/log/progress.rb +106 -0
- data/lib/scout/log/trap.rb +107 -0
- data/lib/scout/log.rb +441 -0
- data/lib/scout/meta_extension.rb +100 -0
- data/lib/scout/misc/digest.rb +63 -0
- data/lib/scout/misc/filesystem.rb +25 -0
- data/lib/scout/misc/format.rb +255 -0
- data/lib/scout/misc/helper.rb +31 -0
- data/lib/scout/misc/insist.rb +56 -0
- data/lib/scout/misc/monitor.rb +66 -0
- data/lib/scout/misc/system.rb +73 -0
- data/lib/scout/misc.rb +10 -0
- data/lib/scout/named_array.rb +138 -0
- data/lib/scout/open/lock/lockfile.rb +587 -0
- data/lib/scout/open/lock.rb +68 -0
- data/lib/scout/open/remote.rb +135 -0
- data/lib/scout/open/stream.rb +491 -0
- data/lib/scout/open/util.rb +244 -0
- data/lib/scout/open.rb +170 -0
- data/lib/scout/path/find.rb +204 -0
- data/lib/scout/path/tmpfile.rb +8 -0
- data/lib/scout/path/util.rb +127 -0
- data/lib/scout/path.rb +51 -0
- data/lib/scout/persist/open.rb +17 -0
- data/lib/scout/persist/path.rb +15 -0
- data/lib/scout/persist/serialize.rb +157 -0
- data/lib/scout/persist.rb +104 -0
- data/lib/scout/resource/open.rb +8 -0
- data/lib/scout/resource/path.rb +80 -0
- data/lib/scout/resource/produce/rake.rb +69 -0
- data/lib/scout/resource/produce.rb +151 -0
- data/lib/scout/resource/scout.rb +3 -0
- data/lib/scout/resource/software.rb +178 -0
- data/lib/scout/resource/util.rb +59 -0
- data/lib/scout/resource.rb +40 -0
- data/lib/scout/simple_opt/accessor.rb +54 -0
- data/lib/scout/simple_opt/doc.rb +126 -0
- data/lib/scout/simple_opt/get.rb +57 -0
- data/lib/scout/simple_opt/parse.rb +67 -0
- data/lib/scout/simple_opt/setup.rb +26 -0
- data/lib/scout/simple_opt.rb +5 -0
- data/lib/scout/tmpfile.rb +129 -0
- data/lib/scout-essentials.rb +10 -0
- data/scout-essentials.gemspec +143 -0
- data/share/color/color_names +507 -0
- data/share/color/diverging_colors.hex +12 -0
- data/share/software/install_helpers +523 -0
- data/test/scout/indiferent_hash/test_case_insensitive.rb +16 -0
- data/test/scout/indiferent_hash/test_options.rb +46 -0
- data/test/scout/log/test_color.rb +0 -0
- data/test/scout/log/test_progress.rb +108 -0
- data/test/scout/misc/test_digest.rb +30 -0
- data/test/scout/misc/test_filesystem.rb +30 -0
- data/test/scout/misc/test_insist.rb +13 -0
- data/test/scout/misc/test_system.rb +21 -0
- data/test/scout/open/test_lock.rb +52 -0
- data/test/scout/open/test_remote.rb +25 -0
- data/test/scout/open/test_stream.rb +676 -0
- data/test/scout/open/test_util.rb +73 -0
- data/test/scout/path/test_find.rb +110 -0
- data/test/scout/path/test_util.rb +22 -0
- data/test/scout/persist/test_open.rb +37 -0
- data/test/scout/persist/test_path.rb +37 -0
- data/test/scout/persist/test_serialize.rb +114 -0
- data/test/scout/resource/test_path.rb +58 -0
- data/test/scout/resource/test_produce.rb +94 -0
- data/test/scout/resource/test_software.rb +24 -0
- data/test/scout/resource/test_util.rb +38 -0
- data/test/scout/simple_opt/test_doc.rb +16 -0
- data/test/scout/simple_opt/test_get.rb +11 -0
- data/test/scout/simple_opt/test_parse.rb +10 -0
- data/test/scout/simple_opt/test_setup.rb +77 -0
- data/test/scout/test_cmd.rb +85 -0
- data/test/scout/test_concurrent_stream.rb +29 -0
- data/test/scout/test_config.rb +66 -0
- data/test/scout/test_indiferent_hash.rb +26 -0
- data/test/scout/test_log.rb +32 -0
- data/test/scout/test_meta_extension.rb +80 -0
- data/test/scout/test_misc.rb +6 -0
- data/test/scout/test_named_array.rb +43 -0
- data/test/scout/test_open.rb +146 -0
- data/test/scout/test_path.rb +54 -0
- data/test/scout/test_persist.rb +186 -0
- data/test/scout/test_resource.rb +26 -0
- data/test/scout/test_tmpfile.rb +53 -0
- data/test/test_helper.rb +50 -0
- metadata +247 -0
@@ -0,0 +1,284 @@
|
|
1
|
+
require_relative 'indiferent_hash'
|
2
|
+
|
3
|
+
module AbortedStream
|
4
|
+
attr_accessor :exception
|
5
|
+
def self.setup(obj, exception = nil)
|
6
|
+
obj.extend AbortedStream
|
7
|
+
obj.exception = exception
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
module ConcurrentStream
|
12
|
+
attr_accessor :threads, :pids, :callback, :abort_callback, :filename, :joined, :aborted, :autojoin, :lock, :no_fail, :pair, :thread, :stream_exception, :log, :std_err, :next
|
13
|
+
|
14
|
+
def self.setup(stream, options = {}, &block)
|
15
|
+
threads, pids, callback, abort_callback, filename, autojoin, lock, no_fail, pair, next_stream = IndiferentHash.process_options options, :threads, :pids, :callback, :abort_callback, :filename, :autojoin, :lock, :no_fail, :pair, :next
|
16
|
+
stream.extend ConcurrentStream unless ConcurrentStream === stream
|
17
|
+
|
18
|
+
stream.threads ||= []
|
19
|
+
stream.pids ||= []
|
20
|
+
stream.threads.concat(Array === threads ? threads : [threads]) unless threads.nil?
|
21
|
+
stream.pids.concat(Array === pids ? pids : [pids]) unless pids.nil? or pids.empty?
|
22
|
+
stream.autojoin = autojoin unless autojoin.nil?
|
23
|
+
stream.no_fail = no_fail unless no_fail.nil?
|
24
|
+
stream.std_err = ""
|
25
|
+
|
26
|
+
stream.next = next_stream unless next_stream.nil?
|
27
|
+
stream.pair = pair unless pair.nil?
|
28
|
+
|
29
|
+
callback = block if block_given?
|
30
|
+
if callback
|
31
|
+
if stream.callback
|
32
|
+
old_callback = stream.callback
|
33
|
+
stream.callback = Proc.new do
|
34
|
+
old_callback.call
|
35
|
+
callback.call
|
36
|
+
end
|
37
|
+
else
|
38
|
+
stream.callback = callback
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
if abort_callback
|
43
|
+
if stream.abort_callback
|
44
|
+
old_abort_callback = stream.abort_callback
|
45
|
+
stream.abort_callback = Proc.new do
|
46
|
+
old_abort_callback.call
|
47
|
+
abort_callback.call
|
48
|
+
end
|
49
|
+
else
|
50
|
+
stream.abort_callback = abort_callback
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
stream.filename = filename.nil? ? stream.inspect.split(":").last[0..-2] : filename
|
55
|
+
|
56
|
+
stream.lock = lock unless lock.nil?
|
57
|
+
|
58
|
+
stream.aborted = false
|
59
|
+
|
60
|
+
stream
|
61
|
+
end
|
62
|
+
|
63
|
+
def annotate(stream)
|
64
|
+
ConcurrentStream.setup(stream, :threads => threads, :pids => pids, :callback => callback, :abort_callback => abort_callback, :filename => filename, :autojoin => autojoin, :lock => lock)
|
65
|
+
stream
|
66
|
+
end
|
67
|
+
|
68
|
+
def clear
|
69
|
+
@threads = @pids = @callback = @abort_callback = @joined = nil
|
70
|
+
end
|
71
|
+
|
72
|
+
def joined?
|
73
|
+
@joined
|
74
|
+
end
|
75
|
+
|
76
|
+
def aborted?
|
77
|
+
@aborted
|
78
|
+
end
|
79
|
+
|
80
|
+
def join_threads
|
81
|
+
if @threads
|
82
|
+
@threads.each do |t|
|
83
|
+
next if t == Thread.current
|
84
|
+
begin
|
85
|
+
t.join
|
86
|
+
if Process::Status === t.value
|
87
|
+
if ! (t.value.success? || no_fail)
|
88
|
+
|
89
|
+
if log
|
90
|
+
msg = "Error joining #{self.filename || self.inspect}. Last log line: #{log}"
|
91
|
+
else
|
92
|
+
msg = "Error joining #{self.filename || self.inspect}"
|
93
|
+
end
|
94
|
+
|
95
|
+
raise ConcurrentStreamProcessFailed.new t.pid, msg, self
|
96
|
+
end
|
97
|
+
end
|
98
|
+
rescue Exception
|
99
|
+
if no_fail
|
100
|
+
Log.low "Not failing on exception joining thread in ConcurrenStream - #{filename} - #{$!.message}"
|
101
|
+
else
|
102
|
+
Log.low "Exception joining thread in ConcurrenStream #{Log.fingerprint self} - #{Log.fingerprint t} - #{$!.message}"
|
103
|
+
stream_raise_exception $!
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
@threads = []
|
109
|
+
end
|
110
|
+
|
111
|
+
def join_pids
|
112
|
+
if @pids and @pids.any?
|
113
|
+
@pids.each do |pid|
|
114
|
+
begin
|
115
|
+
Process.waitpid(pid, Process::WUNTRACED)
|
116
|
+
stream_raise_exception ConcurrentStreamProcessFailed.new(pid, "Error in waitpid", self) unless $?.success? or no_fail
|
117
|
+
rescue Errno::ECHILD
|
118
|
+
end
|
119
|
+
end
|
120
|
+
@pids = []
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def join_callback
|
125
|
+
if @callback and not joined?
|
126
|
+
begin
|
127
|
+
@callback.call
|
128
|
+
ensure
|
129
|
+
@callback = nil
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def join
|
135
|
+
begin
|
136
|
+
join_threads
|
137
|
+
join_pids
|
138
|
+
raise stream_exception if stream_exception
|
139
|
+
join_callback
|
140
|
+
close unless closed?
|
141
|
+
ensure
|
142
|
+
@joined = true
|
143
|
+
begin
|
144
|
+
lock.unlock if lock && lock.locked?
|
145
|
+
rescue
|
146
|
+
Log.exception $!
|
147
|
+
end
|
148
|
+
raise stream_exception if stream_exception
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def abort_threads(exception = nil)
|
153
|
+
return unless @threads and @threads.any?
|
154
|
+
name = Log.fingerprint(Thread.current)
|
155
|
+
name += " - file:#{filename}" if filename
|
156
|
+
Log.low "Aborting threads (#{name}) - #{@threads.collect{|t| Log.fingerprint(t) } * ", "}"
|
157
|
+
|
158
|
+
threads = @threads.dup
|
159
|
+
@threads.clear
|
160
|
+
threads.each do |t|
|
161
|
+
next if t == Thread.current
|
162
|
+
next if t["aborted"]
|
163
|
+
t["aborted"] = true
|
164
|
+
exception = exception.nil? ? Aborted.new : exception
|
165
|
+
Log.debug "Aborting thread #{Log.fingerprint(t)} with exception: #{exception}"
|
166
|
+
t.raise(exception)
|
167
|
+
t.join
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def abort_pids
|
172
|
+
@pids.each do |pid|
|
173
|
+
begin
|
174
|
+
Log.low "Killing PID #{pid} in ConcurrentStream #{filename}"
|
175
|
+
Process.kill :INT, pid
|
176
|
+
rescue Errno::ESRCH
|
177
|
+
end
|
178
|
+
end if @pids
|
179
|
+
@pids = []
|
180
|
+
end
|
181
|
+
|
182
|
+
def abort(exception = nil)
|
183
|
+
self.stream_exception ||= exception
|
184
|
+
if @aborted
|
185
|
+
Log.medium "Already aborted stream #{Log.fingerprint self} [#{@aborted}]"
|
186
|
+
return
|
187
|
+
else
|
188
|
+
Log.medium "Aborting stream #{Log.fingerprint self} [#{@aborted}]"
|
189
|
+
end
|
190
|
+
AbortedStream.setup(self, exception)
|
191
|
+
@aborted = true
|
192
|
+
begin
|
193
|
+
@abort_callback.call exception if @abort_callback
|
194
|
+
|
195
|
+
abort_threads(exception)
|
196
|
+
abort_pids
|
197
|
+
|
198
|
+
@callback = nil
|
199
|
+
@abort_callback = nil
|
200
|
+
|
201
|
+
if @pair && @pair.respond_to?(:abort) && ! @pair.aborted?
|
202
|
+
Log.medium "Aborting pair stream #{Log.fingerprint self}: #{Log.fingerprint @pair }"
|
203
|
+
@pair.abort exception
|
204
|
+
end
|
205
|
+
ensure
|
206
|
+
close unless closed?
|
207
|
+
|
208
|
+
if lock and lock.locked?
|
209
|
+
lock.unlock
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
def close(*args)
|
215
|
+
if autojoin
|
216
|
+
begin
|
217
|
+
super(*args)
|
218
|
+
rescue
|
219
|
+
self.abort
|
220
|
+
self.join
|
221
|
+
stream_raise_exception $!
|
222
|
+
ensure
|
223
|
+
self.join if ! @stream_exception && (self.closed? || self.eof?)
|
224
|
+
end
|
225
|
+
else
|
226
|
+
super(*args)
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
def read(*args)
|
231
|
+
begin
|
232
|
+
super(*args)
|
233
|
+
rescue Exception
|
234
|
+
@stream_exception ||= $!
|
235
|
+
raise @stream_exception
|
236
|
+
ensure
|
237
|
+
if ! @stream_exception && autojoin && ! closed?
|
238
|
+
begin
|
239
|
+
done = eof?
|
240
|
+
rescue Exception
|
241
|
+
self.abort($!)
|
242
|
+
raise $!
|
243
|
+
end
|
244
|
+
close if done
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
def add_callback(&block)
|
250
|
+
old_callback = callback
|
251
|
+
@callback = Proc.new do
|
252
|
+
old_callback.call if old_callback
|
253
|
+
block.call
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
def stream_raise_exception(exception)
|
258
|
+
self.stream_exception = exception
|
259
|
+
threads.each do |thread|
|
260
|
+
thread.raise exception
|
261
|
+
end
|
262
|
+
self.abort
|
263
|
+
end
|
264
|
+
|
265
|
+
def self.process_stream(stream, close: true, join: true, message: "process_stream", **kwargs, &block)
|
266
|
+
ConcurrentStream.setup(stream, **kwargs)
|
267
|
+
begin
|
268
|
+
begin
|
269
|
+
yield
|
270
|
+
ensure
|
271
|
+
stream.close if close && stream.respond_to?(:close) && ! (stream.respond_to?(:closed?) && stream.closed?)
|
272
|
+
stream.join if join && stream.respond_to?(:join) && ! stream.joined?
|
273
|
+
end
|
274
|
+
rescue Aborted
|
275
|
+
Log.low "Aborted #{message}: #{$!.message}"
|
276
|
+
stream.abort($!) if stream.respond_to?(:abort) && ! stream.aborted?
|
277
|
+
raise $!
|
278
|
+
rescue Exception
|
279
|
+
Log.low "Exception #{message}: #{$!.message}"
|
280
|
+
stream.abort($!) if stream.respond_to?(:abort) && ! stream.aborted?
|
281
|
+
raise $!
|
282
|
+
end
|
283
|
+
end
|
284
|
+
end
|
data/lib/scout/config.rb
ADDED
@@ -0,0 +1,168 @@
|
|
1
|
+
require_relative 'path'
|
2
|
+
require_relative 'resource'
|
3
|
+
require_relative 'resource/scout'
|
4
|
+
|
5
|
+
module Scout::Config
|
6
|
+
|
7
|
+
CACHE ||= IndiferentHash.setup({})
|
8
|
+
|
9
|
+
GOT_KEYS=[]
|
10
|
+
|
11
|
+
def self.add_entry(key, value, tokens)
|
12
|
+
tokens = [tokens] unless Array === tokens
|
13
|
+
tokens << "key:#{key}" unless tokens.include?("key:#{key}")
|
14
|
+
CACHE[key.to_s] ||= []
|
15
|
+
CACHE[key.to_s] << [tokens, value]
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.load_file(file)
|
19
|
+
Log.debug "Loading config file: #{ file }"
|
20
|
+
TSV.traverse file, :type => :array do |line|
|
21
|
+
next if line =~ /^#/
|
22
|
+
key, value, *tokens = line.strip.split(/\s/)
|
23
|
+
|
24
|
+
self.add_entry(key, value, tokens) if key
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.load_config
|
29
|
+
Scout.etc.config.find_all.reverse.each do |file|
|
30
|
+
self.load_file(file)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.set(values, *tokens)
|
35
|
+
if not Hash === values
|
36
|
+
values = {values => tokens.shift}
|
37
|
+
end
|
38
|
+
|
39
|
+
values.each do |key,value|
|
40
|
+
add_entry key, value, tokens
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.token_priority(token)
|
45
|
+
token, _sep, priority = token.to_s.partition("::")
|
46
|
+
|
47
|
+
if priority.nil? || priority.empty?
|
48
|
+
type, _sep, rest = token.partition(":")
|
49
|
+
priority = case type
|
50
|
+
when "workflow"
|
51
|
+
4
|
52
|
+
when "task"
|
53
|
+
3
|
54
|
+
when "file"
|
55
|
+
2
|
56
|
+
when "line"
|
57
|
+
1
|
58
|
+
when "key"
|
59
|
+
20
|
60
|
+
else
|
61
|
+
10
|
62
|
+
end
|
63
|
+
else
|
64
|
+
priority = priority.to_i
|
65
|
+
end
|
66
|
+
|
67
|
+
[token, priority]
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.match(entries, give_token)
|
71
|
+
priorities = {}
|
72
|
+
entries.each do |tokens, value|
|
73
|
+
best_prio = nil
|
74
|
+
tokens = [tokens] unless Array === tokens
|
75
|
+
tokens.each do |tok|
|
76
|
+
tok, prio = token_priority tok
|
77
|
+
next unless tok == give_token
|
78
|
+
|
79
|
+
best_prio = prio if best_prio.nil? or best_prio > prio
|
80
|
+
next if prio > best_prio
|
81
|
+
|
82
|
+
priorities[prio] ||= []
|
83
|
+
priorities[prio].unshift value
|
84
|
+
end
|
85
|
+
end if entries
|
86
|
+
priorities
|
87
|
+
end
|
88
|
+
|
89
|
+
# For equal priorities the matching prioritizes tokens ealier in the list
|
90
|
+
def self.get(key, *tokens)
|
91
|
+
options = tokens.pop if Hash === tokens.last
|
92
|
+
default = options.nil? ? nil : options[:default]
|
93
|
+
|
94
|
+
tokens = ["key:" + key] if tokens.empty?
|
95
|
+
|
96
|
+
tokens = tokens.flatten
|
97
|
+
file, _sep, line = caller.reject{|l|
|
98
|
+
l =~ /rbbt\/(?:resource\.rb|workflow\.rb)/ or
|
99
|
+
l =~ /rbbt\/resource\/path\.rb/ or
|
100
|
+
l =~ /rbbt\/util\/misc\.rb/ or
|
101
|
+
l =~ /accessor\.rb/ or
|
102
|
+
l =~ /progress-monitor\.rb/
|
103
|
+
}.first.partition(":")
|
104
|
+
|
105
|
+
File.expand_path(file)
|
106
|
+
|
107
|
+
tokens << ("file:" << file)
|
108
|
+
tokens << ("line:" << file << ":" << line.sub(/:in \`.*/,''))
|
109
|
+
|
110
|
+
entries = CACHE[key.to_s]
|
111
|
+
priorities = {}
|
112
|
+
tokens.each do |token|
|
113
|
+
token_prio = match entries, token.to_s
|
114
|
+
token_prio.each do |prio, values|
|
115
|
+
priorities[prio] ||= []
|
116
|
+
priorities[prio].concat(values)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
value = priorities.empty? ? default : priorities.collect{|p| p }.sort_by{|p,v| p}.first.last.first
|
121
|
+
value = false if value == 'false'
|
122
|
+
|
123
|
+
Log.debug "Value #{value.inspect} for config key '#{ key }': #{tokens * ", "}"
|
124
|
+
GOT_KEYS << [key, value, tokens]
|
125
|
+
|
126
|
+
if String === value && m = value.match(/^env:(.*)/)
|
127
|
+
variable = m.captures.first
|
128
|
+
ENV[variable]
|
129
|
+
elsif value == 'nil'
|
130
|
+
nil
|
131
|
+
else
|
132
|
+
value
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def self.with_config
|
137
|
+
saved_config = {}
|
138
|
+
CACHE.each do |k,v|
|
139
|
+
saved_config[k] = v.dup
|
140
|
+
end
|
141
|
+
saved_got_keys = GOT_KEYS.dup
|
142
|
+
begin
|
143
|
+
yield
|
144
|
+
ensure
|
145
|
+
CACHE.replace(saved_config)
|
146
|
+
GOT_KEYS.replace(saved_got_keys)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def self.process_config(config)
|
151
|
+
if Path.is_filename?(config) && File.exist?(config)
|
152
|
+
Scout::Config.load_file(config)
|
153
|
+
elsif Scout.etc.config_profile[config].exists?
|
154
|
+
Scout::Config.load_file(Scout.etc.config_profile[config].find)
|
155
|
+
else
|
156
|
+
key, value, *tokens = config.split(/\s/)
|
157
|
+
tokens = tokens.collect do |tok|
|
158
|
+
tok, _sep, prio = tok.partition("::")
|
159
|
+
prio = "0" if prio.nil? or prio.empty?
|
160
|
+
[tok, prio] * "::"
|
161
|
+
end
|
162
|
+
Scout::Config.set({key => value}, *tokens)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
|
167
|
+
self.load_config
|
168
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
class ScoutDeprecated < StandardError; end
|
2
|
+
class ScoutException < StandardError; end
|
3
|
+
|
4
|
+
class FieldNotFoundError < StandardError;end
|
5
|
+
|
6
|
+
class TryAgain < StandardError; end
|
7
|
+
class StopInsist < Exception
|
8
|
+
attr_accessor :exception
|
9
|
+
def initialize(exception)
|
10
|
+
@exception = exception
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class Aborted < StandardError; end
|
15
|
+
|
16
|
+
class ParameterException < ScoutException; end
|
17
|
+
class MissingParameterException < ParameterException
|
18
|
+
def initialize(parameter)
|
19
|
+
super("Missing parameter '#{parameter}'")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
class ProcessFailed < StandardError;
|
23
|
+
attr_accessor :pid, :msg
|
24
|
+
def initialize(pid = Process.pid, msg = nil)
|
25
|
+
@pid = pid
|
26
|
+
@msg = msg
|
27
|
+
if @pid
|
28
|
+
if @msg
|
29
|
+
message = "Process #{@pid} failed - #{@msg}"
|
30
|
+
else
|
31
|
+
message = "Process #{@pid} failed"
|
32
|
+
end
|
33
|
+
else
|
34
|
+
message = "Failed to run #{@msg}"
|
35
|
+
end
|
36
|
+
super(message)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
class ConcurrentStreamProcessFailed < ProcessFailed
|
41
|
+
attr_accessor :concurrent_stream
|
42
|
+
def initialize(pid = Process.pid, msg = nil, concurrent_stream = nil)
|
43
|
+
super(pid, msg)
|
44
|
+
@concurrent_stream = concurrent_stream
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class OpenURLError < StandardError; end
|
49
|
+
|
50
|
+
class DontClose < Exception
|
51
|
+
attr_accessor :payload
|
52
|
+
def initialize(payload = nil)
|
53
|
+
@payload = payload
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
class KeepLocked < Exception
|
59
|
+
attr_accessor :payload
|
60
|
+
def initialize(payload)
|
61
|
+
@payload = payload
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
class KeepBar < Exception
|
66
|
+
attr_accessor :payload
|
67
|
+
def initialize(payload)
|
68
|
+
@payload = payload
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
class LockInterrupted < TryAgain; end
|
73
|
+
|
74
|
+
class ClosedStream < StandardError; end
|
75
|
+
|
76
|
+
class ResourceNotFound < ScoutException; end
|
77
|
+
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module CaseInsensitiveHash
|
2
|
+
|
3
|
+
def self.setup(hash)
|
4
|
+
hash.extend CaseInsensitiveHash
|
5
|
+
end
|
6
|
+
|
7
|
+
def downcase_keys
|
8
|
+
@downcase_keys ||= begin
|
9
|
+
down = {}
|
10
|
+
keys.collect{|key|
|
11
|
+
down[key.to_s.downcase] = key
|
12
|
+
}
|
13
|
+
down
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def [](key, *rest)
|
18
|
+
value = super(key, *rest)
|
19
|
+
return value unless value.nil?
|
20
|
+
key_downcase = key.to_s.downcase
|
21
|
+
super(downcase_keys[key_downcase])
|
22
|
+
end
|
23
|
+
|
24
|
+
def values_at(*keys)
|
25
|
+
keys.collect do |key|
|
26
|
+
self[key]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
module IndiferentHash
|
2
|
+
def self.add_defaults(options, defaults = {})
|
3
|
+
options = string2hash options if String === options
|
4
|
+
IndiferentHash.setup(options)
|
5
|
+
|
6
|
+
defaults = string2hash defaults if String === defaults
|
7
|
+
|
8
|
+
defaults.each do |key, value|
|
9
|
+
next if options.include?(key)
|
10
|
+
|
11
|
+
options[key] = value
|
12
|
+
end
|
13
|
+
|
14
|
+
options
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.process_options(hash, *keys)
|
18
|
+
IndiferentHash.setup(hash)
|
19
|
+
|
20
|
+
defaults = keys.pop if Hash === keys.last
|
21
|
+
hash = IndiferentHash.add_defaults hash, defaults if defaults
|
22
|
+
|
23
|
+
if keys.length == 1
|
24
|
+
hash.include?(keys.first.to_sym) ? hash.delete(keys.first.to_sym) : hash.delete(keys.first.to_s)
|
25
|
+
else
|
26
|
+
keys.collect do |key| hash.include?(key.to_sym) ? hash.delete(key.to_sym) : hash.delete(key.to_s) end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.pull_keys(hash, prefix)
|
31
|
+
new = {}
|
32
|
+
prefix = prefix.to_s
|
33
|
+
hash.keys.each do |key|
|
34
|
+
if key.to_s =~ /#{ prefix }_(.*)/
|
35
|
+
case
|
36
|
+
when String === key
|
37
|
+
new[$1] = hash.delete key
|
38
|
+
when Symbol === key
|
39
|
+
new[$1.to_sym] = hash.delete key
|
40
|
+
end
|
41
|
+
else
|
42
|
+
if key.to_s == prefix.to_s
|
43
|
+
new[key] = hash.delete key
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
IndiferentHash.setup(new)
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.zip2hash(list1, list2)
|
52
|
+
hash = {}
|
53
|
+
list1.each_with_index do |e,i|
|
54
|
+
hash[e] = list2[i]
|
55
|
+
end
|
56
|
+
IndiferentHash.setup(hash)
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.positional2hash(keys, *values)
|
60
|
+
if Hash === values.last
|
61
|
+
extra = values.pop
|
62
|
+
inputs = IndiferentHash.zip2hash(keys, values)
|
63
|
+
inputs.delete_if{|k,v| v.nil? or (String === v and v.empty?)}
|
64
|
+
inputs = IndiferentHash.add_defaults inputs, extra
|
65
|
+
inputs.delete_if{|k,v| not keys.include?(k) and not (Symbol === k ? keys.include?(k.to_s) : keys.include?(k.to_sym))}
|
66
|
+
inputs
|
67
|
+
else
|
68
|
+
IndiferentHash.zip2hash(keys, values)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.array2hash(array, default = nil)
|
73
|
+
hash = {}
|
74
|
+
array.each do |key, value|
|
75
|
+
value = default.dup if value.nil? and not default.nil?
|
76
|
+
hash[key] = value
|
77
|
+
end
|
78
|
+
IndiferentHash.setup(hash)
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.process_to_hash(list)
|
82
|
+
result = yield list
|
83
|
+
zip2hash(list, result)
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.hash2string(hash)
|
87
|
+
hash.sort_by{|k,v| k.to_s}.collect{|k,v|
|
88
|
+
next unless %w(Symbol String Float Fixnum Integer Numeric TrueClass FalseClass Module Class Object).include? v.class.to_s
|
89
|
+
[ Symbol === k ? ":" << k.to_s : k.to_s.chomp,
|
90
|
+
Symbol === v ? ":" << v.to_s : v.to_s.chomp] * "="
|
91
|
+
}.compact * "#"
|
92
|
+
end
|
93
|
+
|
94
|
+
def self.string2hash(string)
|
95
|
+
options = {}
|
96
|
+
|
97
|
+
string.split('#').each do |str|
|
98
|
+
key, _, value = str.partition "="
|
99
|
+
|
100
|
+
key = key[1..-1].to_sym if key[0] == ":"
|
101
|
+
|
102
|
+
options[key] = true and next if value.empty?
|
103
|
+
options[key] = value[1..-1].to_sym and next if value[0] == ":"
|
104
|
+
options[key] = Regexp.new(/#{value[1..-2]}/) and next if value[0] == "/" and value[-1] == "/"
|
105
|
+
options[key] = value[1..-2] and next if value =~ /^['"].*['"]$/
|
106
|
+
options[key] = value.to_i and next if value =~ /^\d+$/
|
107
|
+
options[key] = value.to_f and next if value =~ /^\d*\.\d+$/
|
108
|
+
options[key] = true and next if value == "true"
|
109
|
+
options[key] = false and next if value == "false"
|
110
|
+
options[key] = value
|
111
|
+
end
|
112
|
+
|
113
|
+
IndiferentHash.setup(options)
|
114
|
+
end
|
115
|
+
end
|