bud 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
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