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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 243728b311e7948c452e6de9e299e5938a3ebd24
4
- data.tar.gz: 8eb9ee8a10b1653c79465eab2c68f340a39ecc9f
3
+ metadata.gz: f5bc1786fca01c18645eeb743092710a25ebef1e
4
+ data.tar.gz: 7b4698982619547c6d37a6b0357f1937d33a7baa
5
5
  SHA512:
6
- metadata.gz: 46d41fe4394efa9c7ad329e8fa42d0fcd3ea6d2d72cd30a7d2b3f6d7fd8df61565f621ad339abc74d7662a5220df92d2de03beb46f0b5ded72d5a967e532f752
7
- data.tar.gz: 20566c536d6b4f4946feedea1e5ad956caf883d8772db394fc8217bbc9eae1bacecb9d5b74fdfde0d45cd94784b82f8ceed01ac3ed286edfa8e35dd3782a12c7
6
+ metadata.gz: fdf6ad7098498a63382450710dec248108f2956f8919ee72f63ee27fb1c9863eaedd449662ea709fce610c3735d6dc2eac37a3c58ad8c9451935ee32b8076ca1
7
+ data.tar.gz: 7d59b991703716459c7fec294b7acdffe8a55f33cd5ba989fc634d2e01a9be973ae092863f1aaeb661a16c662935c9ec858ecee98124c8aa4aa6995be25be743
@@ -40,4 +40,3 @@ $annotation_repo = Rbbt.var.sinatra.annotation_repo.find
40
40
  end
41
41
  end if Rbbt.etc.persist_properties.exists?
42
42
 
43
-
@@ -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 = IndiferentHash.setup({})
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(kb, name)
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
- @databases[Misc.fingerprint([name, options])] ||= \
158
+ key = name.to_s + "_" + Misc.digest(Misc.fingerprint([name,options,format,namespace]))
159
+ @databases[key] ||=
122
160
  begin
123
- Persist.memory("Database:" <<[name, self.dir] * "@") do
124
- options = Misc.add_defaults options, :persist_dir => dir.databases
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
- 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?
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
- Log.low "Opening database #{ name } from #{ Misc.fingerprint file }. #{options}"
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
- @indices[Misc.fingerprint([name, options])] ||= \
187
+ key = name.to_s + "_" + Misc.digest(Misc.fingerprint([name,options]))
188
+ @indices[key] ||=
141
189
  begin
142
- Persist.memory("Index:" <<[name, self.dir] * "@") do
143
- options = Misc.add_defaults options, :persist_dir => dir.indices
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
- 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?
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
- Log.low "Opening index #{ name } from #{ Misc.fingerprint file }. #{options}"
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
@@ -34,12 +34,12 @@ module TSV
34
34
 
35
35
  new_values.flatten if type == :flat
36
36
 
37
- self[key] = current.concat new_values
37
+ self[key] = current + new_values
38
38
  else
39
39
  if type == :double
40
- self[key] = current.concat [[]] * fields.length
40
+ self[key] = current + [[]] * fields.length
41
41
  else
42
- self[key] = current.concat [nil] * fields.length
42
+ self[key] = current + [nil] * fields.length
43
43
  end
44
44
  end
45
45
  end
@@ -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
- @pid = Process.fork do
9
- begin
10
- Misc.pre_fork
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
- @cleanup.call if @cleanup
13
- @queue.close_write
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
- if @callback_queue
16
- Misc.purge_pipes(@callback_queue.swrite)
17
- @callback_queue.close_read
18
- else
19
- Misc.purge_pipes
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
- Signal.trap(:INT){
23
- Kernel.exit! -1
24
- }
25
-
26
- loop do
27
- p = @queue.pop
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
- Kernel.exit! 0
35
- rescue ClosedStream
36
- rescue Aborted, Interrupt
37
- Log.warn "Worker #{Process.pid} aborted"
38
- Kernel.exit! 0
39
- rescue Exception
40
- Log.exception $!
41
- @callback_queue.push($!) if @callback_queue
42
- Kernel.exit! -1
43
- ensure
44
- @callback_queue.close_write if @callback_queue
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
@@ -298,4 +298,8 @@ module Misc
298
298
  nil
299
299
  end
300
300
  end
301
+
302
+ def self.memory_use(pid=nil)
303
+ `ps -o rss -p #{pid || $$}`.strip.split.last.to_i
304
+ end
301
305
  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.18
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-26 00:00:00.000000000 Z
11
+ date: 2014-08-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake