bud 0.1.0.pre1 → 0.9.0
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 +23 -0
 - data/{README → README.md} +6 -2
 - data/docs/cheat.md +1 -8
 - data/docs/intro.md +1 -1
 - data/lib/bud/aggs.rb +16 -16
 - data/lib/bud/bud_meta.rb +8 -15
 - data/lib/bud/collections.rb +85 -172
 - data/lib/bud/errors.rb +5 -1
 - data/lib/bud/executor/elements.rb +133 -118
 - data/lib/bud/executor/group.rb +6 -6
 - data/lib/bud/executor/join.rb +25 -22
 - data/lib/bud/metrics.rb +1 -1
 - data/lib/bud/monkeypatch.rb +18 -29
 - data/lib/bud/rebl.rb +5 -4
 - data/lib/bud/rewrite.rb +21 -160
 - data/lib/bud/source.rb +5 -5
 - data/lib/bud/state.rb +13 -12
 - data/lib/bud/storage/dbm.rb +13 -23
 - data/lib/bud/storage/zookeeper.rb +0 -4
 - data/lib/bud.rb +184 -162
 - metadata +144 -216
 - data/docs/deploy.md +0 -96
 - data/lib/bud/deploy/countatomicdelivery.rb +0 -38
 - data/lib/bud/joins.rb +0 -526
 
    
        data/lib/bud/collections.rb
    CHANGED
    
    | 
         @@ -17,7 +17,7 @@ module Bud 
     | 
|
| 
       17 
17 
     | 
    
         
             
              class BudCollection
         
     | 
| 
       18 
18 
     | 
    
         
             
                include Enumerable
         
     | 
| 
       19 
19 
     | 
    
         | 
| 
       20 
     | 
    
         
            -
                attr_accessor :bud_instance, : 
     | 
| 
      
 20 
     | 
    
         
            +
                attr_accessor :bud_instance, :tabname  # :nodoc: all
         
     | 
| 
       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
         
     | 
| 
         @@ -25,6 +25,7 @@ module Bud 
     | 
|
| 
       25 
25 
     | 
    
         
             
                attr_accessor :invalidated, :to_delete, :rescan
         
     | 
| 
       26 
26 
     | 
    
         
             
                attr_accessor :is_source
         
     | 
| 
       27 
27 
     | 
    
         
             
                attr_accessor :wired_by
         
     | 
| 
      
 28 
     | 
    
         
            +
                attr_accessor :accumulate_tick_deltas # updated in bud.do_wiring
         
     | 
| 
       28 
29 
     | 
    
         | 
| 
       29 
30 
     | 
    
         
             
                def initialize(name, bud_instance, given_schema=nil, defer_schema=false) # :nodoc: all
         
     | 
| 
       30 
31 
     | 
    
         
             
                  @tabname = name
         
     | 
| 
         @@ -32,6 +33,7 @@ module Bud 
     | 
|
| 
       32 
33 
     | 
    
         
             
                  @invalidated = true
         
     | 
| 
       33 
34 
     | 
    
         
             
                  @is_source = true # unless it shows up on the lhs of some rule
         
     | 
| 
       34 
35 
     | 
    
         
             
                  @wired_by = []
         
     | 
| 
      
 36 
     | 
    
         
            +
                  @accumulate_tick_deltas = false
         
     | 
| 
       35 
37 
     | 
    
         
             
                  init_schema(given_schema) unless given_schema.nil? and defer_schema
         
     | 
| 
       36 
38 
     | 
    
         
             
                  init_buffers
         
     | 
| 
       37 
39 
     | 
    
         
             
                end
         
     | 
| 
         @@ -46,8 +48,6 @@ module Bud 
     | 
|
| 
       46 
48 
     | 
    
         
             
                public
         
     | 
| 
       47 
49 
     | 
    
         
             
                def init_schema(given_schema)
         
     | 
| 
       48 
50 
     | 
    
         
             
                  given_schema ||= {[:key]=>[:val]}
         
     | 
| 
       49 
     | 
    
         
            -
             
     | 
| 
       50 
     | 
    
         
            -
             
     | 
| 
       51 
51 
     | 
    
         
             
                  @given_schema = given_schema
         
     | 
| 
       52 
52 
     | 
    
         
             
                  @cols, @key_cols = BudCollection.parse_schema(given_schema)
         
     | 
| 
       53 
53 
     | 
    
         
             
                  # Check that no location specifiers appear in the schema. In the case of
         
     | 
| 
         @@ -91,7 +91,7 @@ module Bud 
     | 
|
| 
       91 
91 
     | 
    
         
             
                  cols = key_cols + val_cols
         
     | 
| 
       92 
92 
     | 
    
         
             
                  cols.each do |c|
         
     | 
| 
       93 
93 
     | 
    
         
             
                    if c.class != Symbol
         
     | 
| 
       94 
     | 
    
         
            -
                      raise Bud::Error, " 
     | 
| 
      
 94 
     | 
    
         
            +
                      raise Bud::Error, "invalid column name \"#{c}\", type \"#{c.class}\""
         
     | 
| 
       95 
95 
     | 
    
         
             
                    end
         
     | 
| 
       96 
96 
     | 
    
         
             
                  end
         
     | 
| 
       97 
97 
     | 
    
         
             
                  if cols.uniq.length < cols.length
         
     | 
| 
         @@ -105,11 +105,6 @@ module Bud 
     | 
|
| 
       105 
105 
     | 
    
         
             
                  "#{self.class}:#{self.object_id.to_s(16)} [#{qualified_tabname}]"
         
     | 
| 
       106 
106 
     | 
    
         
             
                end
         
     | 
| 
       107 
107 
     | 
    
         | 
| 
       108 
     | 
    
         
            -
                public
         
     | 
| 
       109 
     | 
    
         
            -
                def clone_empty #:nodoc: all
         
     | 
| 
       110 
     | 
    
         
            -
                  self.class.new(tabname, bud_instance, @given_schema)
         
     | 
| 
       111 
     | 
    
         
            -
                end
         
     | 
| 
       112 
     | 
    
         
            -
             
     | 
| 
       113 
108 
     | 
    
         
             
                # produces the schema in a format that is useful as the schema specification for another table
         
     | 
| 
       114 
109 
     | 
    
         
             
                public
         
     | 
| 
       115 
110 
     | 
    
         
             
                def schema
         
     | 
| 
         @@ -140,24 +135,14 @@ module Bud 
     | 
|
| 
       140 
135 
     | 
    
         
             
                  # set up schema accessors, which are class methods
         
     | 
| 
       141 
136 
     | 
    
         
             
                  @cols_access = Module.new do
         
     | 
| 
       142 
137 
     | 
    
         
             
                    sc.each_with_index do |c, i|
         
     | 
| 
       143 
     | 
    
         
            -
                       
     | 
| 
      
 138 
     | 
    
         
            +
                      define_method c do
         
     | 
| 
       144 
139 
     | 
    
         
             
                        [@tabname, i, c]
         
     | 
| 
       145 
140 
     | 
    
         
             
                      end
         
     | 
| 
       146 
141 
     | 
    
         
             
                    end
         
     | 
| 
       147 
142 
     | 
    
         
             
                  end
         
     | 
| 
       148 
143 
     | 
    
         
             
                  self.extend @cols_access
         
     | 
| 
       149 
     | 
    
         
            -
             
     | 
| 
       150 
     | 
    
         
            -
                  # now set up a Module for tuple accessors, which are instance methods
         
     | 
| 
       151 
     | 
    
         
            -
                  @tupaccess = Module.new do
         
     | 
| 
       152 
     | 
    
         
            -
                    sc.each_with_index do |colname, offset|
         
     | 
| 
       153 
     | 
    
         
            -
                      define_method colname do
         
     | 
| 
       154 
     | 
    
         
            -
                        self[offset]
         
     | 
| 
       155 
     | 
    
         
            -
                      end
         
     | 
| 
       156 
     | 
    
         
            -
                    end
         
     | 
| 
       157 
     | 
    
         
            -
                  end
         
     | 
| 
       158 
144 
     | 
    
         
             
                end
         
     | 
