bud 0.9.2 → 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/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
|