bud 0.0.5 → 0.0.6

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/lib/bud/bud_meta.rb CHANGED
@@ -148,8 +148,8 @@ class BudMeta #:nodoc: all
148
148
 
149
149
  # Check that LHS references a named collection
150
150
  return n if lhs.nil? or lhs.sexp_type != :call
151
- lhs_name = lhs[2]
152
- unless @bud_instance.tables.has_key? lhs_name.to_sym
151
+ lhs_name = lhs[2].to_sym
152
+ unless @bud_instance.tables.has_key? lhs_name
153
153
  return [n, "Table does not exist: '#{lhs_name}'"]
154
154
  end
155
155
 
@@ -182,11 +182,11 @@ class BudMeta #:nodoc: all
182
182
  strat.tick_internal
183
183
 
184
184
  # Copy computed data back into Bud runtime
185
- strat.stratum.each {|s| @bud_instance.t_stratum << s}
186
- @bud_instance.stratum_collection_map = strat.stratum.inject({}) do |memo, t|
187
- memo[t[1]] ||= []
188
- memo[t[1]] << t[0]
189
- memo
185
+ @bud_instance.stratum_collection_map = []
186
+ strat.stratum.each do |s|
187
+ @bud_instance.t_stratum << s
188
+ @bud_instance.stratum_collection_map[s[1]] ||= []
189
+ @bud_instance.stratum_collection_map[s[1]] << s[0].to_sym
190
190
  end
191
191
  strat.depends_tc.each {|d| @bud_instance.t_depends_tc << d}
192
192
  strat.cycle.each {|c| @bud_instance.t_cycle << c}
data/lib/bud/bust/bust.rb CHANGED
@@ -19,7 +19,7 @@ module Bust
19
19
  # copied from peter's code; this should probably be in the Bud runtime or in
20
20
  # some meta module
21
21
  @tables.each do |t|
22
- t_table_schema << [t[0], t[1].schema.clone]
22
+ t_table_schema << [t[0], t[1].cols.clone]
23
23
  t_table_info << [t[0], t[1].class.to_s]
24
24
  end
25
25
 
@@ -77,7 +77,7 @@ module Bust
77
77
  # instantiate a new tuple
78
78
  tuple_to_insert = []
79
79
  @body.each do |k, v|
80
- index = (eval "@bud." + table_name).schema.find_index(k.to_sym)
80
+ index = (eval "@bud." + table_name).cols.find_index(k.to_sym)
81
81
  for i in (tuple_to_insert.size..index)
82
82
  tuple_to_insert << nil
83
83
  end
@@ -14,8 +14,10 @@ module Bud
14
14
  class BudCollection
15
15
  include Enumerable
16
16
 
17
- attr_accessor :bud_instance, :locspec_idx # :nodoc: all
18
- attr_reader :schema, :tabname # :nodoc: all
17
+ # This needs to be an accessor to allow REBL to update it after cloning a
18
+ # Bud instance.
19
+ attr_accessor :bud_instance # :nodoc: all
20
+ attr_reader :cols, :key_cols, :tabname # :nodoc: all
19
21
  attr_reader :storage, :delta, :new_delta, :pending # :nodoc: all
20
22
 
21
23
  def initialize(name, bud_instance, given_schema=nil, defer_schema=false) # :nodoc: all
@@ -35,16 +37,26 @@ module Bud
35
37
  private
36
38
  def init_schema(given_schema)
37
39
  given_schema ||= {[:key]=>[:val]}
40
+
41
+ # Check that no location specifiers appear in the schema. In the case of
42
+ # channels, the location specifier has already been stripped from the
43
+ # user-specified schema.
44
+ given_schema.each do |s|
45
+ if s.to_s.start_with? "@"
46
+ raise BudError, "illegal use of location specifier (@) in column #{s} of non-channel collection #{tabname}"
47
+ end
48
+ end
49
+
38
50
  @given_schema = given_schema
39
- @schema, @key_cols = parse_schema(given_schema)
40
- @key_colnums = key_cols.map {|k| schema.index(k)}
51
+ @cols, @key_cols = parse_schema(given_schema)
52
+ @key_colnums = key_cols.map {|k| @cols.index(k)}
41
53
  setup_accessors
42
54
  end
43
55
 
44
56
  # The user-specified schema might come in two forms: a hash of Array =>