| 
       159 
145 
     | 
    
         | 
| 
       160 
     | 
    
         
            -
             
     | 
| 
       161 
146 
     | 
    
         
             
                private
         
     | 
| 
       162 
147 
     | 
    
         
             
                def name_reserved?(colname)
         
     | 
| 
       163 
148 
     | 
    
         
             
                  reserved = eval "defined?(#{colname})"
         
     | 
| 
         @@ -174,12 +159,6 @@ module Bud 
     | 
|
| 
       174 
159 
     | 
    
         
             
                  return true
         
     | 
| 
       175 
160 
     | 
    
         
             
                end
         
     | 
| 
       176 
161 
     | 
    
         | 
| 
       177 
     | 
    
         
            -
                # define methods to access tuple attributes by column name
         
     | 
| 
       178 
     | 
    
         
            -
                public
         
     | 
| 
       179 
     | 
    
         
            -
                def tuple_accessors(tup)
         
     | 
| 
       180 
     | 
    
         
            -
                  tup #  XXX remove tuple_acessors everywhere.
         
     | 
| 
       181 
     | 
    
         
            -
                end
         
     | 
| 
       182 
     | 
    
         
            -
             
     | 
| 
       183 
162 
     | 
    
         
             
                # generate a tuple with the schema of this collection and nil values in each attribute
         
     | 
| 
       184 
163 
     | 
    
         
             
                public
         
     | 
| 
       185 
164 
     | 
    
         
             
                def null_tuple
         
     | 
| 
         @@ -208,7 +187,7 @@ module Bud 
     | 
|
| 
       208 
187 
     | 
    
         | 
| 
       209 
188 
     | 
    
         
             
                # projection
         
     | 
| 
       210 
189 
     | 
    
         
             
                public
         
     | 
