bud 0.9.0 → 0.9.1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +10 -1
- data/docs/cheat.md +3 -3
- data/examples/{README → README.md} +0 -0
- data/lib/bud/bud_meta.rb +21 -13
- data/lib/bud/collections.rb +123 -130
- data/lib/bud/executor/elements.rb +27 -52
- data/lib/bud/executor/group.rb +1 -1
- data/lib/bud/executor/join.rb +7 -12
- data/lib/bud/rewrite.rb +83 -53
- data/lib/bud/storage/dbm.rb +2 -2
- data/lib/bud/viz_util.rb +4 -2
- data/lib/bud.rb +21 -7
- metadata +27 -68
- data/docs/bust.md +0 -83
- data/examples/bust/README.md +0 -9
- data/examples/bust/bustclient-example.rb +0 -23
- data/examples/bust/bustinspector.html +0 -135
- data/examples/bust/bustserver-example.rb +0 -18
- data/lib/bud/bust/bust.rb +0 -137
- data/lib/bud/bust/client/idempotence.rb +0 -10
- data/lib/bud/bust/client/restclient.rb +0 -49
data/History.txt
CHANGED
@@ -1,4 +1,13 @@
|
|
1
|
-
== 0.9.
|
1
|
+
== 0.9.1 / 2012-04-10
|
2
|
+
|
3
|
+
* Reject attempts to insert a tuple into a collection with more fields than are
|
4
|
+
in the collection's schema
|
5
|
+
* Previous behavior was to ignore additional fields, but this was found to be
|
6
|
+
error-prone
|
7
|
+
* Remove builtin support for BUST (web services API); this avoids the need to
|
8
|
+
depend on the json, nestful and i18n gems.
|
9
|
+
|
10
|
+
== 0.9.0 / 2012-03-21
|
2
11
|
|
3
12
|
* Major performance enhancements
|
4
13
|
* Much, much faster: rewritten runtime that now uses a push-based dataflow
|
data/docs/cheat.md
CHANGED
@@ -295,14 +295,14 @@ Like `pairs`, but implicitly includes a block that projects down to the left ite
|
|
295
295
|
`rights(`*hash pairs*`)`:
|
296
296
|
Like `pairs`, but implicitly includes a block that projects down to the right item in each pair.
|
297
297
|
|
298
|
+
`outer(`*hash pairs*`)`:<br>
|
299
|
+
Left Outer Join. Like `pairs`, but items in the first collection will be produced nil-padded if they have no match in the second collection.
|
300
|
+
|
298
301
|
`flatten`:<br>
|
299
302
|
`flatten` is a bit like SQL's `SELECT *`: it produces a collection of concatenated objects, with a schema that is the concatenation of the schemas in tablelist (with duplicate names disambiguated). Useful for chaining to operators that expect input collections with schemas, e.g., `group`:
|
300
303
|
|
301
304
|
out <= (r * s).matches.flatten.group([:a], max(:b))
|
302
305
|
|
303
|
-
`outer(`*hash pairs*`)`:<br>
|
304
|
-
Left Outer Join. Like `pairs`, but items in the first collection will be produced nil-padded if they have no match in the second collection.
|
305
|
-
|
306
306
|
## Temp Collections ##
|
307
307
|
`temp`<br>
|
308
308
|
Temp collections are scratches defined within a `bloom` block:
|
File without changes
|
data/lib/bud/bud_meta.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'bud/rewrite'
|
2
|
-
require 'pp'
|
3
2
|
|
4
3
|
|
5
4
|
class BudMeta #:nodoc: all
|
@@ -16,9 +15,12 @@ class BudMeta #:nodoc: all
|
|
16
15
|
if @bud_instance.toplevel == @bud_instance
|
17
16
|
nodes, stratum_map, top_stratum = stratify_preds
|
18
17
|
|
19
|
-
# stratum_map = {fully qualified pred
|
18
|
+
# stratum_map = {fully qualified pred => stratum}. Copy stratum_map data
|
19
|
+
# into t_stratum format.
|
20
|
+
raise unless @bud_instance.t_stratum.to_a.empty?
|
21
|
+
@bud_instance.t_stratum <= stratum_map.to_a
|
20
22
|
|
21
|
-
#slot each rule into the stratum corresponding to its lhs pred (from stratum_map)
|
23
|
+
# slot each rule into the stratum corresponding to its lhs pred (from stratum_map)
|
22
24
|
stratified_rules = Array.new(top_stratum + 2) { [] } # stratum -> [ rules ]
|
23
25
|
@bud_instance.t_rules.each do |rule|
|
24
26
|
if rule.op.to_s == '<='
|
@@ -70,8 +72,11 @@ class BudMeta #:nodoc: all
|
|
70
72
|
pt = klass.__bloom_asts__[block_name]
|
71
73
|
return if pt.nil?
|
72
74
|
|
73
|
-
pt = Marshal.load(Marshal.dump(pt)) #deep
|
74
|
-
|
75
|
+
pt = Marshal.load(Marshal.dump(pt)) # deep copy because RuleRewriter mucks up pt
|
76
|
+
if @bud_instance.options[:dump_ast]
|
77
|
+
require 'pp'
|
78
|
+
pp pt
|
79
|
+
end
|
75
80
|
tmp_expander = TempExpander.new
|
76
81
|
pt = tmp_expander.process(pt)
|
77
82
|
tmp_expander.tmp_tables.each do |t|
|
@@ -104,9 +109,9 @@ class BudMeta #:nodoc: all
|
|
104
109
|
|
105
110
|
def get_qual_name(pt)
|
106
111
|
# expect to see a parse tree corresponding to a dotted name
|
107
|
-
# a.b.c == s(:call, s1,
|
108
|
-
# where s1 == s(:call, s2,
|
109
|
-
# where s2 == s(:call, nil
|
112
|
+
# a.b.c == s(:call, s1, :c, (:args))
|
113
|
+
# where s1 == s(:call, s2, :b, (:args))
|
114
|
+
# where s2 == s(:call, nil, :a, (:args))
|
110
115
|
|
111
116
|
tag, recv, name, args = pt
|
112
117
|
return nil unless tag == :call or args.length == 1
|
@@ -114,7 +119,7 @@ class BudMeta #:nodoc: all
|
|
114
119
|
if recv
|
115
120
|
qn = get_qual_name(recv)
|
116
121
|
return nil if qn.nil? or qn.size == 0
|
117
|
-
qn = qn
|
122
|
+
qn = "#{qn}.#{name}"
|
118
123
|
else
|
119
124
|
qn = name.to_s
|
120
125
|
end
|
@@ -147,11 +152,12 @@ class BudMeta #:nodoc: all
|
|
147
152
|
return pt unless n.sexp_type == :call and n.length == 4
|
148
153
|
|
149
154
|
# Rule format: call tag, lhs, op, rhs
|
150
|
-
|
155
|
+
_, lhs, op, rhs = n
|
151
156
|
|
152
157
|
# Check that LHS references a named collection
|
153
158
|
lhs_name = get_qual_name(lhs)
|
154
|
-
|
159
|
+
return [n, "Unexpected lhs format: #{lhs}"] if lhs.nil?
|
160
|
+
unless @bud_instance.tables.has_key? lhs_name.to_sym
|
155
161
|
return [n, "Collection does not exist: '#{lhs_name}'"]
|
156
162
|
end
|
157
163
|
|
@@ -242,19 +248,21 @@ class BudMeta #:nodoc: all
|
|
242
248
|
preds_in_body = nodes.select {|_, node| node.in_body}.map {|name, _| name}.to_set
|
243
249
|
|
244
250
|
bud = @bud_instance
|
251
|
+
out = bud.options[:stdout]
|
252
|
+
out ||= $stdout
|
245
253
|
bud.t_provides.each do |p|
|
246
254
|
pred, input = p.interface, p.input
|
247
255
|
if input
|
248
256
|
unless preds_in_body.include? pred.to_s
|
249
257
|
# input interface is underspecified if not used in any rule body
|
250
258
|
bud.t_underspecified << [pred, true] # true indicates input mode
|
251
|
-
puts "Warning: input interface #{pred} not used"
|
259
|
+
out.puts "Warning: input interface #{pred} not used"
|
252
260
|
end
|
253
261
|
else
|
254
262
|
unless preds_in_lhs.include? pred.to_s
|
255
263
|
# output interface underspecified if not in any rule's lhs
|
256
264
|
bud.t_underspecified << [pred, false] #false indicates output mode.
|
257
|
-
puts "Warning: output interface #{pred} not used"
|
265
|
+
out.puts "Warning: output interface #{pred} not used"
|
258
266
|
end
|
259
267
|
end
|
260
268
|
end
|
data/lib/bud/collections.rb
CHANGED
@@ -21,10 +21,9 @@ module Bud
|
|
21
21
|
attr_reader :cols, :key_cols # :nodoc: all
|
22
22
|
attr_reader :struct
|
23
23
|
attr_reader :storage, :delta, :new_delta, :pending, :tick_delta # :nodoc: all
|
24
|
-
|
25
|
-
attr_accessor :invalidated, :
|
24
|
+
attr_reader :wired_by, :to_delete
|
25
|
+
attr_accessor :invalidated, :rescan
|
26
26
|
attr_accessor :is_source
|
27
|
-
attr_accessor :wired_by
|
28
27
|
attr_accessor :accumulate_tick_deltas # updated in bud.do_wiring
|
29
28
|
|
30
29
|
def initialize(name, bud_instance, given_schema=nil, defer_schema=false) # :nodoc: all
|
@@ -50,6 +49,7 @@ module Bud
|
|
50
49
|
given_schema ||= {[:key]=>[:val]}
|
51
50
|
@given_schema = given_schema
|
52
51
|
@cols, @key_cols = BudCollection.parse_schema(given_schema)
|
52
|
+
|
53
53
|
# Check that no location specifiers appear in the schema. In the case of
|
54
54
|
# channels, the location specifier has already been stripped from the
|
55
55
|
# user-specified schema.
|
@@ -59,18 +59,19 @@ module Bud
|
|
59
59
|
end
|
60
60
|
end
|
61
61
|
|
62
|
-
|
62
|
+
@key_colnums = @key_cols.map {|k| @cols.index(k)}
|
63
|
+
|
64
|
+
if @cols.empty?
|
63
65
|
@cols = nil
|
64
66
|
else
|
65
67
|
@struct = ($struct_classes[@cols] ||= Struct.new(*@cols))
|
66
68
|
@structlen = @struct.members.length
|
67
69
|
end
|
68
|
-
@key_colnums = key_cols.map {|k| @cols.index(k)}
|
69
70
|
setup_accessors
|
70
71
|
end
|
71
72
|
|
72
73
|
def qualified_tabname
|
73
|
-
@qualified_tabname ||= @bud_instance.toplevel? ? tabname :
|
74
|
+
@qualified_tabname ||= @bud_instance.toplevel? ? tabname : "#{@bud_instance.qualified_name}.#{tabname}".to_sym
|
74
75
|
end
|
75
76
|
|
76
77
|
# The user-specified schema might come in two forms: a hash of Array =>
|
@@ -168,7 +169,7 @@ module Bud
|
|
168
169
|
# project the collection to its key attributes
|
169
170
|
public
|
170
171
|
def keys
|
171
|
-
self.pro{|t|
|
172
|
+
self.pro{|t| get_key_vals(t)}
|
172
173
|
end
|
173
174
|
|
174
175
|
# project the collection to its non-key attributes
|
@@ -181,33 +182,19 @@ module Bud
|
|
181
182
|
public
|
182
183
|
def inspected
|
183
184
|
self.pro{|t| [t.inspect]}
|
184
|
-
# how about when this is called outside wiring?
|
185
|
-
# [["#{@tabname}: [#{self.map{|t| "\n (#{t.map{|v| v.inspect}.join ", "})"}}]"]]
|
186
185
|
end
|
187
186
|
|
188
187
|
# projection
|
189
188
|
public
|
190
189
|
def pro(the_name=tabname, the_schema=schema, &blk)
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
public
|
199
|
-
def each_with_index(the_name=tabname, the_schema=schema, &blk)
|
200
|
-
toplevel = @bud_instance.toplevel
|
201
|
-
if not toplevel.done_wiring
|
202
|
-
proj = pro(the_name, the_schema)
|
203
|
-
elem = Bud::PushEachWithIndex.new('each_with_index' + object_id.to_s,
|
204
|
-
toplevel.this_rule_context, tabname)
|
205
|
-
elem.set_block(&blk)
|
206
|
-
proj.wire_to(elem)
|
207
|
-
toplevel.push_elems[[self.object_id, :each, blk]] = elem
|
208
|
-
elem
|
190
|
+
if @bud_instance.wiring?
|
191
|
+
pusher = to_push_elem(the_name, the_schema)
|
192
|
+
pusher_pro = pusher.pro(&blk)
|
193
|
+
pusher_pro.elem_name = the_name
|
194
|
+
pusher_pro.tabname = the_name
|
195
|
+
pusher_pro
|
209
196
|
else
|
210
|
-
|
197
|
+
@storage.map(&blk)
|
211
198
|
end
|
212
199
|
end
|
213
200
|
|
@@ -217,40 +204,42 @@ module Bud
|
|
217
204
|
# accum.
|
218
205
|
public
|
219
206
|
def flat_map(&blk)
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
207
|
+
if @bud_instance.wiring?
|
208
|
+
pusher = self.pro(&blk)
|
209
|
+
toplevel = @bud_instance.toplevel
|
210
|
+
elem = Bud::PushElement.new(tabname, toplevel.this_rule_context, tabname)
|
211
|
+
pusher.wire_to(elem)
|
212
|
+
f = Proc.new do |t|
|
213
|
+
t.each do |i|
|
214
|
+
elem.push_out(i, false)
|
215
|
+
end
|
216
|
+
nil
|
227
217
|
end
|
228
|
-
|
218
|
+
elem.set_block(&f)
|
219
|
+
toplevel.push_elems[[self.object_id, :flatten]] = elem
|
220
|
+
return elem
|
221
|
+
else
|
222
|
+
@storage.flat_map(&blk)
|
229
223
|
end
|
230
|
-
elem.set_block(&f)
|
231
|
-
toplevel.push_elems[[self.object_id, :flatten]] = elem
|
232
|
-
return elem
|
233
224
|
end
|
234
225
|
|
235
226
|
public
|
236
227
|
def sort(&blk)
|
237
|
-
|
238
|
-
|
228
|
+
if @bud_instance.wiring?
|
229
|
+
pusher = self.pro
|
230
|
+
pusher.sort("sort#{object_id}", @bud_instance, @cols, &blk)
|
231
|
+
else
|
232
|
+
@storage.sort
|
233
|
+
end
|
239
234
|
end
|
240
235
|
|
241
|
-
def rename(the_name, the_schema=nil)
|
236
|
+
def rename(the_name, the_schema=nil, &blk)
|
237
|
+
raise unless @bud_instance.wiring?
|
242
238
|
# a scratch with this name should have been defined during rewriting
|
243
|
-
raise
|
244
|
-
|
245
|
-
#retval.init_schema(the_schema)
|
246
|
-
retval
|
239
|
+
raise Bud::Error, "rename failed to define a scratch named #{the_name}" unless @bud_instance.respond_to? the_name
|
240
|
+
pro(the_name, the_schema, &blk)
|
247
241
|
end
|
248
242
|
|
249
|
-
# def to_enum
|
250
|
-
# pusher = self.pro
|
251
|
-
# pusher.to_enum
|
252
|
-
# end
|
253
|
-
|
254
243
|
# By default, all tuples in any rhs are in storage or delta. Tuples in
|
255
244
|
# new_delta will get transitioned to delta in the next iteration of the
|
256
245
|
# evaluator (but within the current time tick).
|
@@ -377,9 +366,9 @@ module Bud
|
|
377
366
|
end
|
378
367
|
|
379
368
|
private
|
380
|
-
def raise_pk_error(
|
369
|
+
def raise_pk_error(new, old)
|
381
370
|
key = get_key_vals(old)
|
382
|
-
raise Bud::KeyConstraintError, "key conflict inserting #{
|
371
|
+
raise Bud::KeyConstraintError, "key conflict inserting #{new.inspect} into \"#{tabname}\": existing tuple #{old.inspect}, key = #{key.inspect}"
|
383
372
|
end
|
384
373
|
|
385
374
|
private
|
@@ -396,7 +385,9 @@ module Bud
|
|
396
385
|
raise Bud::TypeError, "array or struct type expected in \"#{qualified_tabname}\": #{o.inspect}"
|
397
386
|
end
|
398
387
|
|
399
|
-
|
388
|
+
if o.length > @structlen
|
389
|
+
raise Bud::TypeError, "too many columns for \"#{qualified_tabname}\": #{o.inspect}"
|
390
|
+
end
|
400
391
|
return @struct.new(*o)
|
401
392
|
end
|
402
393
|
|
@@ -406,7 +397,7 @@ module Bud
|
|
406
397
|
end
|
407
398
|
|
408
399
|
public
|
409
|
-
def do_insert(
|
400
|
+
def do_insert(t, store)
|
410
401
|
if $BUD_DEBUG
|
411
402
|
storetype = case store.object_id
|
412
403
|
when @storage.object_id; "storage"
|
@@ -414,17 +405,22 @@ module Bud
|
|
414
405
|
when @delta.object_id; "delta"
|
415
406
|
when @new_delta.object_id; "new_delta"
|
416
407
|
end
|
417
|
-
puts "#{qualified_tabname}.#{storetype} ==> #{
|
408
|
+
puts "#{qualified_tabname}.#{storetype} ==> #{t}"
|
418
409
|
end
|
419
|
-
return if
|
420
|
-
|
421
|
-
key = get_key_vals(
|
410
|
+
return if t.nil? # silently ignore nils resulting from map predicates failing
|
411
|
+
t = prep_tuple(t)
|
412
|
+
key = get_key_vals(t)
|
413
|
+
merge_to_buf(store, key, t, store[key])
|
414
|
+
end
|
422
415
|
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
416
|
+
# Merge "tup" with key values "key" into "buf". "old" is an existing tuple
|
417
|
+
# with the same key columns as "tup" (if any such tuple exists).
|
418
|
+
private
|
419
|
+
def merge_to_buf(buf, key, tup, old)
|
420
|
+
if old.nil? # no matching tuple found
|
421
|
+
buf[key] = tup
|
422
|
+
elsif old != tup # ignore duplicates
|
423
|
+
raise_pk_error(tup, old)
|
428
424
|
end
|
429
425
|
end
|
430
426
|
|
@@ -487,9 +483,13 @@ module Bud
|
|
487
483
|
end
|
488
484
|
end
|
489
485
|
|
486
|
+
# This is used for two quite different purposes. If given a Bud collection
|
487
|
+
# or dataflow element as an input, we assume we're being called to wire up
|
488
|
+
# the push-based dataflow. If given an Enumerable consisting of Bud tuples,
|
489
|
+
# we assume we're being called to insert the tuples (e.g., to support direct
|
490
|
+
# insertion of tuples into Bud collections in a sync_do block).
|
490
491
|
public
|
491
492
|
def merge(o, buf=@delta) # :nodoc: all
|
492
|
-
toplevel = @bud_instance.toplevel
|
493
493
|
if o.class <= Bud::PushElement
|
494
494
|
add_merge_target
|
495
495
|
deduce_schema(o) if @cols.nil?
|
@@ -498,7 +498,7 @@ module Bud
|
|
498
498
|
add_merge_target
|
499
499
|
deduce_schema(o) if @cols.nil?
|
500
500
|
o.pro.wire_to self
|
501
|
-
elsif o.class <= Proc
|
501
|
+
elsif o.class <= Proc
|
502
502
|
add_merge_target
|
503
503
|
tbl = register_coll_expr(o)
|
504
504
|
tbl.pro.wire_to self
|
@@ -510,15 +510,13 @@ module Bud
|
|
510
510
|
o.each {|i| do_insert(i, buf)}
|
511
511
|
end
|
512
512
|
end
|
513
|
-
return self
|
514
513
|
end
|
515
514
|
|
516
515
|
def register_coll_expr(expr)
|
517
516
|
coll_name = "expr_#{expr.object_id}"
|
518
517
|
cols = (1..@cols.length).map{|i| "c#{i}".to_sym} unless @cols.nil?
|
519
518
|
@bud_instance.coll_expr(coll_name.to_sym, expr, cols)
|
520
|
-
|
521
|
-
coll
|
519
|
+
@bud_instance.send(coll_name)
|
522
520
|
end
|
523
521
|
|
524
522
|
public
|
@@ -530,26 +528,12 @@ module Bud
|
|
530
528
|
# buffer items to be merged atomically at end of this timestep
|
531
529
|
public
|
532
530
|
def pending_merge(o) # :nodoc: all
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
o.
|
537
|
-
|
538
|
-
add_merge_target
|
539
|
-
o.pro.wire_to_pending self
|
540
|
-
elsif o.class <= Proc and toplevel.done_bootstrap and not toplevel.done_wiring
|
541
|
-
add_merge_target
|
542
|
-
tbl = register_coll_expr(o) unless o.nil?
|
543
|
-
tbl.pro.wire_to_pending self
|
544
|
-
else
|
545
|
-
unless o.nil?
|
546
|
-
o = o.uniq.compact if o.respond_to?(:uniq)
|
547
|
-
check_enumerable(o)
|
548
|
-
establish_schema(o) if @cols.nil?
|
549
|
-
o.each{|i| self.do_insert(i, @pending)}
|
550
|
-
end
|
531
|
+
unless o.nil?
|
532
|
+
o = o.uniq.compact if o.respond_to?(:uniq)
|
533
|
+
check_enumerable(o)
|
534
|
+
establish_schema(o) if @cols.nil?
|
535
|
+
o.each{|i| self.do_insert(i, @pending)}
|
551
536
|
end
|
552
|
-
return self
|
553
537
|
end
|
554
538
|
|
555
539
|
public
|
@@ -557,7 +541,19 @@ module Bud
|
|
557
541
|
|
558
542
|
public
|
559
543
|
superator "<+" do |o|
|
560
|
-
|
544
|
+
if o.class <= Bud::PushElement
|
545
|
+
add_merge_target
|
546
|
+
o.wire_to(self, :pending)
|
547
|
+
elsif o.class <= Bud::BudCollection
|
548
|
+
add_merge_target
|
549
|
+
o.pro.wire_to(self, :pending)
|
550
|
+
elsif o.class <= Proc
|
551
|
+
add_merge_target
|
552
|
+
tbl = register_coll_expr(o)
|
553
|
+
tbl.pro.wire_to(self, :pending)
|
554
|
+
else
|
555
|
+
pending_merge(o)
|
556
|
+
end
|
561
557
|
end
|
562
558
|
|
563
559
|
def tick
|
@@ -578,15 +574,10 @@ module Bud
|
|
578
574
|
unless @new_delta.empty?
|
579
575
|
puts "#{qualified_tabname}.tick_delta new_delta --> delta (#{@new_delta.size} elems)" if $BUD_DEBUG
|
580
576
|
|
581
|
-
#
|
582
|
-
#
|
583
|
-
@new_delta.each_pair do |
|
584
|
-
|
585
|
-
if sv.nil?
|
586
|
-
@delta[k] = v
|
587
|
-
else
|
588
|
-
raise_pk_error(v, sv) unless v == sv
|
589
|
-
end
|
577
|
+
# NB: key conflicts between different new_delta tuples are detected in
|
578
|
+
# do_insert().
|
579
|
+
@new_delta.each_pair do |key, tup|
|
580
|
+
merge_to_buf(@delta, key, tup, @storage[key])
|
590
581
|
end
|
591
582
|
@new_delta.clear
|
592
583
|
return !(@delta.empty?)
|
@@ -633,8 +624,10 @@ module Bud
|
|
633
624
|
this_stratum = toplevel.this_stratum
|
634
625
|
oid = self.object_id
|
635
626
|
unless toplevel.scanners[this_stratum][[oid, the_name]]
|
636
|
-
|
637
|
-
|
627
|
+
scanner = Bud::ScannerElement.new(the_name, @bud_instance,
|
628
|
+
self, the_schema)
|
629
|
+
toplevel.scanners[this_stratum][[oid, the_name]] = scanner
|
630
|
+
toplevel.push_sources[this_stratum][[oid, the_name]] = scanner
|
638
631
|
end
|
639
632
|
return toplevel.scanners[this_stratum][[oid, the_name]]
|
640
633
|
end
|
@@ -709,11 +702,8 @@ module Bud
|
|
709
702
|
col.class <= Symbol ? self.send(col) : col
|
710
703
|
end
|
711
704
|
|
712
|
-
# alias reduce inject
|
713
705
|
def reduce(initial, &blk)
|
714
|
-
|
715
|
-
red_elem = elem1.reduce(initial, &blk)
|
716
|
-
return red_elem
|
706
|
+
return to_push_elem.reduce(initial, &blk)
|
717
707
|
end
|
718
708
|
|
719
709
|
public
|
@@ -867,17 +857,18 @@ module Bud
|
|
867
857
|
public
|
868
858
|
def flush # :nodoc: all
|
869
859
|
toplevel = @bud_instance.toplevel
|
870
|
-
ip = toplevel.ip
|
871
|
-
port = toplevel.port
|
872
860
|
@pending.each_value do |t|
|
873
861
|
if @is_loopback
|
862
|
+
ip = toplevel.ip
|
863
|
+
port = toplevel.port
|
874
864
|
the_locspec = [ip, port]
|
875
865
|
else
|
876
866
|
the_locspec = split_locspec(t, @locspec_idx)
|
877
867
|
raise Bud::Error, "'#{t[@locspec_idx]}', channel '#{@tabname}'" if the_locspec[0].nil? or the_locspec[1].nil? or the_locspec[0] == '' or the_locspec[1] == ''
|
878
868
|
end
|
879
869
|
puts "channel #{qualified_tabname}.send: #{t}" if $BUD_DEBUG
|
880
|
-
toplevel.dsock.send_datagram([qualified_tabname.to_s, t].to_msgpack,
|
870
|
+
toplevel.dsock.send_datagram([qualified_tabname.to_s, t].to_msgpack,
|
871
|
+
the_locspec[0], the_locspec[1])
|
881
872
|
end
|
882
873
|
@pending.clear
|
883
874
|
end
|
@@ -903,7 +894,12 @@ module Bud
|
|
903
894
|
|
904
895
|
superator "<~" do |o|
|
905
896
|
if o.class <= Bud::PushElement
|
906
|
-
o.
|
897
|
+
o.wire_to(self, :pending)
|
898
|
+
elsif o.class <= Bud::BudCollection
|
899
|
+
o.pro.wire_to(self, :pending)
|
900
|
+
elsif o.class <= Proc
|
901
|
+
tbl = register_coll_expr(o)
|
902
|
+
tbl.pro.wire_to(self, :pending)
|
907
903
|
else
|
908
904
|
pending_merge(o)
|
909
905
|
end
|
@@ -1001,7 +997,12 @@ module Bud
|
|
1001
997
|
|
1002
998
|
superator "<~" do |o|
|
1003
999
|
if o.class <= Bud::PushElement
|
1004
|
-
o.
|
1000
|
+
o.wire_to(self, :pending)
|
1001
|
+
elsif o.class <= Bud::BudCollection
|
1002
|
+
o.pro.wire_to(self, :pending)
|
1003
|
+
elsif o.class <= Proc
|
1004
|
+
tbl = register_coll_expr(o)
|
1005
|
+
tbl.pro.wire_to(self, :pending)
|
1005
1006
|
else
|
1006
1007
|
pending_merge(o)
|
1007
1008
|
end
|
@@ -1072,27 +1073,22 @@ module Bud
|
|
1072
1073
|
@tick_delta.clear
|
1073
1074
|
deleted = nil
|
1074
1075
|
@to_delete.each do |tuple|
|
1075
|
-
keycols =
|
1076
|
+
keycols = get_key_vals(tuple)
|
1076
1077
|
if @storage[keycols] == tuple
|
1077
1078
|
v = @storage.delete keycols
|
1078
1079
|
deleted ||= v
|
1079
1080
|
end
|
1080
1081
|
end
|
1081
1082
|
@to_delete_by_key.each do |tuple|
|
1082
|
-
v = @storage.delete
|
1083
|
+
v = @storage.delete(get_key_vals(tuple))
|
1083
1084
|
deleted ||= v
|
1084
1085
|
end
|
1085
1086
|
|
1086
1087
|
@invalidated = (not deleted.nil?)
|
1087
1088
|
puts "table #{qualified_tabname} invalidated" if $BUD_DEBUG and @invalidated
|
1088
1089
|
|
1089
|
-
@pending.each do |
|
1090
|
-
|
1091
|
-
if old.nil?
|
1092
|
-
@delta[keycols] = tuple
|
1093
|
-
else
|
1094
|
-
raise_pk_error(tuple, old) unless tuple == old
|
1095
|
-
end
|
1090
|
+
@pending.each do |key, tup|
|
1091
|
+
merge_to_buf(@delta, key, tup, @storage[key])
|
1096
1092
|
end
|
1097
1093
|
@to_delete = []
|
1098
1094
|
@to_delete_by_key = []
|
@@ -1100,21 +1096,20 @@ module Bud
|
|
1100
1096
|
end
|
1101
1097
|
|
1102
1098
|
def invalidated=(val)
|
1103
|
-
raise "
|
1099
|
+
raise Bud::Error, "internal error: must not set invalidate on tables"
|
1104
1100
|
end
|
1105
1101
|
|
1106
1102
|
def pending_delete(o)
|
1107
|
-
toplevel = @bud_instance.toplevel
|
1108
1103
|
if o.class <= Bud::PushElement
|
1109
1104
|
add_merge_target
|
1110
|
-
o.
|
1105
|
+
o.wire_to(self, :delete)
|
1111
1106
|
elsif o.class <= Bud::BudCollection
|
1112
1107
|
add_merge_target
|
1113
|
-
o.pro.
|
1114
|
-
elsif o.class <= Proc
|
1108
|
+
o.pro.wire_to(self, :delete)
|
1109
|
+
elsif o.class <= Proc
|
1115
1110
|
add_merge_target
|
1116
1111
|
tbl = register_coll_expr(o)
|
1117
|
-
tbl.pro.
|
1112
|
+
tbl.pro.wire_to(self, :delete)
|
1118
1113
|
else
|
1119
1114
|
unless o.nil?
|
1120
1115
|
o = o.uniq.compact if o.respond_to?(:uniq)
|
@@ -1130,14 +1125,13 @@ module Bud
|
|
1130
1125
|
|
1131
1126
|
public
|
1132
1127
|
def pending_delete_keys(o)
|
1133
|
-
toplevel = @bud_instance.toplevel
|
1134
1128
|
if o.class <= Bud::PushElement
|
1135
|
-
o.
|
1129
|
+
o.wire_to(self, :delete_by_key)
|
1136
1130
|
elsif o.class <= Bud::BudCollection
|
1137
|
-
o.pro.
|
1138
|
-
elsif o.class <= Proc
|
1131
|
+
o.pro.wire_to(self, :delete_by_key)
|
1132
|
+
elsif o.class <= Proc
|
1139
1133
|
tbl = register_coll_expr(o)
|
1140
|
-
tbl.pro.
|
1134
|
+
tbl.pro.wire_to(self, :delete_by_key)
|
1141
1135
|
else
|
1142
1136
|
unless o.nil?
|
1143
1137
|
o = o.uniq.compact if o.respond_to?(:uniq)
|
@@ -1146,7 +1140,6 @@ module Bud
|
|
1146
1140
|
o.each{|i| @to_delete_by_key << prep_tuple(i)}
|
1147
1141
|
end
|
1148
1142
|
end
|
1149
|
-
o
|
1150
1143
|
end
|
1151
1144
|
|
1152
1145
|
public
|