rbbt-util 5.14.18 → 5.14.20
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/etc/app.d/entities.rb +0 -1
- data/lib/rbbt/knowledge_base.rb +86 -24
- data/lib/rbbt/tsv/attach/util.rb +3 -3
- data/lib/rbbt/tsv/manipulate.rb +10 -0
- data/lib/rbbt/tsv/parallel/traverse.rb +2 -2
- data/lib/rbbt/util/concurrency/processes.rb +4 -3
- data/lib/rbbt/util/concurrency/processes/worker.rb +114 -34
- data/lib/rbbt/util/misc/development.rb +4 -0
- data/share/rbbt_commands/association/subset +1 -0
- data/test/rbbt/util/concurrency/test_processes.rb +27 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f5bc1786fca01c18645eeb743092710a25ebef1e
|
4
|
+
data.tar.gz: 7b4698982619547c6d37a6b0357f1937d33a7baa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fdf6ad7098498a63382450710dec248108f2956f8919ee72f63ee27fb1c9863eaedd449662ea709fce610c3735d6dc2eac37a3c58ad8c9451935ee32b8076ca1
|
7
|
+
data.tar.gz: 7d59b991703716459c7fec294b7acdffe8a55f33cd5ba989fc634d2e01a9be973ae092863f1aaeb661a16c662935c9ec858ecee98124c8aa4aa6995be25be743
|
data/etc/app.d/entities.rb
CHANGED
data/lib/rbbt/knowledge_base.rb
CHANGED
@@ -22,12 +22,12 @@ class KnowledgeBase
|
|
22
22
|
|
23
23
|
attr_accessor :namespace, :dir, :indices, :registry, :format, :databases, :entity_options
|
24
24
|
def initialize(dir, namespace = nil)
|
25
|
-
@dir = Path.setup(dir).find
|
25
|
+
@dir = Path.setup(dir.dup).find
|
26
26
|
|
27
27
|
@namespace = namespace
|
28
28
|
@format = IndiferentHash.setup({})
|
29
29
|
|
30
|
-
@registry
|
30
|
+
@registry ||= IndiferentHash.setup({})
|
31
31
|
@entity_options = IndiferentHash.setup({})
|
32
32
|
|
33
33
|
@indices = IndiferentHash.setup({})
|
@@ -59,7 +59,7 @@ class KnowledgeBase
|
|
59
59
|
end
|
60
60
|
end
|
61
61
|
|
62
|
-
def syndicate(
|
62
|
+
def syndicate(name, kb)
|
63
63
|
kb.all_databases.each do |database|
|
64
64
|
db_name = [database, name] * "@"
|
65
65
|
file, kb_options = kb.registry[database]
|
@@ -72,7 +72,7 @@ class KnowledgeBase
|
|
72
72
|
end
|
73
73
|
|
74
74
|
def all_databases
|
75
|
-
@registry.keys
|
75
|
+
@registry.keys
|
76
76
|
end
|
77
77
|
|
78
78
|
def description(name)
|
@@ -117,43 +117,103 @@ class KnowledgeBase
|
|
117
117
|
{:namespace => namespace, :format => @format}
|
118
118
|
end
|
119
119
|
|
120
|
+
#def get_database(name, options = {})
|
121
|
+
# @databases[Misc.fingerprint([name, options])] ||= \
|
122
|
+
# begin
|
123
|
+
# Persist.memory("Database:" <<[name, self.dir] * "@") do
|
124
|
+
# options = Misc.add_defaults options, :persist_dir => dir.databases
|
125
|
+
# persist_options = Misc.pull_keys options, :persist
|
126
|
+
|
127
|
+
# file, registered_options = registry[name]
|
128
|
+
# options = open_options.merge(registered_options || {}).merge(options)
|
129
|
+
# raise "Repo #{ name } not found and not registered" if file.nil?
|
130
|
+
|
131
|
+
# Log.low "Opening database #{ name } from #{ Misc.fingerprint file }. #{options}"
|
132
|
+
# Association.open(file, options, persist_options).
|
133
|
+
# tap{|tsv| tsv.namespace = self.namespace}
|
134
|
+
# end
|
135
|
+
# end
|
136
|
+
#end
|
137
|
+
|
138
|
+
|
139
|
+
#def get_index(name, options = {})
|
140
|
+
# @indices[Misc.fingerprint([name, options])] ||= \
|
141
|
+
# begin
|
142
|
+
# Persist.memory("Index:" <<[name, self.dir] * "@") do
|
143
|
+
# options = Misc.add_defaults options, :persist_dir => dir.indices
|
144
|
+
# persist_options = Misc.pull_keys options, :persist
|
145
|
+
|
146
|
+
# file, registered_options = registry[name]
|
147
|
+
# options = open_options.merge(registered_options || {}).merge(options)
|
148
|
+
# raise "Repo #{ name } not found and not registered" if file.nil?
|
149
|
+
|
150
|
+
# Log.low "Opening index #{ name } from #{ Misc.fingerprint file }. #{options}"
|
151
|
+
# Association.index(file, options, persist_options).
|
152
|
+
# tap{|tsv| tsv.namespace = self.namespace}
|
153
|
+
# end
|
154
|
+
# end
|
155
|
+
#end
|
156
|
+
|
120
157
|
def get_database(name, options = {})
|
121
|
-
|
158
|
+
key = name.to_s + "_" + Misc.digest(Misc.fingerprint([name,options,format,namespace]))
|
159
|
+
@databases[key] ||=
|
122
160
|
begin
|
123
|
-
Persist.memory("Database:" <<[
|
124
|
-
|
161
|
+
Persist.memory("Database:" << [key, dir] * "@") do
|
162
|
+
persist_file = dir.databases[key]
|
163
|
+
file, registered_options = registry[name]
|
164
|
+
|
165
|
+
options = Misc.add_defaults options, :persist_file => persist_file, :namespace => namespace, :format => format
|
166
|
+
options = Misc.add_defaults options, registered_options
|
167
|
+
|
125
168
|
persist_options = Misc.pull_keys options, :persist
|
126
169
|
|
127
|
-
|
128
|
-
|
129
|
-
|
170
|
+
database = if persist_file.exists?
|
171
|
+
Log.low "Re-opening database #{ name } from #{ Misc.fingerprint persist_file }. #{options}"
|
172
|
+
Association.open(file, options, persist_options)
|
173
|
+
else
|
174
|
+
raise "Repo #{ name } not found and not registered" if file.nil?
|
175
|
+
Log.low "Opening database #{ name } from #{ Misc.fingerprint file }. #{options}"
|
176
|
+
Association.open(file, options, persist_options)
|
177
|
+
end
|
178
|
+
|
179
|
+
database.namespace = self.namespace
|
130
180
|
|
131
|
-
|
132
|
-
Association.open(file, options, persist_options).
|
133
|
-
tap{|tsv| tsv.namespace = self.namespace}
|
181
|
+
database
|
134
182
|
end
|
135
183
|
end
|
136
184
|
end
|
137
185
|
|
138
|
-
|
139
186
|
def get_index(name, options = {})
|
140
|
-
|
187
|
+
key = name.to_s + "_" + Misc.digest(Misc.fingerprint([name,options]))
|
188
|
+
@indices[key] ||=
|
141
189
|
begin
|
142
|
-
Persist.memory("Index:" <<[
|
143
|
-
|
190
|
+
Persist.memory("Index:" << [key, dir] * "@") do
|
191
|
+
persist_file = dir.indices[key]
|
192
|
+
file, registered_options = registry[name]
|
193
|
+
|
194
|
+
options = Misc.add_defaults options, :persist_file => persist_file, :namespace => namespace, :format => format
|
195
|
+
options = Misc.add_defaults options, registered_options
|
196
|
+
|
144
197
|
persist_options = Misc.pull_keys options, :persist
|
145
198
|
|
146
|
-
|
147
|
-
|
148
|
-
|
199
|
+
index = if persist_file.exists?
|
200
|
+
Log.low "Re-opening index #{ name } from #{ Misc.fingerprint persist_file }. #{options}"
|
201
|
+
Association.index(nil, options, persist_options)
|
202
|
+
else
|
203
|
+
options = Misc.add_defaults options, registered_options if registered_options
|
204
|
+
raise "Repo #{ name } not found and not registered" if file.nil?
|
205
|
+
Log.low "Opening index #{ name } from #{ Misc.fingerprint file }. #{options}"
|
206
|
+
Association.index(file, options, persist_options)
|
207
|
+
end
|
208
|
+
|
209
|
+
index.namespace = self.namespace
|
149
210
|
|
150
|
-
|
151
|
-
Association.index(file, options, persist_options).
|
152
|
-
tap{|tsv| tsv.namespace = self.namespace}
|
211
|
+
index
|
153
212
|
end
|
154
213
|
end
|
155
214
|
end
|
156
215
|
|
216
|
+
|
157
217
|
#{{{ Add manual database
|
158
218
|
|
159
219
|
def add_index(name, source_type, target_type, *fields)
|
@@ -292,6 +352,8 @@ class KnowledgeBase
|
|
292
352
|
|
293
353
|
def subset(name, entities)
|
294
354
|
entities = case entities
|
355
|
+
when :all
|
356
|
+
{:target => :all, :source => :all}
|
295
357
|
when AnnotatedArray
|
296
358
|
format = entities.format if entities.respond_to? :format
|
297
359
|
format ||= entities.base_entity.to_s
|
@@ -319,7 +381,7 @@ class KnowledgeBase
|
|
319
381
|
end
|
320
382
|
|
321
383
|
def translate(entities, type)
|
322
|
-
if format = @format[type] and format != entities.format
|
384
|
+
if format = @format[type] and (entities.respond_to? :format and format != entities.format)
|
323
385
|
entities.to format
|
324
386
|
else
|
325
387
|
entities
|
data/lib/rbbt/tsv/attach/util.rb
CHANGED
@@ -34,12 +34,12 @@ module TSV
|
|
34
34
|
|
35
35
|
new_values.flatten if type == :flat
|
36
36
|
|
37
|
-
self[key] = current
|
37
|
+
self[key] = current + new_values
|
38
38
|
else
|
39
39
|
if type == :double
|
40
|
-
self[key] = current
|
40
|
+
self[key] = current + [[]] * fields.length
|
41
41
|
else
|
42
|
-
self[key] = current
|
42
|
+
self[key] = current + [nil] * fields.length
|
43
43
|
end
|
44
44
|
end
|
45
45
|
end
|
data/lib/rbbt/tsv/manipulate.rb
CHANGED
@@ -528,6 +528,16 @@ module TSV
|
|
528
528
|
new
|
529
529
|
end
|
530
530
|
|
531
|
+
def column_values(field, options = {})
|
532
|
+
all = []
|
533
|
+
through :key, field do |k,values|
|
534
|
+
values = Array === values ? values.flatten : [values]
|
535
|
+
all.concat value
|
536
|
+
end
|
537
|
+
prepare_entity(all, field, options = {})
|
538
|
+
end
|
539
|
+
|
540
|
+
|
531
541
|
def process_key(&block)
|
532
542
|
new = annotate({})
|
533
543
|
through do |key, values|
|
@@ -334,9 +334,9 @@ module TSV
|
|
334
334
|
|
335
335
|
def self.traverse_cpus(num, obj, options, &block)
|
336
336
|
begin
|
337
|
-
callback, cleanup, join = Misc.process_options options, :callback, :cleanup, :join
|
337
|
+
callback, cleanup, join, respawn = Misc.process_options options, :callback, :cleanup, :join, :respawn
|
338
338
|
|
339
|
-
q = RbbtProcessQueue.new num, cleanup, join
|
339
|
+
q = RbbtProcessQueue.new num, cleanup, join, respawn
|
340
340
|
q.callback &callback
|
341
341
|
q.init &block
|
342
342
|
|
@@ -3,12 +3,13 @@ require 'rbbt/util/concurrency/processes/socket'
|
|
3
3
|
|
4
4
|
class RbbtProcessQueue
|
5
5
|
|
6
|
-
attr_accessor :num_processes, :processes, :queue, :process_monitor, :cleanup, :join
|
7
|
-
def initialize(num_processes, cleanup = nil, join = nil)
|
6
|
+
attr_accessor :num_processes, :processes, :queue, :process_monitor, :cleanup, :join, :reswpan
|
7
|
+
def initialize(num_processes, cleanup = nil, join = nil, reswpan = nil)
|
8
8
|
@num_processes = num_processes
|
9
9
|
@processes = []
|
10
10
|
@cleanup = cleanup
|
11
11
|
@join = join
|
12
|
+
@respawn = reswpan
|
12
13
|
@queue = RbbtProcessSocket.new
|
13
14
|
end
|
14
15
|
|
@@ -48,7 +49,7 @@ class RbbtProcessQueue
|
|
48
49
|
|
49
50
|
def init(&block)
|
50
51
|
num_processes.times do |i|
|
51
|
-
@processes << RbbtProcessQueueWorker.new(@queue, @callback_queue, @cleanup, &block)
|
52
|
+
@processes << RbbtProcessQueueWorker.new(@queue, @callback_queue, @cleanup, @respawn, &block)
|
52
53
|
end
|
53
54
|
@queue.close_read
|
54
55
|
|
@@ -2,46 +2,126 @@ require 'rbbt/util/concurrency/processes/socket'
|
|
2
2
|
class RbbtProcessQueue
|
3
3
|
class RbbtProcessQueueWorker
|
4
4
|
attr_reader :pid, :queue, :callback_queue, :cleanup, :block
|
5
|
-
def initialize(queue, callback_queue = nil, cleanup = nil, &block)
|
6
|
-
@queue, @callback_queue, @cleanup, @block = queue, callback_queue, cleanup, block
|
7
5
|
|
8
|
-
|
9
|
-
|
10
|
-
|
6
|
+
class Respawn < Exception; end
|
7
|
+
|
8
|
+
def run
|
9
|
+
begin
|
10
|
+
Signal.trap(:INT){
|
11
|
+
Kernel.exit! -1
|
12
|
+
}
|
13
|
+
|
14
|
+
@stop = false
|
15
|
+
Signal.trap(:USR1){
|
16
|
+
@stop = true
|
17
|
+
}
|
18
|
+
|
19
|
+
loop do
|
20
|
+
p = @queue.pop
|
21
|
+
next if p.nil?
|
22
|
+
raise p if Exception === p
|
23
|
+
raise p.first if Exception === p.first
|
24
|
+
res = @block.call *p
|
25
|
+
@callback_queue.push res if @callback_queue
|
26
|
+
raise Respawn if @stop
|
27
|
+
end
|
28
|
+
Kernel.exit! 0
|
29
|
+
rescue Respawn
|
30
|
+
Kernel.exit! 28
|
31
|
+
rescue ClosedStream
|
32
|
+
rescue Aborted, Interrupt
|
33
|
+
Log.warn "Worker #{Process.pid} aborted"
|
34
|
+
Kernel.exit! 0
|
35
|
+
rescue Exception
|
36
|
+
Log.exception $!
|
37
|
+
@callback_queue.push($!) if @callback_queue
|
38
|
+
Kernel.exit! -1
|
39
|
+
ensure
|
40
|
+
@callback_queue.close_write if @callback_queue
|
41
|
+
end
|
42
|
+
end
|
11
43
|
|
12
|
-
|
13
|
-
|
44
|
+
def run_with_respawn(multiplier = nil)
|
45
|
+
multiplier = case multiplier
|
46
|
+
when String
|
47
|
+
multiplier.to_s
|
48
|
+
when Fixnum
|
49
|
+
multiplier.to_i
|
50
|
+
else
|
51
|
+
3
|
52
|
+
end
|
14
53
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
54
|
+
status = nil
|
55
|
+
begin
|
56
|
+
@current = Process.fork do
|
57
|
+
run
|
58
|
+
end
|
59
|
+
Log.warn "Worker #{Process.pid} started with #{@current}"
|
60
|
+
|
61
|
+
@monitor_thread = Thread.new do
|
62
|
+
begin
|
63
|
+
while true
|
64
|
+
current = Misc.memory_use(@current)
|
65
|
+
initial = Misc.memory_use(Process.pid)
|
66
|
+
if current > multiplier * initial
|
67
|
+
Process.kill "USR1", @current
|
68
|
+
end
|
69
|
+
sleep 1
|
70
|
+
end
|
71
|
+
rescue
|
72
|
+
Log.exception $!
|
20
73
|
end
|
74
|
+
end
|
21
75
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
next if p.nil?
|
29
|
-
raise p if Exception === p
|
30
|
-
raise p.first if Exception === p.first
|
31
|
-
res = @block.call *p
|
32
|
-
@callback_queue.push res if @callback_queue
|
76
|
+
while true
|
77
|
+
pid, status = Process.waitpid2 @current
|
78
|
+
code = status.to_i >> 8
|
79
|
+
break unless code == 28
|
80
|
+
@current = Process.fork do
|
81
|
+
run
|
33
82
|
end
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
83
|
+
Log.warn "Worker #{Process.pid} respawning to #{@current}"
|
84
|
+
end
|
85
|
+
rescue Aborted, Interrupt
|
86
|
+
Log.warn "Worker #{Process.pid} aborted"
|
87
|
+
Kernel.exit! 0
|
88
|
+
Process.kill "INT", @current
|
89
|
+
rescue Exception
|
90
|
+
Log.exception $!
|
91
|
+
raise $!
|
92
|
+
ensure
|
93
|
+
@monitor_thread.kill
|
94
|
+
Process.kill "INT", @current if Misc.pid_exists? @current
|
95
|
+
@callback_queue.close_write if @callback_queue
|
96
|
+
end
|
97
|
+
|
98
|
+
if status
|
99
|
+
Kernel.exit! status.to_i >> 8
|
100
|
+
else
|
101
|
+
Kernel.exit! -1
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def initialize(queue, callback_queue = nil, cleanup = nil, respawn = false, &block)
|
106
|
+
@queue, @callback_queue, @cleanup, @block = queue, callback_queue, cleanup, block
|
107
|
+
|
108
|
+
@pid = Process.fork do
|
109
|
+
Misc.pre_fork
|
110
|
+
|
111
|
+
@cleanup.call if @cleanup
|
112
|
+
@queue.close_write
|
113
|
+
|
114
|
+
if @callback_queue
|
115
|
+
Misc.purge_pipes(@callback_queue.swrite)
|
116
|
+
@callback_queue.close_read
|
117
|
+
else
|
118
|
+
Misc.purge_pipes
|
119
|
+
end
|
120
|
+
|
121
|
+
if respawn
|
122
|
+
run_with_respawn respawn
|
123
|
+
else
|
124
|
+
run
|
45
125
|
end
|
46
126
|
end
|
47
127
|
end
|
@@ -19,6 +19,7 @@ Indicate the index file (TokyoCabinet BDB with source~target keys) as the <filen
|
|
19
19
|
-t--target* Target entities
|
20
20
|
-tsv--tsv* Output tsv
|
21
21
|
EOF
|
22
|
+
|
22
23
|
rbbt_usage and exit 0 if options[:help]
|
23
24
|
filename = ARGV.shift
|
24
25
|
raise ParameterException, "No filename specified" if filename.nil?
|
@@ -69,9 +69,36 @@ class TestConcurrencyProcess < Test::Unit::TestCase
|
|
69
69
|
sleep 2
|
70
70
|
q.clean
|
71
71
|
|
72
|
+
|
72
73
|
q.join
|
73
74
|
end
|
74
75
|
end
|
76
|
+
|
77
|
+
|
78
|
+
def test_process_respawn
|
79
|
+
q = RbbtProcessQueue.new 2, nil, nil, true
|
80
|
+
|
81
|
+
res = []
|
82
|
+
|
83
|
+
q.callback do |v|
|
84
|
+
res << v
|
85
|
+
end
|
86
|
+
|
87
|
+
q.init do |i|
|
88
|
+
$str ||="-"
|
89
|
+
$str = $str * (2 + rand(5).to_i)
|
90
|
+
sleep 0.1
|
91
|
+
"."
|
92
|
+
end
|
93
|
+
|
94
|
+
times = 50
|
95
|
+
|
96
|
+
times.times do |i|
|
97
|
+
q.process i
|
98
|
+
end
|
99
|
+
|
100
|
+
q.join
|
101
|
+
end
|
75
102
|
end
|
76
103
|
|
77
104
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rbbt-util
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.14.
|
4
|
+
version: 5.14.20
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Miguel Vazquez
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-08-
|
11
|
+
date: 2014-08-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|