45
- # Array (key_cols => remaining columns), or simply an Array of columns (if no
46
- # key_cols were specified). Return a pair: [list of columns in entire tuple,
47
- # list of key columns]
57
+ # Array (key_cols => remaining columns), or simply an Array of columns (if
58
+ # no key_cols were specified). Return a pair: [list of (all) columns, list
59
+ # of key columns]
48
60
  private
49
61
  def parse_schema(given_schema)
50
62
  if given_schema.respond_to? :keys
@@ -56,17 +68,17 @@ module Bud
56
68
  val_cols = []
57
69
  end
58
70
 
59
- schema = key_cols + val_cols
60
- schema.each do |s|
61
- if s.class != Symbol
62
- raise BudError, "Invalid schema element \"#{s}\", type \"#{s.class}\""
71
+ cols = key_cols + val_cols
72
+ cols.each do |c|
73
+ if c.class != Symbol
74
+ raise BudError, "invalid schema element \"#{c}\", type \"#{c.class}\""
63
75
  end
64
76
  end
65
- if schema.uniq.length < schema.length
77
+ if cols.uniq.length < cols.length
66
78
  raise BudError, "schema for #{tabname} contains duplicate names"
67
79
  end
68
80
 
69
- return [schema, key_cols]
81
+ return [cols, key_cols]
70
82
  end
71
83
 
72
84
  public
@@ -74,16 +86,18 @@ module Bud
74
86
  self.class.new(tabname, bud_instance, @given_schema)
75
87
  end
76
88
 
77
- # subset of the schema (i.e. an array of attribute names) that forms the key
89
+ # produces the schema in a format that is useful as the schema specification for another table
78
90
  public
79
- def key_cols
80
- @key_cols
91
+ def schema
92
+ return nil if @cols.nil?
93
+ return key_cols if val_cols.empty?
94
+ return { key_cols => val_cols }
81
95
  end
82
96
 
83
- # subset of the schema (i.e. an array of attribute names) that is not in the key
97
+ # the columns of the collection's schema that are not part of the key
84
98
  public
85
99
  def val_cols # :nodoc: all
86
- schema - key_cols
100
+ @cols - @key_cols
87
101
  end
88
102
 
89
103
  # define methods to turn 'table.col' into a [table,col] pair
@@ -91,7 +105,7 @@ module Bud
91
105
  # j = join link, path, {link.to => path.from}
92
106
  private
93
107
  def setup_accessors
94
- s = @schema
108
+ s = @cols
95
109
  s.each do |colname|
96
110
  reserved = eval "defined?(#{colname})"