| 
       211 
     | 
    
         
            -
                def pro(the_name 
     | 
| 
      
 190 
     | 
    
         
            +
                def pro(the_name=tabname, the_schema=schema, &blk)
         
     | 
| 
       212 
191 
     | 
    
         
             
                  pusher = to_push_elem(the_name, the_schema)
         
     | 
| 
       213 
192 
     | 
    
         
             
                  pusher_pro = pusher.pro(&blk)
         
     | 
| 
       214 
193 
     | 
    
         
             
                  pusher_pro.elem_name = the_name
         
     | 
| 
         @@ -217,45 +196,46 @@ module Bud 
     | 
|
| 
       217 
196 
     | 
    
         
             
                end
         
     | 
| 
       218 
197 
     | 
    
         | 
| 
       219 
198 
     | 
    
         
             
                public
         
     | 
| 
       220 
     | 
    
         
            -
                def each_with_index(the_name 
     | 
| 
      
 199 
     | 
    
         
            +
                def each_with_index(the_name=tabname, the_schema=schema, &blk)
         
     | 
| 
       221 
200 
     | 
    
         
             
                  toplevel = @bud_instance.toplevel
         
     | 
| 
       222 
201 
     | 
    
         
             
                  if not toplevel.done_wiring
         
     | 
| 
       223 
202 
     | 
    
         
             
                    proj = pro(the_name, the_schema)
         
     | 
| 
       224 
     | 
    
         
            -
                    elem = Bud::PushEachWithIndex.new('each_with_index' + object_id.to_s, 
     | 
| 
      
 203 
     | 
    
         
            +
                    elem = Bud::PushEachWithIndex.new('each_with_index' + object_id.to_s,
         
     | 
| 
      
 204 
     | 
    
         
            +
                                                      toplevel.this_rule_context, tabname)
         
     | 
| 
       225 
205 
     | 
    
         
             
                    elem.set_block(&blk)
         
     | 
| 
       226 
206 
     | 
    
         
             
                    proj.wire_to(elem)
         
     | 
| 
       227 
     | 
    
         
            -
                    toplevel.push_elems[[self.object_id 
     | 
| 
      
 207 
     | 
    
         
            +
                    toplevel.push_elems[[self.object_id, :each, blk]] = elem
         
     | 
| 
       228 
208 
     | 
    
         
             
                    elem
         
     | 
| 
       229 
209 
     | 
    
         
             
                  else
         
     | 
| 
       230 
210 
     | 
    
         
             
                     storage.each_with_index
         
     | 
| 
       231 
211 
     | 
    
         
             
                  end
         
     | 
| 
       232 
212 
     | 
    
         
             
                end
         
     | 
| 
       233 
213 
     | 
    
         | 
| 
       234 
     | 
    
         
            -
             
     | 
| 
       235 
     | 
    
         
            -
                #  
     | 
| 
       236 
     | 
    
         
            -
                #  
     | 
| 
       237 
     | 
    
         
            -
                #  
     | 
| 
      
 214 
     | 
    
         
            +
                # ruby 1.9 defines flat_map to return "a new array with the concatenated
         
     | 
| 
      
 215 
     | 
    
         
            +
                # results of running <em>block</em> once for every element". So we wire the
         
     | 
| 
      
 216 
     | 
    
         
            +
                # input to a pro(&blk), and wire the output of that pro to a group that does
         
     | 
| 
      
 217 
     | 
    
         
            +
                # accum.
         
     | 
| 
       238 
218 
     | 
    
         
             
                public
         
     | 
| 
       239 
219 
     | 
    
         
             
                def flat_map(&blk)
         
     | 
| 
       240 
220 
     | 
    
         
             
                  pusher = self.pro(&blk)
         
     | 
| 
       241 
221 
     | 
    
         
             
                  toplevel = @bud_instance.toplevel
         
     | 
| 
       242 
222 
     | 
    
         
             
                  elem = Bud::PushElement.new(tabname, toplevel.this_rule_context, tabname)
         
     | 
| 
       243 
223 
     | 
    
         
             
                  pusher.wire_to(elem)
         
     | 
| 
       244 
     | 
    
         
            -
                  f = Proc.new do |t| 
     | 
| 
       245 
     | 
    
         
            -
                    t.each do |i| 
     | 
| 
       246 
     | 
    
         
            -
                      elem.push_out(i,false)
         
     | 
| 
      
 224 
     | 
    
         
            +
                  f = Proc.new do |t|
         
     | 
| 
      
 225 
     | 
    
         
            +
                    t.each do |i|
         
     | 
| 
      
 226 
     | 
    
         
            +
                      elem.push_out(i, false)
         
     | 
| 
       247 
227 
     | 
    
         
             
                    end
         
     | 
| 
       248 
228 
     | 
    
         
             
                    nil
         
     | 
| 
       249 
229 
     | 
    
         
             
                  end
         
     | 
| 
       250 
230 
     | 
    
         
             
                  elem.set_block(&f)
         
     | 
| 
       251 
     | 
    
         
            -
                  toplevel.push_elems[[self.object_id 
     | 
| 
      
 231 
     | 
    
         
            +
                  toplevel.push_elems[[self.object_id, :flatten]] = elem
         
     | 
| 
       252 
232 
     | 
    
         
             
                  return elem
         
     | 
| 
       253 
233 
     | 
    
         
             
                end
         
     | 
| 
       254 
234 
     | 
    
         | 
| 
       255 
     | 
    
         
            -
                public 
     | 
| 
      
 235 
     | 
    
         
            +
                public
         
     | 
| 
       256 
236 
     | 
    
         
             
                def sort(&blk)
         
     | 
| 
       257 
237 
     | 
    
         
             
                  pusher = self.pro
         
     | 
| 
       258 
     | 
    
         
            -
                  pusher.sort( 
     | 
| 
      
 238 
     | 
    
         
            +
                  pusher.sort("sort#{object_id}", @bud_instance, @cols, &blk)
         
     | 
| 
       259 
239 
     | 
    
         
             
                end
         
     | 
| 
       260 
240 
     | 
    
         | 
| 
       261 
241 
     | 
    
         
             
                def rename(the_name, the_schema=nil)
         
     | 
| 
         @@ -300,7 +280,6 @@ module Bud 
     | 
|
| 
       300 
280 
     | 
    
         
             
                  rule_num = bud_instance.this_rule
         
     | 
| 
       301 
281 
     | 
    
         
             
                  addr = nil
         
     | 
| 
       302 
282 
     | 
    
         
             
                  addr = bud_instance.ip_port unless bud_instance.port.nil?
         
     | 
| 
       303 
     | 
    
         
            -
                  rule_txt = nil
         
     | 
| 
       304 
283 
     | 
    
         
             
                  bud_instance.metrics[:collections] ||= {}
         
     | 
| 
       305 
284 
     | 
    
         
             
                  bud_instance.metrics[:collections][{:addr=>addr, :tabname=>qualified_tabname, :strat_num=>strat_num, :rule_num=>rule_num}] ||= 0
         
     | 
| 
       306 
285 
     | 
    
         
             
                  bud_instance.metrics[:collections][{:addr=>addr, :tabname=>qualified_tabname, :strat_num=>strat_num, :rule_num=>rule_num}] += 1
         
     | 
| 
         @@ -311,7 +290,7 @@ module Bud 
     | 
|
| 
       311 
290 
     | 
    
         
             
                  bufs.each do |b|
         
     | 
| 
       312 
291 
     | 
    
         
             
                    b.each_value do |v|
         
     | 
| 
       313 
292 
     | 
    
         
             
                      tick_metrics if bud_instance and bud_instance.options[:metrics]
         
     | 
| 
       314 
     | 
    
         
            -
                      yield  
     | 
| 
      
 293 
     | 
    
         
            +
                      yield v
         
     | 
| 
       315 
294 
     | 
    
         
             
                    end
         
     | 
| 
       316 
295 
     | 
    
         
             
                  end
         
     | 
| 
       317 
296 
     | 
    
         
             
                end
         
     | 
| 
         @@ -365,7 +344,7 @@ module Bud 
     | 
|
| 
       365 
344 
     | 
    
         
             
                  # is this enforced in do_insert?
         
     | 
| 
       366 
345 
     | 
    
         
             
                  check_enumerable(k)
         
     | 
| 
       367 
346 
     | 
    
         
             
                  t = @storage[k]
         
     | 
| 
       368 
     | 
    
         
            -
                  return t.nil? ? @delta[k] :  
     | 
| 
      
 347 
     | 
    
         
            +
                  return t.nil? ? @delta[k] : t
         
     | 
| 
       369 
348 
     | 
    
         
             
                end
         
     | 
| 
       370 
349 
     | 
    
         | 
| 
       371 
350 
     | 
    
         
             
                # checks for +item+ in the collection
         
     | 
| 
         @@ -400,7 +379,7 @@ module Bud 
     | 
|
| 
       400 
379 
     | 
    
         
             
                private
         
     | 
| 
       401 
380 
     | 
    
         
             
                def raise_pk_error(new_guy, old)
         
     | 
| 
       402 
381 
     | 
    
         
             
                  key = get_key_vals(old)
         
     | 
| 
       403 
     | 
    
         
            -
                  raise KeyConstraintError, "key conflict inserting #{new_guy.inspect} into \"#{tabname}\": existing tuple #{old.inspect}, key = #{key.inspect}"
         
     | 
| 
      
 382 
     | 
    
         
            +
                  raise Bud::KeyConstraintError, "key conflict inserting #{new_guy.inspect} into \"#{tabname}\": existing tuple #{old.inspect}, key = #{key.inspect}"
         
     | 
| 
       404 
383 
     | 
    
         
             
                end
         
     | 
| 
       405 
384 
     | 
    
         | 
| 
       406 
385 
     | 
    
         
             
                private
         
     | 
| 
         @@ -408,24 +387,22 @@ module Bud 
     | 
|
| 
       408 
387 
     | 
    
         
             
                  return o if o.class == @struct
         
     | 
| 
       409 
388 
     | 
    
         
             
                  if o.class == Array
         
     | 
| 
       410 
389 
     | 
    
         
             
                    if @struct.nil?
         
     | 
| 
       411 
     | 
    
         
            -
                      sch = 
     | 
| 
      
 390 
     | 
    
         
            +
                      sch = (1 .. o.length).map{|i| "c#{i}".to_sym}
         
     | 
| 
       412 
391 
     | 
    
         
             
                      init_schema(sch)
         
     | 
| 
       413 
392 
     | 
    
         
             
                    end
         
     | 
| 
       414 
     | 
    
         
            -
                    o = o.take(@structlen) if o.length > @structlen
         
     | 
| 
       415 
393 
     | 
    
         
             
                  elsif o.kind_of? Struct
         
     | 
| 
       416 
394 
     | 
    
         
             
                    init_schema(o.members.map{|m| m.to_sym}) if @struct.nil?
         
     | 
| 
       417 
     | 
    
         
            -
                    o = o.take(@structlen)
         
     | 
| 
       418 
395 
     | 
    
         
             
                  else
         
     | 
| 
       419 
     | 
    
         
            -
                    raise TypeError, " 
     | 
| 
      
 396 
     | 
    
         
            +
                    raise Bud::TypeError, "array or struct type expected in \"#{qualified_tabname}\": #{o.inspect}"
         
     | 
| 
       420 
397 
     | 
    
         
             
                  end
         
     | 
| 
      
 398 
     | 
    
         
            +
             
     | 
| 
      
 399 
     | 
    
         
            +
                  o = o.take(@structlen) if o.length > @structlen
         
     | 
| 
       421 
400 
     | 
    
         
             
                  return @struct.new(*o)
         
     | 
| 
       422 
401 
     | 
    
         
             
                end
         
     | 
| 
       423 
402 
     | 
    
         | 
| 
       424 
403 
     | 
    
         
             
                private
         
     | 
| 
       425 
404 
     | 
    
         
             
                def get_key_vals(t)
         
     | 
| 
       426 
     | 
    
         
            -
                  @key_colnums.map  
     | 
| 
       427 
     | 
    
         
            -
                    t[i]
         
     | 
| 
       428 
     | 
    
         
            -
                  end
         
     | 
| 
      
 405 
     | 
    
         
            +
                  @key_colnums.map {|i| t[i]}
         
     | 
| 
       429 
406 
     | 
    
         
             
                end
         
     | 
| 
       430 
407 
     | 
    
         | 
| 
       431 
408 
     | 
    
         
             
                public
         
     | 
| 
         @@ -445,7 +422,7 @@ module Bud 
     | 
|
| 
       445 
422 
     | 
    
         | 
| 
       446 
423 
     | 
    
         
             
                  old = store[key]
         
     | 
| 
       447 
424 
     | 
    
         
             
                  if old.nil?
         
     | 
| 
       448 
     | 
    
         
            -
                    store[key] =  
     | 
| 
      
 425 
     | 
    
         
            +
                    store[key] = o
         
     | 
| 
       449 
426 
     | 
    
         
             
                  else
         
     | 
| 
       450 
427 
     | 
    
         
             
                    raise_pk_error(o, old) unless old == o
         
     | 
| 
       451 
428 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -465,7 +442,7 @@ module Bud 
     | 
|
| 
       465 
442 
     | 
    
         
             
                private
         
     | 
| 
       466 
443 
     | 
    
         
             
                def check_enumerable(o)
         
     | 
| 
       467 
444 
     | 
    
         
             
                  unless o.nil? or o.class < Enumerable or o.class <= Proc
         
     | 
| 
       468 
     | 
    
         
            -
                    raise TypeError, " 
     | 
| 
      
 445 
     | 
    
         
            +
                    raise Bud::TypeError, "collection #{qualified_tabname} expected Enumerable value, not #{o.inspect} (class = #{o.class})"
         
     | 
| 
       469 
446 
     | 
    
         
             
                  end
         
     | 
| 
       470 
447 
     | 
    
         
             
                end
         
     | 
| 
       471 
448 
     | 
    
         | 
| 
         @@ -502,34 +479,27 @@ module Bud 
     | 
|
| 
       502 
479 
     | 
    
         
             
                  init_schema((0..arity-1).map{|indx| ("c"+indx.to_s).to_sym})
         
     | 
| 
       503 
480 
     | 
    
         
             
                end
         
     | 
| 
       504 
481 
     | 
    
         | 
| 
       505 
     | 
    
         
            -
                 
     | 
| 
       506 
     | 
    
         
            -
                def  
     | 
| 
       507 
     | 
    
         
            -
                   
     | 
| 
       508 
     | 
    
         
            -
                   
     | 
| 
       509 
     | 
    
         
            -
                     
     | 
| 
       510 
     | 
    
         
            -
                    next if old.nil?
         
     | 
| 
       511 
     | 
    
         
            -
                    if old != t
         
     | 
| 
       512 
     | 
    
         
            -
                      raise_pk_error(t, old)
         
     | 
| 
       513 
     | 
    
         
            -
                    else
         
     | 
| 
       514 
     | 
    
         
            -
                      return true
         
     | 
| 
       515 
     | 
    
         
            -
                    end
         
     | 
| 
      
 482 
     | 
    
         
            +
                protected
         
     | 
| 
      
 483 
     | 
    
         
            +
                def add_merge_target
         
     | 
| 
      
 484 
     | 
    
         
            +
                  toplevel = @bud_instance.toplevel
         
     | 
| 
      
 485 
     | 
    
         
            +
                  if toplevel.done_bootstrap
         
     | 
| 
      
 486 
     | 
    
         
            +
                    toplevel.merge_targets[toplevel.this_stratum] << self
         
     | 
| 
       516 
487 
     | 
    
         
             
                  end
         
     | 
| 
       517 
     | 
    
         
            -
                  return false
         
     | 
| 
       518 
488 
     | 
    
         
             
                end
         
     | 
| 
       519 
489 
     | 
    
         | 
| 
       520 
490 
     | 
    
         
             
                public
         
     | 
| 
       521 
491 
     | 
    
         
             
                def merge(o, buf=@delta) # :nodoc: all
         
     | 
| 
       522 
492 
     | 
    
         
             
                  toplevel = @bud_instance.toplevel
         
     | 
| 
       523 
493 
     | 
    
         
             
                  if o.class <= Bud::PushElement
         
     | 
| 
       524 
     | 
    
         
            -
                     
     | 
| 
      
 494 
     | 
    
         
            +
                    add_merge_target
         
     | 
| 
       525 
495 
     | 
    
         
             
                    deduce_schema(o) if @cols.nil?
         
     | 
| 
       526 
496 
     | 
    
         
             
                    o.wire_to self
         
     | 
| 
       527 
497 
     | 
    
         
             
                  elsif o.class <= Bud::BudCollection
         
     | 
| 
       528 
     | 
    
         
            -
                     
     | 
| 
      
 498 
     | 
    
         
            +
                    add_merge_target
         
     | 
| 
       529 
499 
     | 
    
         
             
                    deduce_schema(o) if @cols.nil?
         
     | 
| 
       530 
500 
     | 
    
         
             
                    o.pro.wire_to self
         
     | 
| 
       531 
501 
     | 
    
         
             
                  elsif o.class <= Proc and toplevel.done_bootstrap and not toplevel.done_wiring and not o.nil?
         
     | 
| 
       532 
     | 
    
         
            -
                     
     | 
| 
      
 502 
     | 
    
         
            +
                    add_merge_target
         
     | 
| 
       533 
503 
     | 
    
         
             
                    tbl = register_coll_expr(o)
         
     | 
| 
       534 
504 
     | 
    
         
             
                    tbl.pro.wire_to self
         
     | 
| 
       535 
505 
     | 
    
         
             
                  else
         
     | 
| 
         @@ -543,17 +513,9 @@ module Bud 
     | 
|
| 
       543 
513 
     | 
    
         
             
                  return self
         
     | 
| 
       544 
514 
     | 
    
         
             
                end
         
     | 
| 
       545 
515 
     | 
    
         | 
| 
       546 
     | 
    
         
            -
                # def prep_coll_expr(o)
         
     | 
| 
       547 
     | 
    
         
            -
                #   o = o.uniq.compact if o.respond_to?(:uniq)
         
     | 
| 
       548 
     | 
    
         
            -
                #   check_enumerable(o)
         
     | 
| 
       549 
     | 
    
         
            -
                #   establish_schema(o) if @cols.nil?
         
     | 
| 
       550 
     | 
    
         
            -
                #   o
         
     | 
| 
       551 
     | 
    
         
            -
                # end
         
     | 
| 
       552 
     | 
    
         
            -
             
     | 
| 
       553 
516 
     | 
    
         
             
                def register_coll_expr(expr)
         
     | 
| 
       554 
     | 
    
         
            -
                   
     | 
| 
       555 
     | 
    
         
            -
                   
     | 
| 
       556 
     | 
    
         
            -
                  cols = (1..@cols.length).map{|i| ("c"+i.to_s).to_sym} unless @cols.nil?
         
     | 
| 
      
 517 
     | 
    
         
            +
                  coll_name = "expr_#{expr.object_id}"
         
     | 
| 
      
 518 
     | 
    
         
            +
                  cols = (1..@cols.length).map{|i| "c#{i}".to_sym} unless @cols.nil?
         
     | 
| 
       557 
519 
     | 
    
         
             
                  @bud_instance.coll_expr(coll_name.to_sym, expr, cols)
         
     | 
| 
       558 
520 
     | 
    
         
             
                  coll = @bud_instance.send(coll_name)
         
     | 
| 
       559 
521 
     | 
    
         
             
                  coll
         
     | 
| 
         @@ -570,13 +532,13 @@ module Bud 
     | 
|
| 
       570 
532 
     | 
    
         
             
                def pending_merge(o) # :nodoc: all
         
     | 
| 
       571 
533 
     | 
    
         
             
                  toplevel = @bud_instance.toplevel
         
     | 
| 
       572 
534 
     | 
    
         
             
                  if o.class <= Bud::PushElement
         
     | 
| 
       573 
     | 
    
         
            -
                     
     | 
| 
      
 535 
     | 
    
         
            +
                    add_merge_target
         
     | 
| 
       574 
536 
     | 
    
         
             
                    o.wire_to_pending self
         
     | 
| 
       575 
537 
     | 
    
         
             
                  elsif o.class <= Bud::BudCollection
         
     | 
| 
       576 
     | 
    
         
            -
                     
     | 
| 
      
 538 
     | 
    
         
            +
                    add_merge_target
         
     | 
| 
       577 
539 
     | 
    
         
             
                    o.pro.wire_to_pending self
         
     | 
| 
       578 
540 
     | 
    
         
             
                  elsif o.class <= Proc and toplevel.done_bootstrap and not toplevel.done_wiring
         
     | 
| 
       579 
     | 
    
         
            -
                     
     | 
| 
      
 541 
     | 
    
         
            +
                    add_merge_target
         
     | 
| 
       580 
542 
     | 
    
         
             
                    tbl = register_coll_expr(o) unless o.nil?
         
     | 
| 
       581 
543 
     | 
    
         
             
                    tbl.pro.wire_to_pending self
         
     | 
| 
       582 
544 
     | 
    
         
             
                  else
         
     | 
| 
         @@ -599,7 +561,7 @@ module Bud 
     | 
|
| 
       599 
561 
     | 
    
         
             
                end
         
     | 
| 
       600 
562 
     | 
    
         | 
| 
       601 
563 
     | 
    
         
             
                def tick
         
     | 
| 
       602 
     | 
    
         
            -
                  raise "tick must be overriden in #{self.class}"
         
     | 
| 
      
 564 
     | 
    
         
            +
                  raise Bud::Error, "tick must be overriden in #{self.class}"
         
     | 
| 
       603 
565 
     | 
    
         
             
                end
         
     | 
| 
       604 
566 
     | 
    
         | 
| 
       605 
567 
     | 
    
         
             
                # move deltas to storage, and new_deltas to deltas.
         
     | 
| 
         @@ -609,12 +571,15 @@ module Bud 
     | 
|
| 
       609 
571 
     | 
    
         
             
                  unless @delta.empty?
         
     | 
| 
       610 
572 
     | 
    
         
             
                    puts "#{qualified_tabname}.tick_delta delta --> storage (#{@delta.size} elems)" if $BUD_DEBUG
         
     | 
| 
       611 
573 
     | 
    
         
             
                    @storage.merge!(@delta)
         
     | 
| 
       612 
     | 
    
         
            -
                    @tick_delta += @delta.values
         
     | 
| 
      
 574 
     | 
    
         
            +
                    @tick_delta += @delta.values if accumulate_tick_deltas
         
     | 
| 
       613 
575 
     | 
    
         
             
                    @delta.clear
         
     | 
| 
       614 
576 
     | 
    
         
             
                  end
         
     | 
| 
       615 
577 
     | 
    
         | 
| 
       616 
578 
     | 
    
         
             
                  unless @new_delta.empty?
         
     | 
| 
       617 
579 
     | 
    
         
             
                    puts "#{qualified_tabname}.tick_delta new_delta --> delta (#{@new_delta.size} elems)" if $BUD_DEBUG
         
     | 
| 
      
 580 
     | 
    
         
            +
             
     | 
| 
      
 581 
     | 
    
         
            +
                    # XXX: what about multiple delta tuples produced in the same tick that
         
     | 
| 
      
 582 
     | 
    
         
            +
                    # conflict on the PK?
         
     | 
| 
       618 
583 
     | 
    
         
             
                    @new_delta.each_pair do |k, v|
         
     | 
| 
       619 
584 
     | 
    
         
             
                      sv = @storage[k]
         
     | 
| 
       620 
585 
     | 
    
         
             
                      if sv.nil?
         
     | 
| 
         @@ -631,8 +596,9 @@ module Bud 
     | 
|
| 
       631 
596 
     | 
    
         | 
| 
       632 
597 
     | 
    
         
             
                public
         
     | 
| 
       633 
598 
     | 
    
         
             
                def add_rescan_invalidate(rescan, invalidate)
         
     | 
| 
       634 
     | 
    
         
            -
                  # No change. Most collections don't need to rescan on every tick (only do 
     | 
| 
       635 
     | 
    
         
            -
                  #  
     | 
| 
      
 599 
     | 
    
         
            +
                  # No change. Most collections don't need to rescan on every tick (only do
         
     | 
| 
      
 600 
     | 
    
         
            +
                  # so on negate). Also, there's no cache to invalidate by default.
         
     | 
| 
      
 601 
     | 
    
         
            +
                  # Scratches and PushElements override this method.
         
     | 
| 
       636 
602 
     | 
    
         
             
                end
         
     | 
| 
       637 
603 
     | 
    
         | 
| 
       638 
604 
     | 
    
         
             
                def bootstrap
         
     | 
| 
         @@ -648,9 +614,9 @@ module Bud 
     | 
|
| 
       648 
614 
     | 
    
         
             
                    puts "#{qualified_tabname}.flush delta --> storage" unless @delta.empty?
         
     | 
| 
       649 
615 
     | 
    
         
             
                    puts "#{qualified_tabname}.flush new_delta --> storage" unless @new_delta.empty?
         
     | 
| 
       650 
616 
     | 
    
         
             
                  end
         
     | 
| 
       651 
     | 
    
         
            -
                  unless  
     | 
| 
      
 617 
     | 
    
         
            +
                  unless @delta.empty?
         
     | 
| 
       652 
618 
     | 
    
         
             
                    @storage.merge!(@delta)
         
     | 
| 
       653 
     | 
    
         
            -
                    @tick_delta += @delta.values
         
     | 
| 
      
 619 
     | 
    
         
            +
                    @tick_delta += @delta.values if accumulate_tick_deltas
         
     | 
| 
       654 
620 
     | 
    
         
             
                    @delta.clear
         
     | 
| 
       655 
621 
     | 
    
         
             
                  end
         
     | 
| 
       656 
622 
     | 
    
         
             
                  unless @new_delta.empty?
         
     | 
| 
         @@ -664,7 +630,6 @@ module Bud 
     | 
|
| 
       664 
630 
     | 
    
         
             
                def to_push_elem(the_name=tabname, the_schema=schema)
         
     | 
| 
       665 
631 
     | 
    
         
             
                  # if no push source yet, set one up
         
     | 
| 
       666 
632 
     | 
    
         
             
                  toplevel = @bud_instance.toplevel
         
     | 
| 
       667 
     | 
    
         
            -
                  #rule_context = toplevel.this_rule_context
         
     | 
| 
       668 
633 
     | 
    
         
             
                  this_stratum = toplevel.this_stratum
         
     | 
| 
       669 
634 
     | 
    
         
             
                  oid = self.object_id
         
     | 
| 
       670 
635 
     | 
    
         
             
                  unless toplevel.scanners[this_stratum][[oid, the_name]]
         
     | 
| 
         @@ -674,17 +639,6 @@ module Bud 
     | 
|
| 
       674 
639 
     | 
    
         
             
                  return toplevel.scanners[this_stratum][[oid, the_name]]
         
     | 
| 
       675 
640 
     | 
    
         
             
                end
         
     | 
| 
       676 
641 
     | 
    
         | 
| 
       677 
     | 
    
         
            -
                private
         
     | 
| 
       678 
     | 
    
         
            -
                def method_missing(sym, *args, &block)
         
     | 
| 
       679 
     | 
    
         
            -
                  begin
         
     | 
| 
       680 
     | 
    
         
            -
                    @storage.send sym, *args, &block
         
     | 
| 
       681 
     | 
    
         
            -
                  rescue Exception => e
         
     | 
| 
       682 
     | 
    
         
            -
                    err = NoMethodError.new("no method :#{sym} in class #{self.class.name}")
         
     | 
| 
       683 
     | 
    
         
            -
                    err.set_backtrace(e.backtrace)
         
     | 
| 
       684 
     | 
    
         
            -
                    raise err
         
     | 
| 
       685 
     | 
    
         
            -
                  end
         
     | 
| 
       686 
     | 
    
         
            -
                end
         
     | 
| 
       687 
     | 
    
         
            -
             
     | 
| 
       688 
642 
     | 
    
         
             
                ######## aggs
         
     | 
| 
       689 
643 
     | 
    
         | 
| 
       690 
644 
     | 
    
         
             
                private
         
     | 
| 
         @@ -699,16 +653,14 @@ module Bud 
     | 
|
| 
       699 
653 
     | 
    
         
             
                  end
         
     | 
| 
       700 
654 
     | 
    
         
             
                end
         
     | 
| 
       701 
655 
     | 
    
         | 
| 
       702 
     | 
    
         
            -
             
     | 
| 
       703 
656 
     | 
    
         
             
                # a generalization of argmin/argmax to arbitrary exemplary aggregates.
         
     | 
| 
       704 
657 
     | 
    
         
             
                # for each distinct value of the grouping key columns, return the items in that group
         
     | 
| 
       705 
658 
     | 
    
         
             
                # that have the value of the exemplary aggregate +aggname+
         
     | 
| 
       706 
659 
     | 
    
         
             
                public
         
     | 
| 
       707 
660 
     | 
    
         
             
                def argagg(aggname, gbkey_cols, collection)
         
     | 
| 
       708 
661 
     | 
    
         
             
                  elem = to_push_elem
         
     | 
| 
       709 
     | 
    
         
            -
                  elem.schema
         
     | 
| 
       710 
662 
     | 
    
         
             
                  gbkey_cols = gbkey_cols.map{|k| canonicalize_col(k)} unless gbkey_cols.nil?
         
     | 
| 
       711 
     | 
    
         
            -
                  retval = elem.argagg(aggname,gbkey_cols,canonicalize_col(collection))
         
     | 
| 
      
 663 
     | 
    
         
            +
                  retval = elem.argagg(aggname, gbkey_cols, canonicalize_col(collection))
         
     | 
| 
       712 
664 
     | 
    
         
             
                  # PushElement inherits the schema accessors from this Collection
         
     | 
| 
       713 
665 
     | 
    
         
             
                  retval.extend @cols_access
         
     | 
| 
       714 
666 
     | 
    
         
             
                  retval
         
     | 
| 
         @@ -722,37 +674,21 @@ module Bud 
     | 
|
| 
       722 
674 
     | 
    
         
             
                  argagg(:min, gbkey_cols, col)
         
     | 
| 
       723 
675 
     | 
    
         
             
                end
         
     | 
| 
       724 
676 
     | 
    
         | 
| 
       725 
     | 
    
         
            -
                # for each distinct value of the grouping key columns, return the  
     | 
| 
       726 
     | 
    
         
            -
                # that group that  
     | 
| 
      
 677 
     | 
    
         
            +
                # for each distinct value of the grouping key columns, return the items in
         
     | 
| 
      
 678 
     | 
    
         
            +
                # that group that have the maximum value of the attribute +col+. Note that
         
     | 
| 
       727 
679 
     | 
    
         
             
                # multiple tuples might be returned.
         
     | 
| 
       728 
680 
     | 
    
         
             
                public
         
     | 
| 
       729 
681 
     | 
    
         
             
                def argmax(gbkey_cols, col)
         
     | 
| 
       730 
682 
     | 
    
         
             
                  argagg(:max, gbkey_cols, col)
         
     | 
| 
       731 
683 
     | 
    
         
             
                end
         
     | 
| 
       732 
684 
     | 
    
         | 
| 
       733 
     | 
    
         
            -
                private
         
     | 
| 
       734 
     | 
    
         
            -
                def wrap_map(j, &blk)
         
     | 
| 
       735 
     | 
    
         
            -
                  if blk.nil?
         
     | 
| 
       736 
     | 
    
         
            -
                    return j
         
     | 
| 
       737 
     | 
    
         
            -
                  else
         
     | 
| 
       738 
     | 
    
         
            -
                    return j.map(&blk)
         
     | 
| 
       739 
     | 
    
         
            -
                  end
         
     | 
| 
       740 
     | 
    
         
            -
                end
         
     | 
| 
       741 
     | 
    
         
            -
             
     | 
| 
       742 
     | 
    
         
            -
                # def join(collections, *preds, &blk)
         
     | 
| 
       743 
     | 
    
         
            -
                #   # since joins are stateful, we want to allocate them once and store in this Bud instance
         
     | 
| 
       744 
     | 
    
         
            -
                #   # we ID them on their tablenames, preds, and block
         
     | 
| 
       745 
     | 
    
         
            -
                #   return wrap_map(BudJoin.new(collections, @bud_instance, preds), &blk)
         
     | 
| 
       746 
     | 
    
         
            -
                # end
         
     | 
| 
       747 
     | 
    
         
            -
             
     | 
| 
       748 
685 
     | 
    
         
             
                # form a collection containing all pairs of items in +self+ and items in
         
     | 
| 
       749 
686 
     | 
    
         
             
                # +collection+
         
     | 
| 
       750 
687 
     | 
    
         
             
                public
         
     | 
| 
       751 
688 
     | 
    
         
             
                def *(collection)
         
     | 
| 
       752 
     | 
    
         
            -
                  elem1 
     | 
| 
      
 689 
     | 
    
         
            +
                  elem1 = to_push_elem
         
     | 
| 
       753 
690 
     | 
    
         
             
                  j = elem1.join(collection)
         
     | 
| 
       754 
691 
     | 
    
         
             
                  return j
         
     | 
| 
       755 
     | 
    
         
            -
                  # join([self, collection])
         
     | 
| 
       756 
692 
     | 
    
         
             
                end
         
     | 
| 
       757 
693 
     | 
    
         | 
| 
       758 
694 
     | 
    
         
             
                def group(key_cols, *aggpairs, &blk)
         
     | 
| 
         @@ -778,14 +714,14 @@ module Bud 
     | 
|
| 
       778 
714 
     | 
    
         
             
                  elem1 = to_push_elem
         
     | 
| 
       779 
715 
     | 
    
         
             
                  red_elem = elem1.reduce(initial, &blk)
         
     | 
| 
       780 
716 
     | 
    
         
             
                  return red_elem
         
     | 
| 
       781 
     | 
    
         
            -
                end 
     | 
| 
      
 717 
     | 
    
         
            +
                end
         
     | 
| 
       782 
718 
     | 
    
         | 
| 
       783 
719 
     | 
    
         
             
                public
         
     | 
| 
       784 
720 
     | 
    
         
             
                def pretty_print_instance_variables
         
     | 
| 
       785 
721 
     | 
    
         
             
                  # list of attributes (in order) to print when pretty_print is called.
         
     | 
| 
       786 
722 
     | 
    
         
             
                  important = ["@tabname", "@storage", "@delta", "@new_delta", "@pending"]
         
     | 
| 
       787 
723 
     | 
    
         
             
                  # everything except bud_instance
         
     | 
| 
       788 
     | 
    
         
            -
                  important + (self.instance_variables - important - ["@bud_instance"]) 
     | 
| 
      
 724 
     | 
    
         
            +
                  important + (self.instance_variables - important - ["@bud_instance"])
         
     | 
| 
       789 
725 
     | 
    
         
             
                end
         
     | 
| 
       790 
726 
     | 
    
         | 
| 
       791 
727 
     | 
    
         
             
                public
         
     | 
| 
         @@ -796,9 +732,12 @@ module Bud 
     | 
|
| 
       796 
732 
     | 
    
         
             
              end
         
     | 
| 
       797 
733 
     | 
    
         | 
| 
       798 
734 
     | 
    
         
             
              class BudScratch < BudCollection # :nodoc: all
         
     | 
| 
      
 735 
     | 
    
         
            +
                def accumulate_tick_deltas
         
     | 
| 
      
 736 
     | 
    
         
            +
                  false
         
     | 
| 
      
 737 
     | 
    
         
            +
                end
         
     | 
| 
      
 738 
     | 
    
         
            +
             
     | 
| 
       799 
739 
     | 
    
         
             
                public
         
     | 
| 
       800 
740 
     | 
    
         
             
                def tick  # :nodoc: all
         
     | 
| 
       801 
     | 
    
         
            -
                  @tick_delta.clear
         
     | 
| 
       802 
741 
     | 
    
         
             
                  @delta.clear
         
     | 
| 
       803 
742 
     | 
    
         
             
                  if not @pending.empty?
         
     | 
| 
       804 
743 
     | 
    
         
             
                    invalidate_cache
         
     | 
| 
         @@ -815,20 +754,19 @@ module Bud 
     | 
|
| 
       815 
754 
     | 
    
         
             
                  is_source      # rescan always only if this scratch is a source.
         
     | 
| 
       816 
755 
     | 
    
         
             
                end
         
     | 
| 
       817 
756 
     | 
    
         | 
| 
       818 
     | 
    
         
            -
             
     | 
| 
       819 
757 
     | 
    
         
             
                public
         
     | 
| 
       820 
758 
     | 
    
         
             
                def add_rescan_invalidate(rescan, invalidate)
         
     | 
| 
       821 
759 
     | 
    
         
             
                  srcs = non_temporal_predecessors
         
     | 
| 
       822 
760 
     | 
    
         
             
                  if srcs.any? {|e| rescan.member? e}
         
     | 
| 
       823 
761 
     | 
    
         
             
                    invalidate << self
         
     | 
| 
       824 
     | 
    
         
            -
                     
     | 
| 
      
 762 
     | 
    
         
            +
                    rescan += srcs
         
     | 
| 
       825 
763 
     | 
    
         
             
                  end
         
     | 
| 
       826 
764 
     | 
    
         
             
                end
         
     | 
| 
       827 
765 
     | 
    
         | 
| 
       828 
766 
     | 
    
         
             
                public
         
     | 
| 
       829 
767 
     | 
    
         
             
                def invalidate_cache
         
     | 
| 
       830 
768 
     | 
    
         
             
                  puts "#{qualified_tabname} invalidated" if $BUD_DEBUG
         
     | 
| 
       831 
     | 
    
         
            -
                  #for scratches, storage is a cached value 
     | 
| 
      
 769 
     | 
    
         
            +
                  # for scratches, storage is a cached value
         
     | 
| 
       832 
770 
     | 
    
         
             
                  @invalidated = true
         
     | 
| 
       833 
771 
     | 
    
         
             
                  @storage.clear
         
     | 
| 
       834 
772 
     | 
    
         
             
                end
         
     | 
| 
         @@ -843,9 +781,10 @@ module Bud 
     | 
|
| 
       843 
781 
     | 
    
         
             
              class BudTemp < BudScratch # :nodoc: all
         
     | 
| 
       844 
782 
     | 
    
         
             
              end
         
     | 
| 
       845 
783 
     | 
    
         | 
| 
       846 
     | 
    
         
            -
              # Channels are a different type of collection in that they represent two 
     | 
| 
       847 
     | 
    
         
            -
              # incoming and outgoing.  The incoming side 
     | 
| 
       848 
     | 
    
         
            -
              #  
     | 
| 
      
 784 
     | 
    
         
            +
              # Channels are a different type of collection in that they represent two
         
     | 
| 
      
 785 
     | 
    
         
            +
              # distinct collections, one each for incoming and outgoing.  The incoming side
         
     | 
| 
      
 786 
     | 
    
         
            +
              # makes use of @storage and @delta, whereas the outgoing side only deals with
         
     | 
| 
      
 787 
     | 
    
         
            +
              # @pending. XXX Maybe we should be using aliases instead.
         
     | 
| 
       849 
788 
     | 
    
         
             
              class BudChannel < BudCollection
         
     | 
| 
       850 
789 
     | 
    
         
             
                attr_reader :locspec_idx # :nodoc: all
         
     | 
| 
       851 
790 
     | 
    
         | 
| 
         @@ -908,15 +847,10 @@ module Bud 
     | 
|
| 
       908 
847 
     | 
    
         
             
                    lsplit[1] = lsplit[1].to_i
         
     | 
| 
       909 
848 
     | 
    
         
             
                    return lsplit
         
     | 
| 
       910 
849 
     | 
    
         
             
                  rescue Exception => e
         
     | 
| 
       911 
     | 
    
         
            -
                    raise Bud::Error, " 
     | 
| 
      
 850 
     | 
    
         
            +
                    raise Bud::Error, "illegal location specifier in tuple #{t.inspect} for channel \"#{qualified_tabname}\": #{e.to_s}"
         
     | 
| 
       912 
851 
     | 
    
         
             
                  end
         
     | 
| 
       913 
852 
     | 
    
         
             
                end
         
     | 
| 
       914 
853 
     | 
    
         | 
| 
       915 
     | 
    
         
            -
                public
         
     | 
| 
       916 
     | 
    
         
            -
                def clone_empty
         
     | 
| 
       917 
     | 
    
         
            -
                  self.class.new(tabname, bud_instance, @raw_schema, @is_loopback)
         
     | 
| 
       918 
     | 
    
         
            -
                end
         
     | 
| 
       919 
     | 
    
         
            -
             
     | 
| 
       920 
854 
     | 
    
         
             
                public
         
     | 
| 
       921 
855 
     | 
    
         
             
                def tick # :nodoc: all
         
     | 
| 
       922 
856 
     | 
    
         
             
                  @storage.clear
         
     | 
| 
         @@ -968,7 +902,7 @@ module Bud 
     | 
|
| 
       968 
902 
     | 
    
         
             
                end
         
     | 
| 
       969 
903 
     | 
    
         | 
| 
       970 
904 
     | 
    
         
             
                superator "<~" do |o|
         
     | 
| 
       971 
     | 
    
         
            -
                  if o.class <= PushElement
         
     | 
| 
      
 905 
     | 
    
         
            +
                  if o.class <= Bud::PushElement
         
     | 
| 
       972 
906 
     | 
    
         
             
                    o.wire_to_pending self
         
     | 
| 
       973 
907 
     | 
    
         
             
                  else
         
     | 
| 
       974 
908 
     | 
    
         
             
                    pending_merge(o)
         
     | 
| 
         @@ -1066,7 +1000,7 @@ module Bud 
     | 
|
| 
       1066 
1000 
     | 
    
         
             
                end
         
     | 
| 
       1067 
1001 
     | 
    
         | 
| 
       1068 
1002 
     | 
    
         
             
                superator "<~" do |o|
         
     | 
| 
       1069 
     | 
    
         
            -
                  if o.class <= PushElement
         
     | 
| 
      
 1003 
     | 
    
         
            +
                  if o.class <= Bud::PushElement
         
     | 
| 
       1070 
1004 
     | 
    
         
             
                    o.wire_to_pending self
         
     | 
| 
       1071 
1005 
     | 
    
         
             
                  else
         
     | 
| 
       1072 
1006 
     | 
    
         
             
                    pending_merge(o)
         
     | 
| 
         @@ -1118,7 +1052,7 @@ module Bud 
     | 
|
| 
       1118 
1052 
     | 
    
         | 
| 
       1119 
1053 
     | 
    
         
             
                public
         
     | 
| 
       1120 
1054 
     | 
    
         
             
                def invalidate_cache
         
     | 
| 
       1121 
     | 
    
         
            -
                  raise " 
     | 
| 
      
 1055 
     | 
    
         
            +
                  raise Bud::Error, "abstract method not implemented by derived class #{self.class}"
         
     | 
| 
       1122 
1056 
     | 
    
         
             
                end
         
     | 
| 
       1123 
1057 
     | 
    
         
             
              end
         
     | 
| 
       1124 
1058 
     | 
    
         | 
| 
         @@ -1149,13 +1083,13 @@ module Bud 
     | 
|
| 
       1149 
1083 
     | 
    
         
             
                    deleted ||= v
         
     | 
| 
       1150 
1084 
     | 
    
         
             
                  end
         
     | 
| 
       1151 
1085 
     | 
    
         | 
| 
       1152 
     | 
    
         
            -
                  @invalidated = 
     | 
| 
      
 1086 
     | 
    
         
            +
                  @invalidated = (not deleted.nil?)
         
     | 
| 
       1153 
1087 
     | 
    
         
             
                  puts "table #{qualified_tabname} invalidated" if $BUD_DEBUG and @invalidated
         
     | 
| 
       1154 
1088 
     | 
    
         | 
| 
       1155 
1089 
     | 
    
         
             
                  @pending.each do |keycols, tuple|
         
     | 
| 
       1156 
1090 
     | 
    
         
             
                    old = @storage[keycols]
         
     | 
| 
       1157 
1091 
     | 
    
         
             
                    if old.nil?
         
     | 
| 
       1158 
     | 
    
         
            -
                      @delta[keycols] = tuple 
     | 
| 
      
 1092 
     | 
    
         
            +
                      @delta[keycols] = tuple
         
     | 
| 
       1159 
1093 
     | 
    
         
             
                    else
         
     | 
| 
       1160 
1094 
     | 
    
         
             
                      raise_pk_error(tuple, old) unless tuple == old
         
     | 
| 
       1161 
1095 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -1166,19 +1100,19 @@ module Bud 
     | 
|
| 
       1166 
1100 
     | 
    
         
             
                end
         
     | 
| 
       1167 
1101 
     | 
    
         | 
| 
       1168 
1102 
     | 
    
         
             
                def invalidated=(val)
         
     | 
| 
       1169 
     | 
    
         
            -
                  raise "Internal error:  
     | 
| 
      
 1103 
     | 
    
         
            +
                  raise "Internal error: must not set invalidate on tables"
         
     | 
| 
       1170 
1104 
     | 
    
         
             
                end
         
     | 
| 
       1171 
1105 
     | 
    
         | 
| 
       1172 
1106 
     | 
    
         
             
                def pending_delete(o)
         
     | 
| 
       1173 
1107 
     | 
    
         
             
                  toplevel = @bud_instance.toplevel
         
     | 
| 
       1174 
1108 
     | 
    
         
             
                  if o.class <= Bud::PushElement
         
     | 
| 
       1175 
     | 
    
         
            -
                     
     | 
| 
      
 1109 
     | 
    
         
            +
                    add_merge_target
         
     | 
| 
       1176 
1110 
     | 
    
         
             
                    o.wire_to_delete self
         
     | 
| 
       1177 
1111 
     | 
    
         
             
                  elsif o.class <= Bud::BudCollection
         
     | 
| 
       1178 
     | 
    
         
            -
                     
     | 
| 
      
 1112 
     | 
    
         
            +
                    add_merge_target
         
     | 
| 
       1179 
1113 
     | 
    
         
             
                    o.pro.wire_to_delete self
         
     | 
| 
       1180 
1114 
     | 
    
         
             
                  elsif o.class <= Proc and @bud_instance.toplevel.done_bootstrap and not toplevel.done_wiring
         
     | 
| 
       1181 
     | 
    
         
            -
                     
     | 
| 
      
 1115 
     | 
    
         
            +
                    add_merge_target
         
     | 
| 
       1182 
1116 
     | 
    
         
             
                    tbl = register_coll_expr(o)
         
     | 
| 
       1183 
1117 
     | 
    
         
             
                    tbl.pro.wire_to_delete self
         
     | 
| 
       1184 
1118 
     | 
    
         
             
                  else
         
     | 
| 
         @@ -1217,8 +1151,9 @@ module Bud 
     | 
|
| 
       1217 
1151 
     | 
    
         | 
| 
       1218 
1152 
     | 
    
         
             
                public
         
     | 
| 
       1219 
1153 
     | 
    
         
             
                def invalidate_cache
         
     | 
| 
       1220 
     | 
    
         
            -
                  #  
     | 
| 
       1221 
     | 
    
         
            -
                  #  
     | 
| 
      
 1154 
     | 
    
         
            +
                  # No cache to invalidate. Also, tables do not invalidate dependents,
         
     | 
| 
      
 1155 
     | 
    
         
            +
                  # because their own state is not considered invalidated; that happens only
         
     | 
| 
      
 1156 
     | 
    
         
            +
                  # if there were pending deletes at the beginning of a tick (see tick())
         
     | 
| 
       1222 
1157 
     | 
    
         
             
                  puts "******** invalidate_cache called on BudTable"
         
     | 
| 
       1223 
1158 
     | 
    
         
             
                end
         
     | 
| 
       1224 
1159 
     | 
    
         | 
| 
         @@ -1226,8 +1161,8 @@ module Bud 
     | 
|
| 
       1226 
1161 
     | 
    
         
             
                superator "<+-" do |o|
         
     | 
| 
       1227 
1162 
     | 
    
         
             
                  pending_delete_keys(o)
         
     | 
| 
       1228 
1163 
     | 
    
         
             
                  self <+ o
         
     | 
| 
       1229 
     | 
    
         
            -
                end 
     | 
| 
       1230 
     | 
    
         
            -
                public 
     | 
| 
      
 1164 
     | 
    
         
            +
                end
         
     | 
| 
      
 1165 
     | 
    
         
            +
                public
         
     | 
| 
       1231 
1166 
     | 
    
         
             
                superator "<-+" do |o|
         
     | 
| 
       1232 
1167 
     | 
    
         
             
                  self <+- o
         
     | 
| 
       1233 
1168 
     | 
    
         
             
                end
         
     | 
| 
         @@ -1251,20 +1186,6 @@ module Bud 
     | 
|
| 
       1251 
1186 
     | 
    
         
             
                end
         
     | 
| 
       1252 
1187 
     | 
    
         
             
              end
         
     | 
| 
       1253 
1188 
     | 
    
         | 
| 
       1254 
     | 
    
         
            -
              class BudSignal < BudReadOnly
         
     | 
| 
       1255 
     | 
    
         
            -
                def invalidate_at_tick
         
     | 
| 
       1256 
     | 
    
         
            -
                  true
         
     | 
| 
       1257 
     | 
    
         
            -
                end
         
     | 
| 
       1258 
     | 
    
         
            -
                def tick
         
     | 
| 
       1259 
     | 
    
         
            -
                  @invalidated = true
         
     | 
| 
       1260 
     | 
    
         
            -
                  @storage.clear
         
     | 
| 
       1261 
     | 
    
         
            -
                  unless @pending.empty?
         
     | 
| 
       1262 
     | 
    
         
            -
                    @delta = @pending
         
     | 
| 
       1263 
     | 
    
         
            -
                    @pending = {}
         
     | 
| 
       1264 
     | 
    
         
            -
                  end
         
     | 
| 
       1265 
     | 
    
         
            -
                end
         
     | 
| 
       1266 
     | 
    
         
            -
              end
         
     | 
| 
       1267 
     | 
    
         
            -
             
     | 
| 
       1268 
1189 
     | 
    
         
             
              class BudCollExpr < BudReadOnly # :nodoc: all
         
     | 
| 
       1269 
1190 
     | 
    
         
             
                def initialize(name, bud_instance, expr, given_schema=nil, defer_schema=false)
         
     | 
| 
       1270 
1191 
     | 
    
         
             
                  super(name, bud_instance, given_schema, defer_schema)
         
     | 
| 
         @@ -1309,20 +1230,12 @@ module Bud 
     | 
|
| 
       1309 
1230 
     | 
    
         | 
| 
       1310 
1231 
     | 
    
         
             
                public
         
     | 
| 
       1311 
1232 
     | 
    
         
             
                def each(&blk)
         
     | 
| 
       1312 
     | 
    
         
            -
                  each_raw {|l|  
     | 
| 
      
 1233 
     | 
    
         
            +
                  each_raw {|l| blk.call(l)}
         
     | 
| 
       1313 
1234 
     | 
    
         
             
                end
         
     | 
| 
       1314 
1235 
     | 
    
         
             
              end
         
     | 
| 
       1315 
1236 
     | 
    
         
             
            end
         
     | 
| 
       1316 
1237 
     | 
    
         | 
| 
       1317 
1238 
     | 
    
         
             
            module Enumerable
         
     | 
| 
       1318 
     | 
    
         
            -
              # public
         
     | 
| 
       1319 
     | 
    
         
            -
              # # monkeypatch to Enumerable to rename collections and their schemas
         
     | 
| 
       1320 
     | 
    
         
            -
              # def rename(new_tabname, new_schema=nil)
         
     | 
| 
       1321 
     | 
    
         
            -
              #   scr = Bud::BudScratch.new(new_tabname.to_s, nil, new_schema)
         
     | 
| 
       1322 
     | 
    
         
            -
              #   scr.merge(self, scr.storage)
         
     | 
| 
       1323 
     | 
    
         
            -
              #   scr
         
     | 
| 
       1324 
     | 
    
         
            -
              # end
         
     | 
| 
       1325 
     | 
    
         
            -
             
     | 
| 
       1326 
1239 
     | 
    
         
             
              public
         
     | 
| 
       1327 
1240 
     | 
    
         
             
              # We rewrite "map" calls in Bloom blocks to invoke the "pro" method
         
     | 
| 
       1328 
1241 
     | 
    
         
             
              # instead. This is fine when applied to a BudCollection; when applied to a
         
     | 
    
        data/lib/bud/errors.rb
    CHANGED
    
    | 
         @@ -12,7 +12,11 @@ module Bud 
     | 
|
| 
       12 
12 
     | 
    
         
             
              # Raised when the input program fails to compile (e.g., due to illegal
         
     | 
| 
       13 
13 
     | 
    
         
             
              # syntax).
         
     | 
| 
       14 
14 
     | 
    
         
             
              class CompileError < Error; end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
              # Raised when the program is given in an illegal location (e.g., presented as
         
     | 
| 
      
 17 
     | 
    
         
            +
              # an eval block).
         
     | 
| 
      
 18 
     | 
    
         
            +
              class IllegalSourceError < Error; end
         
     | 
| 
       15 
19 
     | 
    
         | 
| 
       16 
     | 
    
         
            -
              # Raised when evaluation halts with outstanding callbacks
         
     | 
| 
      
 20 
     | 
    
         
            +
              # Raised when evaluation halts with outstanding callbacks.
         
     | 
| 
       17 
21 
     | 
    
         
             
              class ShutdownWithCallbacksError < Error; end
         
     | 
| 
       18 
22 
     | 
    
         
             
            end
         
     |