bud 0.9.2 → 0.9.3
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +17 -4
- data/README.md +5 -0
- data/docs/cheat.md +1 -1
- data/docs/getstarted.md +1 -1
- data/lib/bud.rb +52 -34
- data/lib/bud/aggs.rb +8 -11
- data/lib/bud/bud_meta.rb +18 -18
- data/lib/bud/collections.rb +14 -21
- data/lib/bud/executor/README.rescan +80 -0
- data/lib/bud/executor/elements.rb +25 -44
- data/lib/bud/executor/group.rb +80 -29
- data/lib/bud/executor/join.rb +73 -90
- data/lib/bud/monkeypatch.rb +1 -1
- data/lib/bud/rebl.rb +5 -2
- data/lib/bud/rewrite.rb +18 -14
- data/lib/bud/server.rb +1 -1
- data/lib/bud/source.rb +0 -45
- data/lib/bud/storage/dbm.rb +13 -9
- data/lib/bud/viz.rb +6 -8
- data/lib/bud/viz_util.rb +1 -0
- metadata +3 -18
data/History.txt
CHANGED
@@ -1,4 +1,18 @@
|
|
1
|
-
== 0.9.
|
1
|
+
== 0.9.3 / 2012-08-20
|
2
|
+
|
3
|
+
* Change behavior of accum() aggregate to return a Set, rather than an Array in
|
4
|
+
an unspecified order
|
5
|
+
* Fix several serious bugs in caching/invalidation of materialized operator
|
6
|
+
state (#276, #278, #279)
|
7
|
+
* Avoid possible spurious infinite loop with dbm-backed collections
|
8
|
+
* Optimize aggregation/grouping performance
|
9
|
+
* Fix bugs and improve performance for materialization of sort operator
|
10
|
+
* Fix REBL regression with push-based runtime (#274)
|
11
|
+
* Minor performance optimizations for simple projection rules
|
12
|
+
* Remove dependency on gchart
|
13
|
+
* Built-in support for code coverage with MRI 1.9 and SimpleCov
|
14
|
+
|
15
|
+
== 0.9.2 / 2012-05-19
|
2
16
|
|
3
17
|
* Add new aggregate functions: bool_and() and bool_or()
|
4
18
|
* Fix bugs in notin() stratification and implementation (#271)
|
@@ -16,7 +30,7 @@
|
|
16
30
|
* Previous behavior was to ignore additional fields, but this was found to be
|
17
31
|
error-prone
|
18
32
|
* Remove builtin support for BUST (web services API); this avoids the need to
|
19
|
-
depend on the json, nestful and i18n gems
|
33
|
+
depend on the json, nestful and i18n gems
|
20
34
|
|
21
35
|
== 0.9.0 / 2012-03-21
|
22
36
|
|
@@ -39,5 +53,4 @@
|
|
39
53
|
* Support for Bloom-based signal handling has been removed
|
40
54
|
* Support for the "with" syntax has been removed
|
41
55
|
* The Bloom-based "deployment" framework has been removed
|
42
|
-
* Support for Tokyo Cabinet-
|
43
|
-
|
56
|
+
* Support for Tokyo Cabinet-backed collections has been removed
|
data/README.md
CHANGED
@@ -37,6 +37,11 @@ To run the unit tests:
|
|
37
37
|
% gem install minitest # unless already installed
|
38
38
|
% cd test; ruby ts_bud.rb
|
39
39
|
|
40
|
+
To run the unit tests and produce a code coverage report:
|
41
|
+
|
42
|
+
% gem install simplecov # unless already installed
|
43
|
+
% cd test; COVERAGE=1 ruby ts_bud.rb
|
44
|
+
|
40
45
|
## Optional Dependencies
|
41
46
|
|
42
47
|
The bud gem has a handful of mandatory dependencies. It also has one optional
|
data/docs/cheat.md
CHANGED
@@ -239,7 +239,7 @@ Finally, we output every tuple of `bc` that does *not* appear in `t`.
|
|
239
239
|
* `bc.group([:col1, :col2], min(:col3))`. *akin to min(col3) GROUP BY col1,col2*
|
240
240
|
* exemplary aggs: `min`, `max`, `bool_and`, `bool_or`, `choose`
|
241
241
|
* summary aggs: `sum`, `avg`, `count`
|
242
|
-
* structural aggs: `accum`
|
242
|
+
* structural aggs: `accum` *accumulates inputs into a Set*
|
243
243
|
* `bc.argmax([:attr1], :attr2)` *returns the bc items per attr1 that have highest attr2*
|
244
244
|
* `bc.argmin([:attr1], :attr2)`
|
245
245
|
* `bc.argagg(:exemplary_agg_name, [:attr1], :attr2))`. *generalizes argmin/max: returns the bc items per attr1 that are chosen by the exemplary
|
data/docs/getstarted.md
CHANGED
@@ -14,7 +14,7 @@ This installs four things:
|
|
14
14
|
|
15
15
|
* The `Bud` module, to embed Bloom code in Ruby.
|
16
16
|
* The `rebl` executable: an interactive shell for trying out Bloom.
|
17
|
-
* The `budplot` and `
|
17
|
+
* The `budplot`, `budvis`, and `budtimelines` executables: graphical tools for visualizing and debugging Bloom programs.
|
18
18
|
|
19
19
|
## First Blooms ##
|
20
20
|
|
data/lib/bud.rb
CHANGED
@@ -315,12 +315,12 @@ module Bud
|
|
315
315
|
|
316
316
|
# Check scan and merge_targets to see if any builtin_tables need to be added as well.
|
317
317
|
@scanners.each do |scs|
|
318
|
-
@app_tables
|
318
|
+
@app_tables.merge(scs.values.map {|s| s.collection})
|
319
319
|
end
|
320
320
|
@merge_targets.each do |mts| #mts == merge_targets at stratum
|
321
|
-
@app_tables
|
321
|
+
@app_tables.merge(mts)
|
322
322
|
end
|
323
|
-
@app_tables = @app_tables.
|
323
|
+
@app_tables = @app_tables.to_a
|
324
324
|
|
325
325
|
# for each stratum create a sorted list of push elements in topological order
|
326
326
|
@push_sorted_elems = []
|
@@ -352,18 +352,18 @@ module Bud
|
|
352
352
|
end
|
353
353
|
end
|
354
354
|
|
355
|
-
#
|
355
|
+
# Sanity check
|
356
356
|
@push_sorted_elems.each do |stratum_elems|
|
357
|
-
stratum_elems.each
|
358
|
-
se.check_wiring
|
359
|
-
end
|
357
|
+
stratum_elems.each {|se| se.check_wiring}
|
360
358
|
end
|
361
359
|
|
362
|
-
#
|
360
|
+
# Create sets of elements and collections to invalidate or rescan at the
|
361
|
+
# beginning of each tick
|
363
362
|
prepare_invalidation_scheme
|
364
363
|
|
365
|
-
# For all tables that are accessed (scanned) in a stratum higher than the
|
366
|
-
# a flag to track deltas accumulated in that
|
364
|
+
# For all tables that are accessed (scanned) in a stratum higher than the
|
365
|
+
# one they are updated in, set a flag to track deltas accumulated in that
|
366
|
+
# tick (see: collection.tick_delta)
|
367
367
|
stratum_accessed = {}
|
368
368
|
(@num_strata-1).downto(0) do |stratum|
|
369
369
|
@scanners[stratum].each_value do |s|
|
@@ -384,24 +384,38 @@ module Bud
|
|
384
384
|
end
|
385
385
|
end
|
386
386
|
|
387
|
-
# All collections (elements included) are semantically required to erase any
|
388
|
-
#
|
389
|
-
#
|
390
|
-
#
|
387
|
+
# All collections (elements included) are semantically required to erase any
|
388
|
+
# cached information at the start of a tick and start from a clean
|
389
|
+
# slate. prepare_invalidation_scheme prepares a just-in-time invalidation
|
390
|
+
# scheme that permits us to preserve data from one tick to the next, and to
|
391
|
+
# keep things in incremental mode unless there's a negation.
|
392
|
+
#
|
391
393
|
# This scheme solves the following constraints.
|
392
|
-
# 1. A full scan of an element's contents results in downstream elements getting full scans themselves (i.e no \
|
393
|
-
# deltas). This effect is transitive.
|
394
|
-
# 2. Invalidation of an element's cache results in rebuilding of the cache and a consequent fullscan. See next.
|
395
|
-
# 3. Invalidation of an element requires upstream elements to rescan their contents, or to transitively pass the
|
396
|
-
# request on further upstream. Any element that has a cache can rescan without passing on the request to higher
|
397
|
-
# levels.
|
398
394
|
#
|
399
|
-
#
|
400
|
-
#
|
401
|
-
#
|
402
|
-
#
|
403
|
-
#
|
404
|
-
#
|
395
|
+
# 1. A full scan of an element's contents results in downstream elements
|
396
|
+
# getting full scans themselves (i.e., no deltas). This effect is
|
397
|
+
# transitive.
|
398
|
+
# 2. Invalidation of an element's cache results in rebuilding of the cache and
|
399
|
+
# a consequent fullscan. See next.
|
400
|
+
# 3. Invalidation of an element requires upstream elements to rescan their
|
401
|
+
# contents, or to transitively pass the request on further upstream. Any
|
402
|
+
# element that has a cache can rescan without passing on the request to
|
403
|
+
# higher levels.
|
404
|
+
#
|
405
|
+
# This set of constraints is solved once during wiring, resulting in four data
|
406
|
+
# structures:
|
407
|
+
#
|
408
|
+
# @default_invalidate = Set of elements and tables to always invalidate at
|
409
|
+
# every tick.
|
410
|
+
#
|
411
|
+
# @default_rescan = Set of elements and tables to always scan fully in the
|
412
|
+
# first iteration of every tick.
|
413
|
+
#
|
414
|
+
# scanner[stratum].invalidate_set = Set of elements to additionally invalidate
|
415
|
+
# if the scanner's table is invalidated at
|
416
|
+
# run-time.
|
417
|
+
#
|
418
|
+
# scanner[stratum].rescan_set = Similar to above.
|
405
419
|
def prepare_invalidation_scheme
|
406
420
|
num_strata = @push_sorted_elems.size
|
407
421
|
if $BUD_SAFE
|
@@ -443,22 +457,26 @@ module Bud
|
|
443
457
|
|
444
458
|
num_strata.times do |stratum|
|
445
459
|
@push_sorted_elems[stratum].each do |elem|
|
446
|
-
if elem.rescan_at_tick
|
447
|
-
rescan << elem
|
448
|
-
end
|
460
|
+
rescan << elem if elem.rescan_at_tick
|
449
461
|
|
450
462
|
if elem.outputs.any?{|tab| not(tab.class <= PushElement) and nm_targets.member? tab.qualified_tabname.to_sym }
|
451
|
-
rescan
|
463
|
+
rescan.merge(elem.wired_by)
|
452
464
|
end
|
453
465
|
end
|
454
466
|
rescan_invalidate_tc(stratum, rescan, invalidate)
|
455
467
|
end
|
456
468
|
|
469
|
+
puts "(PRE) Default rescan: #{rescan.inspect}" if $BUD_DEBUG
|
470
|
+
puts "(PRE) Default inval: #{invalidate.inspect}" if $BUD_DEBUG
|
471
|
+
|
457
472
|
prune_rescan_invalidate(rescan, invalidate)
|
458
473
|
# transitive closure
|
459
474
|
@default_rescan = rescan.to_a
|
460
475
|
@default_invalidate = invalidate.to_a
|
461
476
|
|
477
|
+
puts "(POST) Default rescan: #{rescan.inspect}" if $BUD_DEBUG
|
478
|
+
puts "(POST) Default inval: #{invalidate.inspect}" if $BUD_DEBUG
|
479
|
+
|
462
480
|
# Now compute for each table that is to be scanned, the set of dependent
|
463
481
|
# tables and elements that will be invalidated if that table were to be
|
464
482
|
# invalidated at run time.
|
@@ -475,7 +493,8 @@ module Bud
|
|
475
493
|
invalidate = dflt_invalidate.clone
|
476
494
|
rescan_invalidate_tc(stratum, rescan, invalidate)
|
477
495
|
prune_rescan_invalidate(rescan, invalidate)
|
478
|
-
to_reset
|
496
|
+
to_reset.merge(rescan)
|
497
|
+
to_reset.merge(invalidate)
|
479
498
|
# Give the diffs (from default) to scanner; these are elements that are
|
480
499
|
# dependent on this scanner
|
481
500
|
diffscan = (rescan - dflt_rescan).find_all {|elem| elem.class <= PushElement}
|
@@ -953,7 +972,7 @@ module Bud
|
|
953
972
|
# One timestep of Bloom execution. This MUST be invoked from the EventMachine
|
954
973
|
# thread; it is not intended to be called directly by client code.
|
955
974
|
def tick_internal
|
956
|
-
puts "#{object_id}/#{port} : =============================================" if $BUD_DEBUG
|
975
|
+
puts "#{object_id}/#{port} : ============================================= (#{@budtime})" if $BUD_DEBUG
|
957
976
|
begin
|
958
977
|
starttime = Time.now if options[:metrics]
|
959
978
|
if options[:metrics] and not @endtime.nil?
|
@@ -979,7 +998,7 @@ module Bud
|
|
979
998
|
num_strata = @push_sorted_elems.size
|
980
999
|
# The following loop invalidates additional (non-default) elements and
|
981
1000
|
# tables that depend on the run-time invalidation state of a table.
|
982
|
-
# Loop once to set the flags
|
1001
|
+
# Loop once to set the flags.
|
983
1002
|
num_strata.times do |stratum|
|
984
1003
|
@scanners[stratum].each_value do |scanner|
|
985
1004
|
if scanner.rescan
|
@@ -1034,7 +1053,6 @@ module Bud
|
|
1034
1053
|
invoke_callbacks
|
1035
1054
|
@budtime += 1
|
1036
1055
|
@inbound.clear
|
1037
|
-
|
1038
1056
|
@reset_list.each {|e| e.invalidated = false; e.rescan = false}
|
1039
1057
|
|
1040
1058
|
ensure
|
data/lib/bud/aggs.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
1
3
|
module Bud
|
2
4
|
######## Agg definitions
|
3
5
|
class Agg #:nodoc: all
|
@@ -12,7 +14,7 @@ module Bud
|
|
12
14
|
# b. :keep tells the caller to save this input
|
13
15
|
# c. :replace tells the caller to keep this input alone
|
14
16
|
# d. :delete, [t1, t2, ...] tells the caller to delete the remaining tuples
|
15
|
-
# For
|
17
|
+
# For aggs that do not inherit from ArgExemplary, the 2nd part can simply be nil.
|
16
18
|
def trans(the_state, val)
|
17
19
|
return the_state, :ignore
|
18
20
|
end
|
@@ -22,16 +24,12 @@ module Bud
|
|
22
24
|
end
|
23
25
|
end
|
24
26
|
|
25
|
-
class Exemplary < Agg #:nodoc: all
|
26
|
-
end
|
27
|
-
|
28
27
|
# ArgExemplary aggs are used by argagg. Canonical examples are min/min (argmin/max)
|
29
28
|
# They must have a trivial final method and be monotonic, i.e. once a value v
|
30
|
-
# is discarded in favor of another, v can never be the final result
|
31
|
-
|
29
|
+
# is discarded in favor of another, v can never be the final result.
|
32
30
|
class ArgExemplary < Agg #:nodoc: all
|
33
31
|
def tie(the_state, val)
|
34
|
-
|
32
|
+
the_state == val
|
35
33
|
end
|
36
34
|
def final(the_state)
|
37
35
|
the_state
|
@@ -184,7 +182,7 @@ module Bud
|
|
184
182
|
return retval, nil
|
185
183
|
end
|
186
184
|
def final(the_state)
|
187
|
-
the_state[0]
|
185
|
+
the_state[0].to_f / the_state[1]
|
188
186
|
end
|
189
187
|
end
|
190
188
|
|
@@ -196,7 +194,7 @@ module Bud
|
|
196
194
|
|
197
195
|
class Accum < Agg #:nodoc: all
|
198
196
|
def init(x)
|
199
|
-
[x]
|
197
|
+
[x].to_set
|
200
198
|
end
|
201
199
|
def trans(the_state, val)
|
202
200
|
the_state << val
|
@@ -205,8 +203,7 @@ module Bud
|
|
205
203
|
end
|
206
204
|
|
207
205
|
# aggregate method to be used in Bud::BudCollection.group.
|
208
|
-
# accumulates all x inputs into
|
209
|
-
# in the resulting array is undefined.
|
206
|
+
# accumulates all x inputs into a set.
|
210
207
|
def accum(x)
|
211
208
|
[Accum.new, x]
|
212
209
|
end
|
data/lib/bud/bud_meta.rb
CHANGED
@@ -23,10 +23,12 @@ class BudMeta #:nodoc: all
|
|
23
23
|
# slot each rule into the stratum corresponding to its lhs pred (from stratum_map)
|
24
24
|
stratified_rules = Array.new(top_stratum + 2) { [] } # stratum -> [ rules ]
|
25
25
|
@bud_instance.t_rules.each do |rule|
|
26
|
-
if rule.op
|
26
|
+
if rule.op == '<='
|
27
27
|
# Deductive rules are assigned to strata based on the basic Datalog
|
28
28
|
# stratification algorithm
|
29
29
|
belongs_in = stratum_map[rule.lhs]
|
30
|
+
# If the rule body doesn't reference any collections, it won't be
|
31
|
+
# assigned a stratum, so just place it in stratum zero
|
30
32
|
belongs_in ||= 0
|
31
33
|
stratified_rules[belongs_in] << rule
|
32
34
|
else
|
@@ -112,18 +114,16 @@ class BudMeta #:nodoc: all
|
|
112
114
|
# a.b.c == s(:call, s1, :c, (:args))
|
113
115
|
# where s1 == s(:call, s2, :b, (:args))
|
114
116
|
# where s2 == s(:call, nil, :a, (:args))
|
115
|
-
|
116
117
|
tag, recv, name, args = pt
|
117
|
-
return nil unless tag == :call
|
118
|
+
return nil unless tag == :call and args.length == 1
|
118
119
|
|
119
120
|
if recv
|
120
121
|
qn = get_qual_name(recv)
|
121
122
|
return nil if qn.nil? or qn.size == 0
|
122
|
-
|
123
|
+
return "#{qn}.#{name}"
|
123
124
|
else
|
124
|
-
|
125
|
+
return name.to_s
|
125
126
|
end
|
126
|
-
qn
|
127
127
|
end
|
128
128
|
|
129
129
|
# Perform some basic sanity checks on the AST of a rule block. We expect a
|
@@ -156,9 +156,9 @@ class BudMeta #:nodoc: all
|
|
156
156
|
|
157
157
|
# Check that LHS references a named collection
|
158
158
|
lhs_name = get_qual_name(lhs)
|
159
|
-
return [n, "
|
159
|
+
return [n, "unexpected lhs format: #{lhs}"] if lhs_name.nil?
|
160
160
|
unless @bud_instance.tables.has_key? lhs_name.to_sym
|
161
|
-
return [n, "
|
161
|
+
return [n, "collection does not exist: '#{lhs_name}'"]
|
162
162
|
end
|
163
163
|
|
164
164
|
return [n, "illegal operator: '#{op}'"] unless [:<, :<=].include? op
|
@@ -194,21 +194,21 @@ class BudMeta #:nodoc: all
|
|
194
194
|
nodes = {}
|
195
195
|
bud.t_depends.each do |d|
|
196
196
|
#t_depends [:bud_instance, :rule_id, :lhs, :op, :body] => [:nm]
|
197
|
-
lhs = (nodes[d.lhs
|
197
|
+
lhs = (nodes[d.lhs] ||= Node.new(d.lhs, :init, 0, [], true, false, false, false))
|
198
198
|
lhs.in_lhs = true
|
199
|
-
body = (nodes[d.body
|
199
|
+
body = (nodes[d.body] ||= Node.new(d.body, :init, 0, [], false, true, false, false))
|
200
200
|
temporal = d.op != "<="
|
201
201
|
lhs.edges << Edge.new(body, d.op, d.nm, temporal)
|
202
202
|
body.in_body = true
|
203
203
|
end
|
204
204
|
|
205
|
-
nodes.
|
205
|
+
nodes.each_value {|n| calc_stratum(n, false, false, [n.name])}
|
206
206
|
# Normalize stratum numbers because they may not be 0-based or consecutive
|
207
207
|
remap = {}
|
208
208
|
# if the nodes stratum numbers are [2, 3, 2, 4], remap = {2 => 0, 3 => 1, 4 => 2}
|
209
|
-
nodes.values.map {|n| n.stratum}.uniq.sort.each_with_index
|
209
|
+
nodes.values.map {|n| n.stratum}.uniq.sort.each_with_index do |num, i|
|
210
210
|
remap[num] = i
|
211
|
-
|
211
|
+
end
|
212
212
|
stratum_map = {}
|
213
213
|
top_stratum = -1
|
214
214
|
nodes.each_pair do |name, n|
|
@@ -232,9 +232,9 @@ class BudMeta #:nodoc: all
|
|
232
232
|
node.status = :in_process
|
233
233
|
node.edges.each do |edge|
|
234
234
|
node.is_neg_head = edge.neg
|
235
|
-
next
|
235
|
+
next unless edge.op == "<="
|
236
236
|
body_stratum = calc_stratum(edge.to, (neg or edge.neg), (edge.temporal or temporal), path + [edge.to.name])
|
237
|
-
node.is_neg_head = false #reset for next edge
|
237
|
+
node.is_neg_head = false # reset for next edge
|
238
238
|
node.stratum = max(node.stratum, body_stratum + (edge.neg ? 1 : 0))
|
239
239
|
end
|
240
240
|
node.status = :done
|
@@ -253,15 +253,15 @@ class BudMeta #:nodoc: all
|
|
253
253
|
bud.t_provides.each do |p|
|
254
254
|
pred, input = p.interface, p.input
|
255
255
|
if input
|
256
|
-
unless preds_in_body.include? pred
|
256
|
+
unless preds_in_body.include? pred
|
257
257
|
# input interface is underspecified if not used in any rule body
|
258
258
|
bud.t_underspecified << [pred, true] # true indicates input mode
|
259
259
|
out.puts "Warning: input interface #{pred} not used"
|
260
260
|
end
|
261
261
|
else
|
262
|
-
unless preds_in_lhs.include? pred
|
262
|
+
unless preds_in_lhs.include? pred
|
263
263
|
# output interface underspecified if not in any rule's lhs
|
264
|
-
bud.t_underspecified << [pred, false] #false indicates output mode
|
264
|
+
bud.t_underspecified << [pred, false] # false indicates output mode
|
265
265
|
out.puts "Warning: output interface #{pred} not used"
|
266
266
|
end
|
267
267
|
end
|
data/lib/bud/collections.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'msgpack'
|
2
2
|
|
3
3
|
$struct_classes = {}
|
4
|
-
$EMPTY_HASH = {}
|
5
4
|
module Bud
|
6
5
|
########
|
7
6
|
#--
|
@@ -74,6 +73,10 @@ module Bud
|
|
74
73
|
@qualified_tabname ||= @bud_instance.toplevel? ? tabname : "#{@bud_instance.qualified_name}.#{tabname}".to_sym
|
75
74
|
end
|
76
75
|
|
76
|
+
def inspect
|
77
|
+
"#{self.class}:#{self.object_id.to_s(16)} [#{qualified_tabname}]"
|
78
|
+
end
|
79
|
+
|
77
80
|
# The user-specified schema might come in two forms: a hash of Array =>
|
78
81
|
# Array (key_cols => remaining columns), or simply an Array of columns (if
|
79
82
|
# no key_cols were specified). Return a pair: [list of (all) columns, list
|
@@ -102,10 +105,6 @@ module Bud
|
|
102
105
|
return [cols, key_cols]
|
103
106
|
end
|
104
107
|
|
105
|
-
def inspect
|
106
|
-
"#{self.class}:#{self.object_id.to_s(16)} [#{qualified_tabname}]"
|
107
|
-
end
|
108
|
-
|
109
108
|
# produces the schema in a format that is useful as the schema specification for another table
|
110
109
|
public
|
111
110
|
def schema
|
@@ -189,6 +188,8 @@ module Bud
|
|
189
188
|
def pro(the_name=tabname, the_schema=schema, &blk)
|
190
189
|
if @bud_instance.wiring?
|
191
190
|
pusher = to_push_elem(the_name, the_schema)
|
191
|
+
# If there is no code block evaluate, use the scanner directly
|
192
|
+
return pusher if blk.nil?
|
192
193
|
pusher_pro = pusher.pro(&blk)
|
193
194
|
pusher_pro.elem_name = the_name
|
194
195
|
pusher_pro.tabname = the_name
|
@@ -260,7 +261,7 @@ module Bud
|
|
260
261
|
|
261
262
|
public
|
262
263
|
def non_temporal_predecessors
|
263
|
-
@wired_by.
|
264
|
+
@wired_by.select {|elem| elem.outputs.include? self}
|
264
265
|
end
|
265
266
|
|
266
267
|
public
|
@@ -393,7 +394,7 @@ module Bud
|
|
393
394
|
|
394
395
|
private
|
395
396
|
def get_key_vals(t)
|
396
|
-
|
397
|
+
t.values_at(*@key_colnums)
|
397
398
|
end
|
398
399
|
|
399
400
|
public
|
@@ -567,7 +568,7 @@ module Bud
|
|
567
568
|
unless @delta.empty?
|
568
569
|
puts "#{qualified_tabname}.tick_delta delta --> storage (#{@delta.size} elems)" if $BUD_DEBUG
|
569
570
|
@storage.merge!(@delta)
|
570
|
-
@tick_delta
|
571
|
+
@tick_delta.concat(@delta.values) if accumulate_tick_deltas
|
571
572
|
@delta.clear
|
572
573
|
end
|
573
574
|
|
@@ -607,7 +608,7 @@ module Bud
|
|
607
608
|
end
|
608
609
|
unless @delta.empty?
|
609
610
|
@storage.merge!(@delta)
|
610
|
-
@tick_delta
|
611
|
+
@tick_delta.concat(@delta.values) if accumulate_tick_deltas
|
611
612
|
@delta.clear
|
612
613
|
end
|
613
614
|
unless @new_delta.empty?
|
@@ -704,14 +705,6 @@ module Bud
|
|
704
705
|
return to_push_elem.reduce(initial, &blk)
|
705
706
|
end
|
706
707
|
|
707
|
-
public
|
708
|
-
def pretty_print_instance_variables
|
709
|
-
# list of attributes (in order) to print when pretty_print is called.
|
710
|
-
important = ["@tabname", "@storage", "@delta", "@new_delta", "@pending"]
|
711
|
-
# everything except bud_instance
|
712
|
-
important + (self.instance_variables - important - ["@bud_instance"])
|
713
|
-
end
|
714
|
-
|
715
708
|
public
|
716
709
|
def uniquify_tabname # :nodoc: all
|
717
710
|
# just append current number of microseconds
|
@@ -747,7 +740,7 @@ module Bud
|
|
747
740
|
srcs = non_temporal_predecessors
|
748
741
|
if srcs.any? {|e| rescan.member? e}
|
749
742
|
invalidate << self
|
750
|
-
rescan
|
743
|
+
rescan.merge(srcs)
|
751
744
|
end
|
752
745
|
end
|
753
746
|
|
@@ -1145,7 +1138,7 @@ module Bud
|
|
1145
1138
|
# No cache to invalidate. Also, tables do not invalidate dependents,
|
1146
1139
|
# because their own state is not considered invalidated; that happens only
|
1147
1140
|
# if there were pending deletes at the beginning of a tick (see tick())
|
1148
|
-
puts "******** invalidate_cache called on BudTable"
|
1141
|
+
puts "******** invalidate_cache called on BudTable" if $BUD_DEBUG
|
1149
1142
|
end
|
1150
1143
|
|
1151
1144
|
public
|
@@ -1190,7 +1183,7 @@ module Bud
|
|
1190
1183
|
|
1191
1184
|
public
|
1192
1185
|
def each(&block)
|
1193
|
-
@expr.call.each
|
1186
|
+
@expr.call.each(&block)
|
1194
1187
|
end
|
1195
1188
|
|
1196
1189
|
public
|
@@ -1221,7 +1214,7 @@ module Bud
|
|
1221
1214
|
|
1222
1215
|
public
|
1223
1216
|
def each(&blk)
|
1224
|
-
each_raw
|
1217
|
+
each_raw(&blk)
|
1225
1218
|
end
|
1226
1219
|
end
|
1227
1220
|
end
|