97
111
  unless (reserved.nil? or
@@ -129,7 +143,7 @@ module Bud
129
143
  # generate a tuple with the schema of this collection and nil values in each attribute
130
144
  public
131
145
  def null_tuple
132
- tuple_accessors(Array.new(@schema.length))
146
+ tuple_accessors(Array.new(@cols.length))
133
147
  end
134
148
 
135
149
  # project the collection to its key attributes
@@ -141,13 +155,13 @@ module Bud
141
155
  # project the collection to its non-key attributes
142
156
  public
143
157
  def values
144
- self.map{|t| (self.key_cols.length..self.schema.length-1).map{|i| t[i]}}
158
+ self.map{|t| (self.key_cols.length..self.cols.length-1).map{|i| t[i]}}
145
159
  end
146
160
 
147
161
  # map each item in the collection into a string, suitable for placement in stdio
148
162
  public
149
163
  def inspected
150
- self.map{|t| [t.inspect]}
164
+ [["#{@tabname}: [#{self.map{|t| "\n (#{t.map{|v| v.inspect}.join ", "})"}}]"]]
151
165
  end
152
166
 
153
167
  # akin to map, but modified for efficiency in Bloom statements
@@ -184,7 +198,7 @@ module Bud
184
198
  bud_instance.metrics[:collections][{:addr=>addr, :tabname=>tabname, :strat_num=>strat_num, :rule_num=>rule_num}] ||= 0
185
199
  bud_instance.metrics[:collections][{:addr=>addr, :tabname=>tabname, :strat_num=>strat_num, :rule_num=>rule_num}] += 1
186
200
  end
187
-
201
+
188
202
  private
189
203
  def each_from(bufs, &block) # :nodoc: all
190
204
  bufs.each do |b|
@@ -269,7 +283,7 @@ module Bud
269
283
  private
270
284
  def raise_pk_error(new_guy, old)
271
285
  keycols = @key_colnums.map{|i| old[i]}
272
- raise KeyConstraintError, "Key conflict inserting #{new_guy.inspect} into \"#{tabname}\": existing tuple #{old.inspect}, key_cols = #{keycols.inspect}"
286
+ raise KeyConstraintError, "key conflict inserting #{new_guy.inspect} into \"#{tabname}\": existing tuple #{old.inspect}, key_cols = #{keycols.inspect}"
273
287
  end
274
288
 
275
289
  private
@@ -281,15 +295,15 @@ module Bud
281
295
  raise BudTypeError, "String value used as a fact inserted into \"#{tabname}\": #{o.inspect}"
282
296
  end
283
297
 
284
- if o.length < schema.length then
298
+ if o.length < cols.length then
285
299
  # if this tuple has too few fields, pad with nil's
286
300
  old = o.clone
287
- (o.length..schema.length-1).each{|i| o << nil}
301
+ (o.length..cols.length-1).each{|i| o << nil}
288
302
  # puts "in #{@tabname}, converted #{old.inspect} to #{o.inspect}"
289
- elsif o.length > schema.length then
303
+ elsif o.length > cols.length then
290
304
  # if this tuple has more fields than usual, bundle up the
291
305
  # extras into an array
292
- o = (0..(schema.length - 1)).map{|c| o[c]} << (schema.length..(o.length - 1)).map{|c| o[c]}
306
+ o = (0..(cols.length - 1)).map{|c| o[c]} << (cols.length..(o.length - 1)).map{|c| o[c]}
293
307
  end
294
308
  return o
295
309
  end
@@ -322,18 +336,18 @@ module Bud
322
336
  private
323
337
  def check_enumerable(o)
324
338
  unless o.nil? or o.class < Enumerable
325
- raise BudTypeError, "Collection #{tabname} expected Enumerable value, not #{o.inspect} (class = #{o.class})"
339
+ raise BudTypeError, "collection #{tabname} expected Enumerable value, not #{o.inspect} (class = #{o.class})"
326
340
  end
327
341
  end
328
342
 
329
343
  # Assign self a schema, by hook or by crook. If +o+ is schemaless *and*
330
- # empty, will leave @schema as is.
344
+ # empty, will leave @cols as is.
331
345
  private
332
346
  def establish_schema(o)
333
347
  # use o's schema if available
334
348
  deduce_schema(o)
335
349
  # else use arity of first non-nil tuple of o
336
- if @schema.nil?
350
+ if @cols.nil?
337
351
  o.each do |t|
338
352
  next if t.nil?
339
353
  fit_schema(t.size)
@@ -345,11 +359,11 @@ module Bud
345
359
  # Copy over the schema from +o+ if available
346
360
  private
347
361
  def deduce_schema(o)
348
- if @schema.nil? and o.class <= Bud::BudCollection and not o.schema.nil?
362
+ if @cols.nil? and o.class <= Bud::BudCollection and not o.cols.nil?
349
363
  # must have been initialized with defer_schema==true. take schema from rhs
350
- init_schema(o.schema)
364
+ init_schema(o.cols)
351
365
  end
352
- # if nothing available, leave @schema unchanged
366
+ # if nothing available, leave @cols unchanged
353
367
  end
354
368
 
355
369
  # manufacture schema of the form [:c0, :c1, ...] with width = +arity+
@@ -377,9 +391,9 @@ module Bud
377
391
  public
378
392
  def merge(o, buf=@new_delta) # :nodoc: all
379
393
  unless o.nil?
380
- o = o.uniq.compact if o.respond_to?(:uniq)
394
+ o = o.uniq if o.respond_to?(:uniq)
381
395
  check_enumerable(o)
382
- establish_schema(o) if @schema.nil?
396
+ establish_schema(o) if @cols.nil?
383
397
 
384
398
  # it's a pity that we are massaging the tuples that already exist in the head
385
399
  o.each do |t|
@@ -402,7 +416,7 @@ module Bud
402
416
  public
403
417
  def pending_merge(o) # :nodoc: all
404
418
  check_enumerable(o)
405
- establish_schema(o) if @schema.nil?
419
+ establish_schema(o) if @cols.nil?
406
420
 
407
421
  o.each {|i| do_insert(i, @pending)}
408
422
  return self
@@ -412,7 +426,7 @@ module Bud
412
426
  superator "<+" do |o|
413
427
  pending_merge o
414
428
  end
415
-
429
+
416
430
  public
417
431
  superator "<+-" do |o|
418
432
  self <+ o
@@ -422,12 +436,12 @@ module Bud
422
436
  end
423
437
  end
424
438
  end
425
-
426
- public
439
+
440
+ public
427
441
  superator "<-+" do |o|
428
442
  self <+- o
429
443
  end
430
-
444
+
431
445
  # Called at the end of each timestep: prepare the collection for the next
432
446
  # timestep.
433
447
  public
@@ -494,11 +508,11 @@ module Bud
494
508
  memo[pkey_cols][:agg], argflag = \
495
509
  agg.send(:trans, memo[pkey_cols][:agg], p[colnum])
496
510
  if argflag == :keep or agg.send(:tie, memo[pkey_cols][:agg], p[colnum])
497
- memo[pkey_cols][:tups] << p
511
+ memo[pkey_cols][:tups] << p
498
512
  elsif argflag == :replace
499
513
  memo[pkey_cols][:tups] = [p]
500
514
  elsif argflag.class <= Array and argflag[0] == :delete
501
- memo[pkey_cols][:tups] -= argflag[1..-1]
515
+ memo[pkey_cols][:tups] -= argflag[1..-1]
502
516
  end
503
517
  end
504
518
  memo
@@ -510,7 +524,7 @@ module Bud
510
524
  tups.each do |k,v|
511
525
  finalaggs[k] = agg.send(:final, v[:agg])
512
526
  end
513
-
527
+
514
528
  # and winnow the tups to match
515
529
  finalaggs.each do |k,v|
516
530
  tups[k][:tups].each do |t|
@@ -566,14 +580,12 @@ module Bud
566
580
  def *(collection)
567
581
  join([self, collection])
568
582
  end
569
-
583
+
570
584
  # AntiJoin
571
585
  public
572
- def notin(coll,*preds, &blk)
573
- @origpreds = preds
574
- @schema = schema
575
- return BudJoin.new([self,coll], @bud_instance).anti(*preds,&blk)
576
- end
586
+ def notin(coll, *preds, &blk)
587
+ return BudJoin.new([self, coll], @bud_instance).anti(*preds, &blk)
588
+ end
577
589
 
578
590
  # SQL-style grouping. first argument is an array of attributes to group by.
579
591
  # Followed by a variable-length list of aggregates over attributes (e.g. +min(:x)+)
@@ -587,7 +599,7 @@ module Bud
587
599
  elsif k[2] and k[2].class == Symbol
588
600
  k[2]
589
601
  else
590
- raise Bud::CompileError, "Invalid grouping key"
602
+ raise Bud::CompileError, "invalid grouping key"
591
603
  end
592
604
  end
593
605
  aggcolsdups = aggpairs.map{|ap| ap[0].class.name.split("::").last}
@@ -671,16 +683,16 @@ module Bud
671
683
  given_schema = Marshal.load(Marshal.dump(given_schema))
672
684
 
673
685
  unless @is_loopback
674
- the_schema, the_key_cols = parse_schema(given_schema)
675
- spec_count = the_schema.count {|s| s.to_s.start_with? "@"}
686
+ the_cols, the_key_cols = parse_schema(given_schema)
687
+ spec_count = the_cols.count {|c| c.to_s.start_with? "@"}
676
688
  if spec_count == 0
677
- raise BudError, "Missing location specifier for channel '#{name}'"
689
+ raise BudError, "missing location specifier for channel '#{name}'"
678
690
  end
679
691
  if spec_count > 1
680
- raise BudError, "Multiple location specifiers for channel '#{name}'"
692
+ raise BudError, "multiple location specifiers for channel '#{name}'"
681
693
  end
682
694
 
683
- the_val_cols = the_schema - the_key_cols
695
+ the_val_cols = the_cols - the_key_cols
684
696
  @locspec_idx = remove_at_sign!(the_key_cols)
685
697
  if @locspec_idx.nil?
686
698
  val_idx = remove_at_sign!(the_val_cols)
@@ -713,7 +725,7 @@ module Bud
713
725
  lsplit[1] = lsplit[1].to_i
714
726
  return lsplit
715
727
  rescue Exception => e
716
- raise BudError, "Illegal location specifier in tuple #{t.inspect} for channel \"#{tabname}\": #{e.to_s}"
728
+ raise BudError, "illegal location specifier in tuple #{t.inspect} for channel \"#{tabname}\": #{e.to_s}"
717
729
  end
718
730
  end
719
731
 
@@ -751,11 +763,11 @@ module Bud
751
763
  def payloads
752
764
  return self.pro if @is_loopback
753
765
 
754
- if schema.size > 2
766
+ if cols.size > 2
755
767
  # bundle up each tuple's non-locspec fields into an array
756
768
  retval = case @locspec_idx
757
769
  when 0 then self.pro{|t| t[1..(t.size-1)]}
758
- when (schema.size - 1) then self.pro{|t| t[0..(t.size-2)]}
770
+ when (cols.size - 1) then self.pro{|t| t[0..(t.size-2)]}
759
771
  else self.pro{|t| t[0..(@locspec_idx-1)] + t[@locspec_idx+1..(t.size-1)]}
760
772
  end
761
773
  else
@@ -770,13 +782,13 @@ module Bud
770
782
  end
771
783
 
772
784
  superator "<+" do |o|
773
- raise BudError, "Illegal use of <+ with channel '#{@tabname}' on left"
785
+ raise BudError, "illegal use of <+ with channel '#{@tabname}' on left"
774
786
  end
775
787
 
776
788
  undef merge
777
789
 
778
790
  def <=(o)
779
- raise BudError, "Illegal use of <= with channel '#{@tabname}' on left"
791
+ raise BudError, "illegal use of <= with channel '#{@tabname}' on left"
780
792
  end
781
793
  end
782
794
 
@@ -837,7 +849,7 @@ module Bud
837
849
 
838
850
  public
839
851
  def <=(o) #:nodoc: all
840
- raise BudError, "Illegal use of <= with terminal '#{@tabname}' on left"
852
+ raise BudError, "illegal use of <= with terminal '#{@tabname}' on left"
841
853
  end
842
854
 
843
855
  superator "<~" do |o|
@@ -855,19 +867,19 @@ module Bud
855
867
 
856
868
  class BudPeriodic < BudCollection # :nodoc: all
857
869
  def <=(o)
858
- raise BudError, "Illegal use of <= with periodic '#{tabname}' on left"
870
+ raise BudError, "illegal use of <= with periodic '#{tabname}' on left"
859
871
  end
860
872
 
861
873
  superator "<~" do |o|
862
- raise BudError, "Illegal use of <~ with periodic '#{tabname}' on left"
874
+ raise BudError, "illegal use of <~ with periodic '#{tabname}' on left"
863
875
  end
864
876
 
865
877
  superator "<-" do |o|
866
- raise BudError, "Illegal use of <- with periodic '#{tabname}' on left"
878
+ raise BudError, "illegal use of <- with periodic '#{tabname}' on left"
867
879
  end
868
880
 
869
881
  superator "<+" do |o|
870
- raise BudError, "Illegal use of <+ with periodic '#{tabname}' on left"
882
+ raise BudError, "illegal use of <+ with periodic '#{tabname}' on left"
871
883
  end
872
884
  end
873
885
 
@@ -907,11 +919,11 @@ module Bud
907
919
 
908
920
  class BudReadOnly < BudScratch # :nodoc: all
909
921
  superator "<+" do |o|
910
- raise CompileError, "Illegal use of <+ with read-only collection '#{@tabname}' on left"
922
+ raise CompileError, "illegal use of <+ with read-only collection '#{@tabname}' on left"
911
923
  end
912
924
  public
913
925
  def merge(o) #:nodoc: all
914
- raise CompileError, "Illegal use of <= with read-only collection '#{@tabname}' on left"
926
+ raise CompileError, "illegal use of <= with read-only collection '#{@tabname}' on left"
915
927
  end
916
928
  end
917
929
 
@@ -160,7 +160,7 @@ module EC2Deploy
160
160
  # Update the Bud gem
161
161
  channel = session.open_channel do |ch|
162
162
  channel.request_pty do |_, success|
163
- raise "Couldn't open a PTY on #{t.node}" if !success
163
+ raise "couldn't open a PTY on #{t.node}" if !success
164
164
  end
165
165
  channel.exec("sudo gem update --no-ri --no-rdoc bud")
166
166
  end