bud 0.0.3 → 0.0.4
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/README +33 -16
- data/bin/budplot +42 -65
- data/bin/budtimelines +235 -0
- data/bin/budvis +24 -122
- data/bin/rebl +1 -0
- data/docs/README.md +21 -10
- data/docs/bfs.md +4 -6
- data/docs/c.html +251 -0
- data/docs/cheat.md +45 -30
- data/docs/deploy.md +26 -26
- data/docs/getstarted.md +6 -4
- data/docs/visualizations.md +43 -31
- data/examples/chat/chat.rb +4 -9
- data/examples/chat/chat_server.rb +1 -8
- data/examples/deploy/deploy_ip_port +1 -0
- data/examples/deploy/keys.rb +5 -0
- data/examples/deploy/tokenring-ec2.rb +9 -9
- data/examples/deploy/{tokenring-local.rb → tokenring-fork.rb} +3 -5
- data/examples/deploy/tokenring-thread.rb +15 -0
- data/examples/deploy/tokenring.rb +25 -17
- data/lib/bud/aggs.rb +87 -25
- data/lib/bud/bud_meta.rb +48 -31
- data/lib/bud/bust/bust.rb +16 -15
- data/lib/bud/collections.rb +207 -232
- data/lib/bud/depanalysis.rb +1 -0
- data/lib/bud/deploy/countatomicdelivery.rb +8 -20
- data/lib/bud/deploy/deployer.rb +16 -16
- data/lib/bud/deploy/ec2deploy.rb +34 -35
- data/lib/bud/deploy/forkdeploy.rb +90 -0
- data/lib/bud/deploy/threaddeploy.rb +38 -0
- data/lib/bud/graphs.rb +103 -199
- data/lib/bud/joins.rb +190 -41
- data/lib/bud/monkeypatch.rb +84 -0
- data/lib/bud/rebl.rb +8 -1
- data/lib/bud/rewrite.rb +152 -49
- data/lib/bud/server.rb +1 -0
- data/lib/bud/state.rb +24 -10
- data/lib/bud/storage/dbm.rb +170 -0
- data/lib/bud/storage/tokyocabinet.rb +5 -1
- data/lib/bud/stratify.rb +6 -7
- data/lib/bud/viz.rb +31 -17
- data/lib/bud/viz_util.rb +204 -0
- data/lib/bud.rb +271 -244
- data/lib/bud.rb.orig +806 -0
- metadata +43 -22
- data/docs/bfs.raw +0 -251
- data/docs/diffs +0 -181
- data/examples/basics/out +0 -1103
- data/examples/basics/out.new +0 -856
- data/lib/bud/deploy/localdeploy.rb +0 -53
data/README
CHANGED
@@ -1,30 +1,47 @@
|
|
1
1
|
# Bud
|
2
2
|
|
3
|
-
This is Bud, a.k.a. "Bloom Under Development". It is an initial cut at a Bloom
|
3
|
+
This is Bud, a.k.a. "Bloom Under Development". It is an initial cut at a Bloom
|
4
|
+
DSL, using Ruby as a setting.
|
4
5
|
|
5
|
-
|
6
|
+
See LICENSE for licensing information.
|
6
7
|
|
7
|
-
Language cheatsheet in
|
8
|
+
Language cheatsheet in docs/cheat.md ; see the docs/ directory for other
|
9
|
+
documentation.
|
8
10
|
|
9
11
|
Main deficiencies at this point are:
|
10
|
-
- Inefficient evaluation: Programs are run using semi-naive evaluation strategies, but no further
|
11
|
-
query optimization has been implemented, and little effort has been spent in
|
12
|
-
tuning.
|
13
12
|
|
14
|
-
-
|
15
|
-
|
13
|
+
- Inefficient evaluation: Programs are run using semi-naive evaluation
|
14
|
+
strategies, but no further query optimization has been implemented, and little
|
15
|
+
effort has been spent in tuning.
|
16
16
|
|
17
|
-
-
|
18
|
-
|
17
|
+
- No Ruby constraints: Within Bloom programs the full power of Ruby is also
|
18
|
+
available, including mutable state. This allows programmers to get outside
|
19
|
+
the Bloom framework and lose cleanliness.
|
19
20
|
|
20
|
-
|
21
|
+
- Compatibility: Bud only works with Ruby (MRI) 1.8. MRI 1.9, JRuby and other
|
22
|
+
Ruby implementations are currently not supported.
|
23
|
+
|
24
|
+
## Installation
|
25
|
+
|
26
|
+
To install the latest release:
|
21
27
|
% gem install bud
|
22
28
|
|
23
|
-
|
24
|
-
|
29
|
+
To build and install a new gem from the current development sources:
|
30
|
+
% gem build bud.gemspec ; gem install bud*.gem
|
31
|
+
|
32
|
+
Note that GraphViz must be installed.
|
33
|
+
|
34
|
+
Simple example programs can be found in examples. A much larger set of example
|
35
|
+
programs and libraries can be found in the bud-sandbox repository.
|
36
|
+
|
37
|
+
To run the unit tests:
|
38
|
+
% cd test; ruby ts_bud.rb
|
25
39
|
|
26
40
|
## Optional Dependencies
|
27
41
|
|
28
|
-
The bud gem has a handful of mandatory dependencies. It also has
|
29
|
-
|
30
|
-
"zktable"
|
42
|
+
The bud gem has a handful of mandatory dependencies. It also has two optional
|
43
|
+
dependencies: if you wish to use Bud collections backed by Zookeeper or Tokyo
|
44
|
+
Cabinet (the "zktable" and "tctable" collection types, respectively), the
|
45
|
+
"zookeeper" and/or "tokyocabinet" gems must be installed. Note that before
|
46
|
+
installing the "tokyocabinet" gem, the Tokyo Cabinet libraries should be
|
47
|
+
installed first.
|
data/bin/budplot
CHANGED
@@ -2,26 +2,30 @@
|
|
2
2
|
require 'rubygems'
|
3
3
|
require 'bud'
|
4
4
|
require 'bud/bud_meta'
|
5
|
-
require 'bud/graphs'
|
6
5
|
require 'bud/depanalysis'
|
6
|
+
require 'bud/graphs'
|
7
|
+
require 'bud/viz_util'
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
def process(mods)
|
11
|
-
classdef = "class FooBar\ninclude Bud\n" + mods.map{|m| "include #{m}"}.join("\n") + "\nend\n FooBar.new"
|
12
|
-
puts "classdef #{classdef}"
|
13
|
-
d = eval(classdef)
|
14
|
-
|
15
|
-
d.t_rules.each {|s| puts "RULE: #{s.inspect}" }
|
16
|
-
#d.t_depends.each {|s| puts "DEP: #{s.inspect}" }
|
9
|
+
include VizUtil
|
17
10
|
|
18
|
-
|
11
|
+
def is_module?(m)
|
12
|
+
begin
|
13
|
+
return (eval("defined?(#{m})") == "constant")
|
14
|
+
rescue SyntaxError
|
15
|
+
return false
|
16
|
+
end
|
17
|
+
end
|
19
18
|
|
20
|
-
|
19
|
+
def process(mods)
|
20
|
+
mods.each do |m|
|
21
|
+
unless is_module? m
|
22
|
+
puts "Error: unable to find definition for module \"#{m}\""
|
23
|
+
exit
|
24
|
+
end
|
25
|
+
end
|
21
26
|
|
22
|
-
#
|
23
|
-
|
24
|
-
#end
|
27
|
+
classdef = "class FooBar\ninclude Bud\n" + mods.map{|m| "include #{m}"}.join("\n") + "\nend\n FooBar.new"
|
28
|
+
d = eval(classdef)
|
25
29
|
|
26
30
|
interfaces = {}
|
27
31
|
d.t_provides.each do |name, is_input|
|
@@ -48,87 +52,60 @@ def process(mods)
|
|
48
52
|
end
|
49
53
|
end
|
50
54
|
|
51
|
-
|
52
|
-
write_index(inp, outp, priv,
|
53
|
-
|
54
|
-
|
55
|
-
gv.dump(d.t_rules)
|
56
|
-
gv.finish
|
57
|
-
|
58
|
-
gv2 = GraphGen.new(d.t_stratum, tabinf, d.t_cycle, svg, -1, 1, ".", false, d.meta_parser.depanalysis)
|
59
|
-
gv2.process(d.t_depends)
|
60
|
-
gv2.dump(d.t_rules)
|
61
|
-
gv2.finish
|
55
|
+
viz_name = "bud_doc/" + mods.join("_") + "_viz"
|
56
|
+
write_index(inp, outp, priv, viz_name)
|
57
|
+
graph_from_instance(d, "#{viz_name}_collapsed", "bud_doc", true)
|
58
|
+
graph_from_instance(d, "#{viz_name}_expanded", "bud_doc", false)
|
62
59
|
end
|
63
60
|
|
64
|
-
def write_index(inp, outp, priv,
|
61
|
+
def write_index(inp, outp, priv, viz_name)
|
65
62
|
f = File.open("bud_doc/index.html", "w")
|
66
63
|
f.puts "<html>"
|
67
|
-
f.puts "<embed src=\"#{ENV['PWD']}/#{
|
64
|
+
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/\" />"
|
68
65
|
|
69
66
|
f.puts "<table border='1' valign='top' width = '100%'><tr valign='top'>"
|
70
67
|
f.puts "<td valign='top'>"
|
71
|
-
f.puts "<h2>
|
68
|
+
f.puts "<h2>Input Interfaces</h2>"
|
72
69
|
do_table(f, inp)
|
73
70
|
f.puts "</td><td>"
|
74
|
-
f.puts "<h2>
|
71
|
+
f.puts "<h2>Output Interfaces</h2>"
|
75
72
|
do_table(f, outp)
|
76
73
|
f.puts "</td><td>"
|
77
|
-
f.puts "<h2>
|
78
|
-
do_table(f, priv
|
74
|
+
f.puts "<h2>Private State</h2>"
|
75
|
+
do_table(f, priv)
|
79
76
|
f.puts "</td>"
|
80
77
|
f.puts "</tr></table>"
|
81
78
|
f.puts "</html>"
|
82
79
|
f.close
|
83
80
|
end
|
84
81
|
|
85
|
-
def do_table(f, info
|
86
|
-
next if info.nil?
|
82
|
+
def do_table(f, info)
|
87
83
|
f.puts "<table border='1'>"
|
88
|
-
info.sort{|a, b| a[0].to_s <=> b[0].to_s}.each do |
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
84
|
+
info.sort{|a, b| a[0].to_s <=> b[0].to_s}.each do |tbl_name, tbl_impl|
|
85
|
+
next if tbl_impl.schema.nil?
|
86
|
+
key_s = tbl_impl.key_cols.join(", ")
|
87
|
+
key_s = "[]" if key_s == ""
|
88
|
+
val_s = tbl_impl.val_cols.join(", ")
|
89
|
+
f.puts "<tr><td><b>#{tbl_name}</b></td>"
|
90
|
+
f.puts "<td>#{key_s}</td><td>#{val_s}</td></tr>"
|
94
91
|
end
|
95
92
|
f.puts "</table>"
|
96
93
|
end
|
97
94
|
|
98
|
-
@shreddies = []
|
99
|
-
@provides = []
|
100
|
-
@demands = []
|
101
|
-
@tabinf = {}
|
102
|
-
@port = 12345
|
103
|
-
files = []
|
104
|
-
classes = []
|
105
|
-
|
106
95
|
if ARGV.length < 2
|
107
|
-
puts "
|
96
|
+
puts "Usage: budplot LIST_OF_FILES LIST_OF_MODULES"
|
108
97
|
exit
|
109
98
|
end
|
110
99
|
|
111
100
|
`mkdir bud_doc`
|
112
101
|
|
113
102
|
modules = []
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
mods = false
|
118
|
-
rescue
|
119
|
-
mods = true
|
120
|
-
end
|
121
|
-
|
122
|
-
unless mods
|
123
|
-
puts "DO #{ARGV[i]}"
|
124
|
-
eval ( "require \"#{ARGV[i]}\"")
|
103
|
+
ARGV.each do |arg|
|
104
|
+
if File.exists? arg
|
105
|
+
eval "require '#{arg}'"
|
125
106
|
else
|
126
|
-
|
127
|
-
#instant(ARGV[i])
|
128
|
-
modules << ARGV[i]
|
129
|
-
puts "OK"
|
107
|
+
modules << arg
|
130
108
|
end
|
131
109
|
end
|
132
110
|
|
133
111
|
process(modules)
|
134
|
-
|
data/bin/budtimelines
ADDED
@@ -0,0 +1,235 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'rubygems'
|
3
|
+
require 'dbm'
|
4
|
+
require 'bud'
|
5
|
+
require 'bud/graphs'
|
6
|
+
require 'bud/viz_util'
|
7
|
+
require 'getopt/std'
|
8
|
+
|
9
|
+
include VizUtil
|
10
|
+
|
11
|
+
module Depends
|
12
|
+
state do
|
13
|
+
table :depends, [:rid, :lhs, :op, :rhs, :nm]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class GlobalDepAnalyzer
|
18
|
+
include Bud
|
19
|
+
include Depends
|
20
|
+
# this module's purpose and mechanism are very similar
|
21
|
+
# to those of basic stratification. here, we are interested
|
22
|
+
# in NM paths that DO cross temporal edges.
|
23
|
+
|
24
|
+
state do
|
25
|
+
table :depends_tc, [:lhs, :rhs, :via, :nm]
|
26
|
+
end
|
27
|
+
|
28
|
+
bloom do
|
29
|
+
depends_tc <= depends{|d| [d.lhs, d.rhs, d.rhs, d.nm]}
|
30
|
+
depends_tc <= (depends * depends_tc).pairs(:rhs => :lhs) do |d, tc|
|
31
|
+
[d.lhs, tc.rhs, d.rhs, (d.nm or tc.nm)]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
module TPSchema
|
37
|
+
state do
|
38
|
+
table :deltas, [:bud_time, :tab, :nm]
|
39
|
+
table :zerod_cards, [:bud_time, :table, :cnt]
|
40
|
+
table :nm_tab, [:table]
|
41
|
+
table :collapsible_base, [:start, :fin]
|
42
|
+
table :collapsible, [:start, :fin]
|
43
|
+
scratch :collapsible_tmp, [:start, :fin]
|
44
|
+
scratch :lcl_best_interval, [:start, :fin]
|
45
|
+
table :best_interval, [:start, :fin]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
module DeltaLogic
|
50
|
+
include TPSchema
|
51
|
+
bloom do
|
52
|
+
zerod_cards <= cardinalities
|
53
|
+
zerod_cards <= (times * depends).pairs do |t, d|
|
54
|
+
unless cardinalities{|c| c[1] if c[0] == t.bud_time}.include? d[1]
|
55
|
+
[t.bud_time, d[1], 0]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
nm_tab <= depends do |d|
|
61
|
+
[d[1]] if d[4]
|
62
|
+
end
|
63
|
+
|
64
|
+
deltas <= (zerod_cards * zerod_cards).pairs(:table => :table) do |c1, c2|
|
65
|
+
if c1.bud_time == c2.bud_time - 1 and c1.table == c2.table and c1.cnt != c2.cnt
|
66
|
+
if nm_tab.include? [c1.table]
|
67
|
+
[c2.bud_time, c1.table, true]
|
68
|
+
else
|
69
|
+
[c2.bud_time, c1.table, false]
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
module VanillaTraceProcessing
|
77
|
+
include TPSchema
|
78
|
+
include DeltaLogic
|
79
|
+
|
80
|
+
bloom do
|
81
|
+
collapsible_base <= times do |t|
|
82
|
+
unless deltas{|d| d.bud_time if d.nm}.include? t.bud_time
|
83
|
+
[t.bud_time-1, t.bud_time]
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
collapsible <= collapsible_base
|
88
|
+
|
89
|
+
collapsible <= (collapsible_base * collapsible).pairs(:fin => :start) do |b, c|
|
90
|
+
puts "another collapsible row; now #{b.inspect} - #{c.inspect}"
|
91
|
+
[b.start, c.fin]
|
92
|
+
end
|
93
|
+
|
94
|
+
best_interval <= collapsible do |c|
|
95
|
+
unless collapsible{|c1| c1.start == c.start and c1.fin > c.fin}.any? \
|
96
|
+
or collapsible{|c2| c2.fin == c.fin and c2.start < c.start}.any?
|
97
|
+
c
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
class SimpleTraceProcessor
|
104
|
+
include Bud
|
105
|
+
include TraceCardinality
|
106
|
+
include Depends
|
107
|
+
include VanillaTraceProcessing
|
108
|
+
|
109
|
+
end
|
110
|
+
|
111
|
+
def collapse(intervals, host, time)
|
112
|
+
return time unless @opts["C"]
|
113
|
+
# worth rethinking when the # of intervals/instance gets high
|
114
|
+
intervals[host].each do |i|
|
115
|
+
if time > i[0] and time < i[1]
|
116
|
+
return i[1]
|
117
|
+
end
|
118
|
+
end
|
119
|
+
return time
|
120
|
+
end
|
121
|
+
|
122
|
+
def usage
|
123
|
+
puts "USAGE:"
|
124
|
+
exit
|
125
|
+
end
|
126
|
+
|
127
|
+
usage unless ARGV[0]
|
128
|
+
usage if ARGV[0] == '--help'
|
129
|
+
|
130
|
+
@opts = Getopt::Std.getopts("CLo:")
|
131
|
+
|
132
|
+
snd_info = {}
|
133
|
+
rcv_info = {}
|
134
|
+
clean_arg = []
|
135
|
+
intervals = {}
|
136
|
+
|
137
|
+
|
138
|
+
da = GlobalDepAnalyzer.new
|
139
|
+
|
140
|
+
ARGV.each do |arg_raw|
|
141
|
+
elems = arg_raw.split("_")
|
142
|
+
arg = elems[1..3].join("_")
|
143
|
+
clean_arg << arg
|
144
|
+
snd_info[arg] = []
|
145
|
+
rcv_info[arg] = []
|
146
|
+
|
147
|
+
meta, data = get_meta2("#{arg_raw}/bud_")
|
148
|
+
tp = SimpleTraceProcessor.new
|
149
|
+
|
150
|
+
meta[:depends].each do |m|
|
151
|
+
tp.depends << m
|
152
|
+
da.depends << m
|
153
|
+
end
|
154
|
+
|
155
|
+
data.each do |d|
|
156
|
+
tp.full_info << d
|
157
|
+
if meta[:tabinf].map{|m| m[0] if m[1] == "Bud::BudChannel"}.include? d[1]
|
158
|
+
if d[1] =~ /_snd\z/
|
159
|
+
snd_info[arg] << d
|
160
|
+
else
|
161
|
+
rcv_info[arg] << d
|
162
|
+
end
|
163
|
+
elsif meta[:tabinf].map{|m| m[0] if m[1] == "Bud::BudPeriodic"}.include? d[1]
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
tp.tick
|
168
|
+
|
169
|
+
|
170
|
+
puts "entries in collapsible: #{tp.collapsible.length}"
|
171
|
+
puts "entries in base: #{tp.collapsible_base.length}"
|
172
|
+
puts "entries in deltas: #{tp.deltas.length}"
|
173
|
+
|
174
|
+
intervals[arg] = []
|
175
|
+
tp.best_interval.each do |n|
|
176
|
+
puts "BEST INTERVAL[#{arg}]: #{n.inspect}"
|
177
|
+
intervals[arg] << n
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
da.tick
|
182
|
+
nmreach = {}
|
183
|
+
da.depends_tc.each do |d|
|
184
|
+
nmreach[d[0]] = {} unless nmreach[d[0]]
|
185
|
+
nmreach[d[0]][d[1]] = d[3]
|
186
|
+
end
|
187
|
+
|
188
|
+
# our local intervals relations are too optimistic. to say that intervals[foo] = [2, 5]
|
189
|
+
# is merely to say that nothing NM happened locally btw 2 and 5. it is only safe to collapse
|
190
|
+
# 2 and 5 if during this interval, we could not have BOTH caused and perceived the results of
|
191
|
+
# a NM deduction. we can (again, conservatively) ensure that this is not the case by showing
|
192
|
+
# that from 2-5, there exist no messages A and B s.t. we sent A and received B in the interval 2..5
|
193
|
+
# and B <n A (where <n means is globally NM-derivable from).
|
194
|
+
|
195
|
+
# we can of course do better than this even with the data we have, but it is complicated and we'll
|
196
|
+
# get to it later.
|
197
|
+
|
198
|
+
plot_data = []
|
199
|
+
snd_info.each_pair do |k1, v1|
|
200
|
+
rcv_info.each_pair do |k2, v2|
|
201
|
+
v1.each do |lval|
|
202
|
+
v2.each do |rval|
|
203
|
+
unless k1 == k2
|
204
|
+
# erm, tuple equivalence?
|
205
|
+
l = lval[2].clone
|
206
|
+
r = rval[2].clone
|
207
|
+
l.shift
|
208
|
+
r.shift
|
209
|
+
if l.inspect == r.inspect
|
210
|
+
plot_data << [l.inspect, k1, k2, lval[0], rval[0], rval[1]]
|
211
|
+
end
|
212
|
+
else
|
213
|
+
if collapse(intervals, k1, lval[0]) == collapse(intervals, k2, rval[0]) and lval[0] < rval[0]
|
214
|
+
unless nmreach[rval[1]].nil?
|
215
|
+
if nmreach[rval[1]][lval[1].gsub(/_snd\z/, "")]
|
216
|
+
match = intervals[k1].find_all{|i| i[1] == collapse(intervals, k1, lval[0])}.first
|
217
|
+
intervals[k1].delete(match)
|
218
|
+
intervals[k1] << [match[0], lval[0]]
|
219
|
+
intervals[k1] << [lval[0]+1, match[1]]
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
rpd = plot_data.map do |p|
|
230
|
+
[p[0], p[1], p[2], collapse(intervals, p[1], p[3]), collapse(intervals, p[2], p[4]), p[5]]
|
231
|
+
end
|
232
|
+
|
233
|
+
st = SpaceTime.new(rpd, @opts["L"])
|
234
|
+
st.process
|
235
|
+
st.finish("spacetime_trace_#{clean_arg.join('-')}", @opts["o"])
|
data/bin/budvis
CHANGED
@@ -1,49 +1,33 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
require 'rubygems'
|
3
|
-
require '
|
3
|
+
require 'dbm'
|
4
4
|
require 'bud'
|
5
5
|
require 'bud/graphs'
|
6
|
-
|
6
|
+
require 'bud/viz_util'
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
BUD_TC_DIR = "#{ARGV[0]}/bud_"
|
8
|
+
include VizUtil
|
11
9
|
|
10
|
+
BUD_DBM_DIR = "#{ARGV[0]}/bud_"
|
12
11
|
|
13
12
|
class VizHelper
|
14
13
|
include Bud
|
14
|
+
include TraceCardinality
|
15
15
|
|
16
|
-
|
17
|
-
table :full_info, [:bud_time, :table, :row]
|
18
|
-
scratch :cardinalities, [:bud_time, :table] => [:cnt]
|
19
|
-
scratch :times, [:bud_time]
|
20
|
-
end
|
21
|
-
|
22
|
-
def initialize(strata, tabinf, cycle, depends, rules, dir)
|
23
|
-
@t_strata = strata
|
16
|
+
def initialize(tabinf, cycle, depends, rules, dir)
|
24
17
|
@t_tabinf = tabinf
|
25
18
|
@t_cycle = cycle
|
26
19
|
@t_depends = depends
|
27
|
-
@dir = dir
|
28
20
|
@t_rules = rules
|
21
|
+
@dir = dir
|
29
22
|
super()
|
30
23
|
end
|
31
24
|
|
32
|
-
bloom :counting do
|
33
|
-
cardinalities <= full_info.group([full_info.bud_time, full_info.table], count)
|
34
|
-
times <= full_info.map{|f| [f.bud_time]}
|
35
|
-
end
|
36
|
-
|
37
25
|
def summarize(dir, schema)
|
38
26
|
table_io = {}
|
39
|
-
timeseries = {}
|
40
27
|
cardinalities.sort{|a, b| a[0] <=> b[0]}.each do |card|
|
41
28
|
table_io["#{card.table}_#{card.bud_time}"] = start_table(dir, card.table, card.bud_time, schema[card.table])
|
42
|
-
unless timeseries[card.table]
|
43
|
-
timeseries[card.table] = []
|
44
|
-
end
|
45
|
-
timeseries[card.table] << card.cnt
|
46
29
|
end
|
30
|
+
|
47
31
|
full_info.each do |info|
|
48
32
|
write_table_content(table_io["#{info.table}_#{info.bud_time}"], info.row)
|
49
33
|
end
|
@@ -52,19 +36,6 @@ class VizHelper
|
|
52
36
|
end_table(tab)
|
53
37
|
end
|
54
38
|
|
55
|
-
ts2 = {}
|
56
|
-
timeseries.each_pair do |k, v|
|
57
|
-
fn = v
|
58
|
-
puts "GOT #{fn}"
|
59
|
-
#ts2[k] = "#{ENV['PWD']}/#{fn}"
|
60
|
-
ts2[k] = v
|
61
|
-
end
|
62
|
-
|
63
|
-
sum = GraphGen.new(@t_strata, @t_tabinf, @t_cycle, "#{@dir}/summary", -1, 3, @dir, false, nil, ts2)
|
64
|
-
sum.process(@t_depends)
|
65
|
-
sum.dump(@t_rules)
|
66
|
-
sum.finish
|
67
|
-
|
68
39
|
# fix: nested loops
|
69
40
|
times.sort.each do |time|
|
70
41
|
card_info = {}
|
@@ -74,24 +45,18 @@ class VizHelper
|
|
74
45
|
end
|
75
46
|
end
|
76
47
|
|
77
|
-
|
78
|
-
|
79
|
-
gv.dump(@t_rules)
|
80
|
-
gv.finish
|
81
|
-
|
48
|
+
d = "#{@dir}/tm_#{time.bud_time}"
|
49
|
+
write_graphs(@t_tabinf, @t_cycle, @t_depends, @t_rules, d, @dir, nil, false, nil, time.bud_time, card_info)
|
82
50
|
end
|
83
|
-
|
84
51
|
end
|
85
52
|
|
86
53
|
def start_table(dir, tab, time, schema)
|
87
54
|
str = "#{dir}/#{tab}_#{time}.html"
|
88
|
-
#fout = File.new("#{dir}/#{tab}_#{time}.html", "w")
|
89
55
|
fout = File.new(str, "w")
|
90
56
|
|
91
|
-
#fout.puts "<h1>#{tab} #{time_node_header()}</h1>"
|
92
57
|
fout.puts "<html><title>#{tab} @ #{time}</title>"
|
93
58
|
fout.puts "<table border=1>"
|
94
|
-
fout.puts "<tr>" + schema.map{|s| "<th> #{s} </th>"}.join(" ") + "<tr>"
|
59
|
+
fout.puts "<tr>" + schema.map{|s| "<th> #{s} </th>"}.join(" ") + "<tr>" unless schema.nil?
|
95
60
|
fout.close
|
96
61
|
return str
|
97
62
|
end
|
@@ -111,91 +76,28 @@ class VizHelper
|
|
111
76
|
end
|
112
77
|
end
|
113
78
|
|
114
|
-
def deserialize_table(tab, strict)
|
115
|
-
# oy. meta only
|
116
|
-
ret = []
|
117
|
-
tab.each_pair do |k, v|
|
118
|
-
#key = Marshal.load(k)
|
119
|
-
key = MessagePack.unpack(k)
|
120
|
-
time = key.shift
|
121
|
-
raise "non-zero budtime. sure this is metadata?" if time != 0 and strict
|
122
|
-
tup = key
|
123
|
-
#Marshal.load(v).each{|v| tup << v }
|
124
|
-
MessagePack.unpack(v).each{|val| tup << val }
|
125
|
-
ret << tup
|
126
|
-
end
|
127
|
-
tab.close
|
128
|
-
return ret
|
129
|
-
end
|
130
|
-
|
131
79
|
def usage
|
132
80
|
puts "Usage:"
|
133
|
-
puts "Running a Bud program with option :
|
134
|
-
puts ">
|
135
|
-
puts "This will create a series of svg files in
|
81
|
+
puts "Running a Bud program with option :trace => true will cause a DBM directory DBM_dir to be created (Class_ObjectId_Port)"
|
82
|
+
puts "> budvis DBM_dir"
|
83
|
+
puts "This will create a series of svg files in DBM_dir, the root of which will be named tm_0.svg. Open in a browser.\n"
|
136
84
|
puts "e.g."
|
137
85
|
puts "> ruby test/tc_carts.rb"
|
138
|
-
puts ">
|
139
|
-
puts "> open
|
86
|
+
puts "> budvis DBM_BCS_2159661360_"
|
87
|
+
puts "> open DBM_BCS_2159661360_/tm_0.svg"
|
88
|
+
puts "\nWith the SVG file open in a browser, you may navigate forward and backward in time"
|
89
|
+
puts "by clicking the T and S nodes, respectively."
|
140
90
|
exit
|
141
91
|
end
|
142
92
|
|
143
|
-
# begin "main"
|
144
|
-
|
145
93
|
usage unless ARGV[0]
|
94
|
+
usage if ARGV[0] == '--help'
|
146
95
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
puts "FILE is #{file}"
|
152
|
-
hdb = TokyoCabinet::HDB.new
|
153
|
-
ret = hdb.open("#{BUD_TC_DIR}/#{file}", HDB::OREADER)
|
154
|
-
raise "db not found" unless ret
|
155
|
-
@tables[file] = hdb
|
156
|
-
end
|
157
|
-
|
158
|
-
|
159
|
-
# let's try to do a visualization
|
160
|
-
strata = deserialize_table(@tables['t_stratum_vizlog.tch'], true)
|
161
|
-
tabinf = deserialize_table(@tables['t_table_info_vizlog.tch'], true)
|
162
|
-
tabscm = deserialize_table(@tables['t_table_schema_vizlog.tch'], true)
|
163
|
-
cycle = deserialize_table(@tables['t_cycle_vizlog.tch'], true)
|
164
|
-
depends = deserialize_table(@tables['t_depends_vizlog.tch'], true)
|
165
|
-
rules = deserialize_table(@tables['t_rules_vizlog.tch'], true)
|
166
|
-
|
167
|
-
|
168
|
-
schminf = {}
|
169
|
-
tabscm.each do |ts|
|
170
|
-
puts "TABSCM: #{ts.inspect}"
|
171
|
-
tab = ts[0].to_s
|
172
|
-
unless schminf[tab]
|
173
|
-
schminf[tab] = []
|
174
|
-
end
|
175
|
-
schminf[tab][ts[2]] = ts[1]
|
176
|
-
end
|
177
|
-
|
178
|
-
gv = GraphGen.new(strata, tabinf, cycle, "OUTPUT", -1, 1, "plotter_out")
|
179
|
-
gv.process(depends)
|
180
|
-
gv.finish
|
181
|
-
|
182
|
-
|
183
|
-
vh = VizHelper.new(strata, tabinf, cycle, depends, rules, ARGV[0])
|
184
|
-
|
185
|
-
@tables.each_pair do |name, contents|
|
186
|
-
name = name.gsub("_vizlog.tch", "")
|
187
|
-
contents.each_pair do |k, v|
|
188
|
-
key = MessagePack.unpack(k)
|
189
|
-
time = key[0]
|
190
|
-
row = key
|
191
|
-
MessagePack.unpack(v).each{ |val| row << val }
|
192
|
-
if name == "t_table_info.tch" or name == "t_table_schema.tch"
|
193
|
-
#vh.full_info << [0, name, row]
|
194
|
-
else
|
195
|
-
vh.full_info << [time, name, row]
|
196
|
-
end
|
197
|
-
end
|
96
|
+
meta, data = get_meta2(BUD_DBM_DIR)
|
97
|
+
vh = VizHelper.new(meta[:tabinf], meta[:cycle], meta[:depends], meta[:rules], ARGV[0])
|
98
|
+
data.each do |d|
|
99
|
+
vh.full_info << d
|
198
100
|
end
|
199
101
|
|
200
102
|
vh.tick
|
201
|
-
vh.summarize(ARGV[0], schminf)
|
103
|
+
vh.summarize(ARGV[0], meta[:schminf])
|