bud 0.0.7 → 0.0.8
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/bin/budplot +97 -8
- data/bin/budvis +1 -2
- data/docs/cheat.md +1 -1
- data/lib/bud/aggs.rb +2 -1
- data/lib/bud/bud_meta.rb +8 -7
- data/lib/bud/collections.rb +36 -48
- data/lib/bud/graphs.rb +48 -21
- data/lib/bud/joins.rb +1 -1
- data/lib/bud/meta_algebra.rb +168 -0
- data/lib/bud/monkeypatch.rb +32 -5
- data/lib/bud/rewrite.rb +53 -14
- data/lib/bud/server.rb +25 -4
- data/lib/bud/state.rb +13 -14
- data/lib/bud/storage/dbm.rb +19 -8
- data/lib/bud/storage/tokyocabinet.rb +18 -8
- data/lib/bud/viz.rb +7 -5
- data/lib/bud/viz_util.rb +93 -11
- data/lib/bud.rb +30 -16
- metadata +4 -3
data/bin/budplot
CHANGED
@@ -4,7 +4,9 @@ require 'bud'
|
|
4
4
|
require 'bud/bud_meta'
|
5
5
|
require 'bud/depanalysis'
|
6
6
|
require 'bud/graphs'
|
7
|
+
require 'bud/meta_algebra'
|
7
8
|
require 'bud/viz_util'
|
9
|
+
require 'getopt/std'
|
8
10
|
|
9
11
|
include VizUtil
|
10
12
|
|
@@ -42,12 +44,34 @@ def make_instance(mods)
|
|
42
44
|
|
43
45
|
def_lines = ["class FooBar",
|
44
46
|
"include Bud",
|
47
|
+
"include MetaAlgebra",
|
48
|
+
"include MetaReports",
|
45
49
|
mods.map {|m| "include #{m}"},
|
46
50
|
"end"
|
47
51
|
]
|
48
52
|
class_def = def_lines.flatten.join("\n")
|
49
53
|
eval(class_def)
|
50
|
-
FooBar.new
|
54
|
+
f =FooBar.new
|
55
|
+
3.times{ f.tick }
|
56
|
+
f
|
57
|
+
end
|
58
|
+
|
59
|
+
def trace_counts(begins)
|
60
|
+
complexity = {:data => {}, :coord => {}}
|
61
|
+
if !begins[:start].nil?
|
62
|
+
begins[:start].each_pair do |k, v|
|
63
|
+
if @data and @data[k]
|
64
|
+
complexity[:data][k] = @data[k].length
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
begins[:finish].each_pair do |k, v|
|
69
|
+
if @data and @data[k]
|
70
|
+
complexity[:coord][k] = @data[k].length
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
complexity
|
51
75
|
end
|
52
76
|
|
53
77
|
def process(mods)
|
@@ -79,12 +103,44 @@ def process(mods)
|
|
79
103
|
end
|
80
104
|
|
81
105
|
viz_name = "bud_doc/" + mods.join("_") + "_viz"
|
82
|
-
|
83
|
-
graph_from_instance(d, "#{viz_name}
|
84
|
-
graph_from_instance(d, "#{viz_name}
|
106
|
+
graph_from_instance(d, "#{viz_name}_collapsed", "bud_doc", true, nil, @data)
|
107
|
+
graph_from_instance(d, "#{viz_name}_expanded", "bud_doc", false, nil, @data)
|
108
|
+
begins = graph_from_instance(d, "#{viz_name}_expanded_dot", "bud_doc", false, "dot", @data)
|
109
|
+
|
110
|
+
|
111
|
+
complexity = trace_counts(begins)
|
112
|
+
# try to figure out the degree of the async edges
|
113
|
+
deg = find_degrees(d, @data)
|
114
|
+
unless deg.nil?
|
115
|
+
deg.each_pair do |k, v|
|
116
|
+
puts "DEGREE: #{k} = #{v.keys.length}"
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
write_index(inp, outp, priv, viz_name, complexity)
|
85
121
|
end
|
86
122
|
|
87
|
-
def
|
123
|
+
def find_degrees(inst, data)
|
124
|
+
degree = {}
|
125
|
+
return if data.nil?
|
126
|
+
data.each_pair do |k, v|
|
127
|
+
tab = inst.tables[k.gsub("_snd", "").to_sym]
|
128
|
+
if !tab.nil?
|
129
|
+
if tab.class == Bud::BudChannel
|
130
|
+
v.each_pair do |k2, v2|
|
131
|
+
v2.each do |row|
|
132
|
+
loc = row[tab.locspec_idx]
|
133
|
+
degree[k] ||= {}
|
134
|
+
degree[k][loc] = true
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
return degree
|
141
|
+
end
|
142
|
+
|
143
|
+
def write_index(inp, outp, priv, viz_name, cx)
|
88
144
|
f = File.open("bud_doc/index.html", "w")
|
89
145
|
f.puts "<html>"
|
90
146
|
f.puts "<embed src=\"#{ENV['PWD']}/#{viz_name}_collapsed.svg\" width=\"100%\" height=\"60%\" type=\"image/svg+xml\" pluginspage=\"http://www.adobe.com/svg/viewer/install/\" />"
|
@@ -97,14 +153,24 @@ def write_index(inp, outp, priv, viz_name)
|
|
97
153
|
f.puts "<h2>Output Interfaces</h2>"
|
98
154
|
do_table(f, outp)
|
99
155
|
f.puts "</td><td>"
|
100
|
-
f.puts "<h2>
|
101
|
-
|
102
|
-
f
|
156
|
+
f.puts "<h2>Trace Analysis Results</h2>"
|
157
|
+
f.puts "<h3>Data Complexity</h3>"
|
158
|
+
do_cx(f, cx[:data])
|
159
|
+
f.puts "<h3>Coordination Complexity</h3>"
|
160
|
+
do_cx(f, cx[:coord])
|
103
161
|
f.puts "</tr></table>"
|
104
162
|
f.puts "</html>"
|
105
163
|
f.close
|
106
164
|
end
|
107
165
|
|
166
|
+
def do_cx(f, cx)
|
167
|
+
f.puts "<table border='1'>"
|
168
|
+
cx.each_pair do |k, v|
|
169
|
+
f.puts "<tr><td>#{k}</td><td>#{v.inspect}</td></tr>"
|
170
|
+
end
|
171
|
+
f.puts "</table>"
|
172
|
+
end
|
173
|
+
|
108
174
|
def do_table(f, info)
|
109
175
|
f.puts "<table border='1'>"
|
110
176
|
info.sort{|a, b| a[0].to_s <=> b[0].to_s}.each do |tbl_name, tbl_impl|
|
@@ -117,11 +183,34 @@ def do_table(f, info)
|
|
117
183
|
f.puts "</table>"
|
118
184
|
end
|
119
185
|
|
186
|
+
def get_trace_data
|
187
|
+
data = nil
|
188
|
+
|
189
|
+
if @opts["t"]
|
190
|
+
data = {}
|
191
|
+
traces = @opts['t'].class == String ? [@opts['t']] : @opts['t']
|
192
|
+
traces.each do |t|
|
193
|
+
meta, da = get_meta2(t)
|
194
|
+
da.each do |d|
|
195
|
+
data[d[1]] ||= {}
|
196
|
+
data[d[1]][d[0]] ||= []
|
197
|
+
data[d[1]][d[0]] << d[2]
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
data
|
202
|
+
end
|
203
|
+
|
120
204
|
if ARGV.length < 2
|
121
205
|
puts "Usage: budplot LIST_OF_FILES LIST_OF_MODULES_OR_CLASSES"
|
122
206
|
exit
|
123
207
|
end
|
124
208
|
|
209
|
+
@opts = Getopt::Std.getopts("t:")
|
210
|
+
|
211
|
+
|
212
|
+
|
213
|
+
@data = get_trace_data
|
125
214
|
`mkdir bud_doc`
|
126
215
|
|
127
216
|
modules = []
|
data/bin/budvis
CHANGED
@@ -28,10 +28,9 @@ usage unless ARGV[0]
|
|
28
28
|
usage if ARGV[0] == '--help'
|
29
29
|
|
30
30
|
meta, data = get_meta2(BUD_DBM_DIR)
|
31
|
-
vh = VizHelper.new(meta[:tabinf], meta[:cycle], meta[:depends], meta[:rules], ARGV[0])
|
31
|
+
vh = VizHelper.new(meta[:tabinf], meta[:cycle], meta[:depends], meta[:rules], ARGV[0], meta[:provides])
|
32
32
|
data.each do |d|
|
33
33
|
vh.full_info << d
|
34
34
|
end
|
35
|
-
|
36
35
|
vh.tick
|
37
36
|
vh.summarize(ARGV[0], meta[:schminf])
|
data/docs/cheat.md
CHANGED
@@ -196,7 +196,7 @@ implicit map:
|
|
196
196
|
end
|
197
197
|
|
198
198
|
## BudCollection-Specific Methods ##
|
199
|
-
`bc.schema`: returns the schema of `bc` (Hash of key column names => non-key column names)<br>
|
199
|
+
`bc.schema`: returns the schema of `bc` (Hash of key column names => non-key column names). Note that for channels, this omits the location specifier (<tt>@</tt>).<br>
|
200
200
|
|
201
201
|
`bc.cols`: returns the column names in `bc` as an Array<br>
|
202
202
|
|
data/lib/bud/aggs.rb
CHANGED
@@ -181,7 +181,8 @@ module Bud
|
|
181
181
|
end
|
182
182
|
|
183
183
|
# aggregate method to be used in Bud::BudCollection.group.
|
184
|
-
# accumulates all x inputs into an array
|
184
|
+
# accumulates all x inputs into an array. note that the order of the elements
|
185
|
+
# in the resulting array is undefined.
|
185
186
|
def accum(x)
|
186
187
|
[Accum.new, x]
|
187
188
|
end
|
data/lib/bud/bud_meta.rb
CHANGED
@@ -49,7 +49,7 @@ class BudMeta #:nodoc: all
|
|
49
49
|
@bud_instance.sinks[s.first] = true
|
50
50
|
end
|
51
51
|
|
52
|
-
dump_rewrite(
|
52
|
+
dump_rewrite(no_attr_rewrite_strata) if @bud_instance.options[:dump_rewrite]
|
53
53
|
|
54
54
|
return rewritten_strata, no_attr_rewrite_strata
|
55
55
|
end
|
@@ -97,13 +97,13 @@ class BudMeta #:nodoc: all
|
|
97
97
|
unless rv.nil?
|
98
98
|
if rv.class <= Sexp
|
99
99
|
error_pt = rv
|
100
|
-
error_msg = "
|
100
|
+
error_msg = "parse error"
|
101
101
|
else
|
102
102
|
error_pt, error_msg = rv
|
103
103
|
end
|
104
104
|
|
105
|
-
# try to
|
106
|
-
#
|
105
|
+
# try to dump the source code associated with the problematic block, so as
|
106
|
+
# to produce a more meaningful error message.
|
107
107
|
begin
|
108
108
|
code = Ruby2Ruby.new.process(Marshal.load(Marshal.dump(error_pt)))
|
109
109
|
src_msg = "\nCode: #{code}"
|
@@ -139,7 +139,7 @@ class BudMeta #:nodoc: all
|
|
139
139
|
|
140
140
|
# Check for a common case
|
141
141
|
if n.sexp_type == :lasgn
|
142
|
-
return [n, "
|
142
|
+
return [n, "illegal operator: '='"]
|
143
143
|
end
|
144
144
|
return pt unless n.sexp_type == :call and n.length == 4
|
145
145
|
|
@@ -150,10 +150,10 @@ class BudMeta #:nodoc: all
|
|
150
150
|
return n if lhs.nil? or lhs.sexp_type != :call
|
151
151
|
lhs_name = lhs[2].to_sym
|
152
152
|
unless @bud_instance.tables.has_key? lhs_name
|
153
|
-
return [n, "
|
153
|
+
return [n, "collection does not exist: '#{lhs_name}'"]
|
154
154
|
end
|
155
155
|
|
156
|
-
return [n, "
|
156
|
+
return [n, "illegal operator: '#{op}'"] unless [:<, :<=].include? op
|
157
157
|
|
158
158
|
# Check superator invocation. A superator that begins with "<" is parsed
|
159
159
|
# as a call to the binary :< operator. The right operand to :< is a :call
|
@@ -195,6 +195,7 @@ class BudMeta #:nodoc: all
|
|
195
195
|
else
|
196
196
|
top = 1
|
197
197
|
end
|
198
|
+
|
198
199
|
return top
|
199
200
|
end
|
200
201
|
|
data/lib/bud/collections.rb
CHANGED
@@ -149,7 +149,7 @@ module Bud
|
|
149
149
|
# project the collection to its key attributes
|
150
150
|
public
|
151
151
|
def keys
|
152
|
-
self.map{|t|
|
152
|
+
self.map{|t| get_key_vals(t)}
|
153
153
|
end
|
154
154
|
|
155
155
|
# project the collection to its non-key attributes
|
@@ -255,6 +255,7 @@ module Bud
|
|
255
255
|
def [](k)
|
256
256
|
# assumes that key is in storage or delta, but not both
|
257
257
|
# is this enforced in do_insert?
|
258
|
+
check_enumerable(k)
|
258
259
|
t = @storage[k]
|
259
260
|
return t.nil? ? @delta[k] : t
|
260
261
|
end
|
@@ -264,7 +265,7 @@ module Bud
|
|
264
265
|
def include?(item)
|
265
266
|
return true if key_cols.nil? or (key_cols.empty? and length > 0)
|
266
267
|
return false if item.nil? or item.empty?
|
267
|
-
key =
|
268
|
+
key = get_key_vals(item)
|
268
269
|
return (item == self[key])
|
269
270
|
end
|
270
271
|
|
@@ -282,8 +283,8 @@ module Bud
|
|
282
283
|
|
283
284
|
private
|
284
285
|
def raise_pk_error(new_guy, old)
|
285
|
-
|
286
|
-
raise KeyConstraintError, "key conflict inserting #{new_guy.inspect} into \"#{tabname}\": existing tuple #{old.inspect},
|
286
|
+
key = get_key_vals(old)
|
287
|
+
raise KeyConstraintError, "key conflict inserting #{new_guy.inspect} into \"#{tabname}\": existing tuple #{old.inspect}, key = #{key.inspect}"
|
287
288
|
end
|
288
289
|
|
289
290
|
private
|
@@ -308,15 +309,22 @@ module Bud
|
|
308
309
|
return o
|
309
310
|
end
|
310
311
|
|
312
|
+
private
|
313
|
+
def get_key_vals(t)
|
314
|
+
@key_colnums.map do |i|
|
315
|
+
t[i]
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
311
319
|
private
|
312
320
|
def do_insert(o, store)
|
313
321
|
return if o.nil? # silently ignore nils resulting from map predicates failing
|
314
322
|
o = prep_tuple(o)
|
315
|
-
|
323
|
+
key = get_key_vals(o)
|
316
324
|
|
317
|
-
old = store[
|
325
|
+
old = store[key]
|
318
326
|
if old.nil?
|
319
|
-
store[
|
327
|
+
store[key] = tuple_accessors(o)
|
320
328
|
else
|
321
329
|
raise_pk_error(o, old) unless old == o
|
322
330
|
end
|
@@ -374,10 +382,10 @@ module Bud
|
|
374
382
|
end
|
375
383
|
|
376
384
|
private
|
377
|
-
def include_any_buf?(t,
|
385
|
+
def include_any_buf?(t, key)
|
378
386
|
bufs = [self, @delta, @new_delta]
|
379
387
|
bufs.each do |b|
|
380
|
-
old = b[
|
388
|
+
old = b[key]
|
381
389
|
next if old.nil?
|
382
390
|
if old != t
|
383
391
|
raise_pk_error(t, old)
|
@@ -391,16 +399,15 @@ module Bud
|
|
391
399
|
public
|
392
400
|
def merge(o, buf=@new_delta) # :nodoc: all
|
393
401
|
unless o.nil?
|
394
|
-
o = o.uniq if o.respond_to?(:uniq)
|
395
402
|
check_enumerable(o)
|
396
403
|
establish_schema(o) if @cols.nil?
|
397
404
|
|
398
|
-
# it's a pity that we are massaging
|
405
|
+
# it's a pity that we are massaging tuples that may be dups
|
399
406
|
o.each do |t|
|
400
407
|
next if t.nil? or t == []
|
401
408
|
t = prep_tuple(t)
|
402
|
-
|
403
|
-
buf[
|
409
|
+
key = get_key_vals(t)
|
410
|
+
buf[key] = tuple_accessors(t) unless include_any_buf?(t, key)
|
404
411
|
end
|
405
412
|
end
|
406
413
|
return self
|
@@ -432,7 +439,7 @@ module Bud
|
|
432
439
|
self <+ o
|
433
440
|
self <- o.map do |t|
|
434
441
|
unless t.nil?
|
435
|
-
self[
|
442
|
+
self[get_key_vals(t)]
|
436
443
|
end
|
437
444
|
end
|
438
445
|
end
|
@@ -461,9 +468,14 @@ module Bud
|
|
461
468
|
@new_delta = {}
|
462
469
|
end
|
463
470
|
|
464
|
-
|
465
|
-
def
|
466
|
-
@storage.
|
471
|
+
public
|
472
|
+
def length
|
473
|
+
@storage.length
|
474
|
+
end
|
475
|
+
|
476
|
+
public
|
477
|
+
def empty?
|
478
|
+
@storage.empty?
|
467
479
|
end
|
468
480
|
|
469
481
|
######## aggs
|
@@ -480,7 +492,6 @@ module Bud
|
|
480
492
|
end
|
481
493
|
end
|
482
494
|
|
483
|
-
|
484
495
|
# a generalization of argmin/argmax to arbitrary exemplary aggregates.
|
485
496
|
# for each distinct value of the grouping key columns, return the items in that group
|
486
497
|
# that have the value of the exemplary aggregate +aggname+
|
@@ -592,7 +603,7 @@ module Bud
|
|
592
603
|
# Attributes can be referenced as symbols, or as +collection_name.attribute_name+
|
593
604
|
public
|
594
605
|
def group(key_cols, *aggpairs)
|
595
|
-
key_cols
|
606
|
+
key_cols ||= []
|
596
607
|
keynames = key_cols.map do |k|
|
597
608
|
if k.class == Symbol
|
598
609
|
k
|
@@ -892,15 +903,15 @@ module Bud
|
|
892
903
|
public
|
893
904
|
def tick #:nodoc: all
|
894
905
|
@to_delete.each do |tuple|
|
895
|
-
|
896
|
-
if @storage[
|
897
|
-
@storage.delete
|
906
|
+
key = get_key_vals(tuple)
|
907
|
+
if @storage[key] == tuple
|
908
|
+
@storage.delete key
|
898
909
|
end
|
899
910
|
end
|
900
|
-
@pending.each do |
|
901
|
-
old = @storage[
|
911
|
+
@pending.each do |key, tuple|
|
912
|
+
old = @storage[key]
|
902
913
|
if old.nil?
|
903
|
-
@storage[
|
914
|
+
@storage[key] = tuple
|
904
915
|
else
|
905
916
|
raise_pk_error(tuple, old) unless tuple == old
|
906
917
|
end
|
@@ -957,26 +968,3 @@ module Bud
|
|
957
968
|
end
|
958
969
|
end
|
959
970
|
end
|
960
|
-
|
961
|
-
module Enumerable
|
962
|
-
public
|
963
|
-
# monkeypatch to Enumerable to rename collections and their schemas
|
964
|
-
def rename(new_tabname, new_schema=nil)
|
965
|
-
budi = (respond_to?(:bud_instance)) ? bud_instance : nil
|
966
|
-
if new_schema.nil? and respond_to?(:schema)
|
967
|
-
new_schema = schema
|
968
|
-
end
|
969
|
-
scr = Bud::BudScratch.new(new_tabname.to_s, budi, new_schema)
|
970
|
-
scr.uniquify_tabname
|
971
|
-
scr.merge(self, scr.storage)
|
972
|
-
scr
|
973
|
-
end
|
974
|
-
|
975
|
-
public
|
976
|
-
# We rewrite "map" calls in Bloom blocks to invoke the "pro" method
|
977
|
-
# instead. This is fine when applied to a BudCollection; when applied to a
|
978
|
-
# normal Enumerable, just treat pro as an alias for map.
|
979
|
-
def pro(&blk)
|
980
|
-
map(&blk)
|
981
|
-
end
|
982
|
-
end
|
data/lib/bud/graphs.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
require 'rubygems'
|
2
|
-
require 'digest/md5'
|
3
2
|
require 'graphviz'
|
4
3
|
|
5
4
|
class GraphGen #:nodoc: all
|
6
5
|
attr_reader :nodes
|
7
6
|
|
8
|
-
def initialize(tableinfo, builtin_tables, cycle, name, budtime, collapse=false, cardinalities={})
|
7
|
+
def initialize(tableinfo, builtin_tables, cycle, name, budtime, collapse=false, cardinalities={}, pathsto={}, begins={})
|
9
8
|
@graph = GraphViz.new(:G, :type => :digraph, :label => "")
|
9
|
+
#@graph.dim = 2
|
10
10
|
@graph.node[:fontname] = "Times-Roman"
|
11
11
|
@graph.node[:fontsize] = 18
|
12
12
|
@graph.edge[:fontname] = "Times-Roman"
|
@@ -16,6 +16,8 @@ class GraphGen #:nodoc: all
|
|
16
16
|
@collapse = collapse
|
17
17
|
@budtime = budtime
|
18
18
|
@builtin_tables = builtin_tables
|
19
|
+
@pathsto = pathsto
|
20
|
+
@begins = begins
|
19
21
|
|
20
22
|
# map: table name -> type
|
21
23
|
@tabinf = {}
|
@@ -87,20 +89,46 @@ class GraphGen #:nodoc: all
|
|
87
89
|
end
|
88
90
|
end
|
89
91
|
|
92
|
+
def color_node(paths)
|
93
|
+
return "" if paths.nil?
|
94
|
+
|
95
|
+
case paths[0][:val]
|
96
|
+
when :A, :N
|
97
|
+
"yellow"
|
98
|
+
when :D, :G
|
99
|
+
"red"
|
100
|
+
else
|
101
|
+
puts "UNKNOWN tag #{paths[0][:val]} class #{paths[0][:val].class}"
|
102
|
+
"black"
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
90
106
|
def addonce(node, negcluster, inhead=false)
|
91
107
|
if !@nodes[node]
|
92
|
-
@nodes[node] = @graph.
|
108
|
+
@nodes[node] = @graph.add_nodes(node)
|
109
|
+
node_p = @nodes[node]
|
110
|
+
node_p.label = node
|
111
|
+
if @begins[:finish] and @begins[:finish][node]
|
112
|
+
# point of divergence.
|
113
|
+
node_p.penwidth = 4
|
114
|
+
end
|
115
|
+
|
93
116
|
if @cards and @cards[node]
|
94
|
-
|
117
|
+
node_p.label = "#{node}\n (#{@cards[node].to_s})"
|
118
|
+
node_p.color = "green"
|
95
119
|
else
|
96
|
-
@
|
120
|
+
p = @pathsto[node].nil? ? "" : "\n(#{@pathsto[node][0][:val]})"
|
121
|
+
node_p.label = node + p
|
122
|
+
node_p.color = color_node(@pathsto[node])
|
97
123
|
end
|
124
|
+
else
|
125
|
+
node_p = @nodes[node]
|
98
126
|
end
|
99
127
|
|
100
128
|
if @budtime == -1
|
101
|
-
|
129
|
+
node_p.URL = "#{node}.html" if inhead
|
102
130
|
else
|
103
|
-
|
131
|
+
node_p.URL = "javascript:openWin(\"#{node}\", #{@budtime})"
|
104
132
|
end
|
105
133
|
|
106
134
|
if negcluster
|
@@ -116,13 +144,13 @@ class GraphGen #:nodoc: all
|
|
116
144
|
res = res + ", " + p
|
117
145
|
end
|
118
146
|
end
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
147
|
+
node_p.label = res
|
148
|
+
node_p.color = "red"
|
149
|
+
node_p.shape = "octagon"
|
150
|
+
node_p.penwidth = 3
|
151
|
+
node_p.URL = "#{File.basename(@name).gsub(".staging", "").gsub("collapsed", "expanded")}.svg"
|
124
152
|
elsif @tabinf[node] and (@tabinf[node] == "Bud::BudTable")
|
125
|
-
|
153
|
+
node_p.shape = "rect"
|
126
154
|
end
|
127
155
|
end
|
128
156
|
|
@@ -134,9 +162,10 @@ class GraphGen #:nodoc: all
|
|
134
162
|
|
135
163
|
ekey = body + head
|
136
164
|
if !@edges[ekey]
|
137
|
-
@edges[ekey] = @graph.
|
165
|
+
@edges[ekey] = @graph.add_edges(@nodes[body], @nodes[head], :penwidth => 5)
|
138
166
|
@edges[ekey].arrowsize = 2
|
139
167
|
|
168
|
+
@edges[ekey].color = (@nodes[body]["color"].source || "")
|
140
169
|
@edges[ekey].URL = "#{rule_id}.html" unless rule_id.nil?
|
141
170
|
if head =~ /_msg\z/
|
142
171
|
@edges[ekey].minlen = 2
|
@@ -212,7 +241,7 @@ class GraphGen #:nodoc: all
|
|
212
241
|
if output.nil?
|
213
242
|
@graph.output(:svg => @name)
|
214
243
|
else
|
215
|
-
@graph.output(output => @name)
|
244
|
+
@graph.output(output.to_sym => @name)
|
216
245
|
end
|
217
246
|
end
|
218
247
|
end
|
@@ -234,9 +263,8 @@ class SpaceTime
|
|
234
263
|
@head = {}
|
235
264
|
last = nil
|
236
265
|
processes.each_with_index do |p, i|
|
237
|
-
#@head[p] = @hdr.add_node("process #{p}(#{i})")#, :color => "white", :label => "")
|
238
266
|
@subs[p] = @g.subgraph("buster_#{i+1}")
|
239
|
-
@head[p] = @hdr.
|
267
|
+
@head[p] = @hdr.add_nodes("process #{p}(#{i})", :group => p)#, :color => "white", :label => "")
|
240
268
|
end
|
241
269
|
end
|
242
270
|
|
@@ -272,10 +300,9 @@ class SpaceTime
|
|
272
300
|
if @links
|
273
301
|
url = "DBM_#{k}/tm_#{item}.svg"
|
274
302
|
end
|
275
|
-
snd = @subs[k].
|
276
|
-
|
303
|
+
snd = @subs[k].add_nodes(label, {:label => item.to_s, :width => 0.1, :height => 0.1, :fontsize => 6, :group => k, :URL => url})
|
277
304
|
unless @head[k].id == snd.id
|
278
|
-
@subs[k].
|
305
|
+
@subs[k].add_edges(@head[k], snd, :weight => 2)
|
279
306
|
@head[k] = snd
|
280
307
|
end
|
281
308
|
end
|
@@ -295,7 +322,7 @@ class SpaceTime
|
|
295
322
|
def finish(file, fmt=nil)
|
296
323
|
@edges.each_pair do |k, v|
|
297
324
|
lbl = v[3] > 1 ? "#{v[2]}(#{v[3]})" : v[2]
|
298
|
-
@g.
|
325
|
+
@g.add_edges(v[0], v[1], :label => lbl, :color => "red", :weight => 1)
|
299
326
|
end
|
300
327
|
if fmt.nil?
|
301
328
|
@g.output(:svg => "#{file}.svg")
|
data/lib/bud/joins.rb
CHANGED
@@ -291,7 +291,7 @@ module Bud
|
|
291
291
|
otherpreds = allpreds - @localpreds
|
292
292
|
unless otherpreds.empty?
|
293
293
|
unless @rels[1].class <= Bud::BudJoin
|
294
|
-
raise Bud::CompileError, "join predicates don't match
|
294
|
+
raise Bud::CompileError, "join predicates don't match collections being joined: #{otherpreds.inspect}"
|
295
295
|
end
|
296
296
|
@rels[1].setup_preds(otherpreds)
|
297
297
|
end
|