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/lib/bud/graphs.rb
CHANGED
@@ -1,32 +1,21 @@
|
|
1
|
-
# -*- coding: utf-8 -*-
|
2
1
|
require 'rubygems'
|
2
|
+
require 'digest/md5'
|
3
3
|
require 'graphviz'
|
4
4
|
|
5
5
|
class GraphGen #:nodoc: all
|
6
|
+
attr_reader :nodes
|
6
7
|
|
7
|
-
def initialize(
|
8
|
-
#@graph = GraphViz.new(:G, :type => :digraph, :label => "", :ratio => 0.85 )
|
8
|
+
def initialize(tableinfo, cycle, name, budtime, collapse=false, cardinalities={})
|
9
9
|
@graph = GraphViz.new(:G, :type => :digraph, :label => "")
|
10
10
|
@graph.node[:fontname] = "Times-Roman"
|
11
11
|
@graph.node[:fontsize] = 18
|
12
12
|
@graph.edge[:fontname] = "Times-Roman"
|
13
13
|
@graph.edge[:fontsize] = 18
|
14
|
-
@tiers = []
|
15
14
|
@cards = cardinalities
|
16
15
|
@name = name
|
17
16
|
@collapse = collapse
|
18
|
-
@depanalysis = depanalysis
|
19
17
|
@budtime = budtime
|
20
|
-
@
|
21
|
-
@pics_dir = pics_dir
|
22
|
-
#@internals = {'count' => 1, 'localtick' => 1, 'stdio' => 1, 't_rules' => 1, 't_depends' => 1, 't_depends_tc' => 1, 't_provides' => 1, 't_cycle' => 1}
|
23
|
-
@internals = {'count' => 1, 'localtick' => 1, 'stdio' => 1} #, 't_rules' => 1, 't_depends' => 1, 't_depends_tc' => 1, 't_provides' => 1, 't_cycle' => 1}
|
24
|
-
|
25
|
-
# map: table -> stratum
|
26
|
-
@t2s = {}
|
27
|
-
mapping.each do |m|
|
28
|
-
@t2s[m[0]] = m[1].to_i
|
29
|
-
end
|
18
|
+
@internals = {'localtick' => 1, 'stdio' => 1}
|
30
19
|
|
31
20
|
# map: table -> type
|
32
21
|
@tabinf = {}
|
@@ -36,7 +25,7 @@ class GraphGen #:nodoc: all
|
|
36
25
|
|
37
26
|
@redcycle = {}
|
38
27
|
cycle.each do |c|
|
39
|
-
|
28
|
+
# assumption: !(c[2] and !c[3]), or stratification would have bombed out
|
40
29
|
if c[2] and c[3]
|
41
30
|
if !@redcycle[c[0]]
|
42
31
|
@redcycle[c[0]] = []
|
@@ -50,21 +39,6 @@ class GraphGen #:nodoc: all
|
|
50
39
|
@labels = {}
|
51
40
|
end
|
52
41
|
|
53
|
-
def safe_t2s(tab)
|
54
|
-
if @t2s[tab]
|
55
|
-
@t2s[tab]
|
56
|
-
else
|
57
|
-
words = tab.split(",")
|
58
|
-
maxs = 0
|
59
|
-
words.each do |w|
|
60
|
-
if @t2s[w] and @t2s[w] > maxs
|
61
|
-
maxs = @t2s[w]
|
62
|
-
end
|
63
|
-
end
|
64
|
-
return maxs
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
42
|
def name_bag(predicate, bag)
|
69
43
|
if bag[predicate]
|
70
44
|
return bag
|
@@ -84,12 +58,9 @@ class GraphGen #:nodoc: all
|
|
84
58
|
|
85
59
|
def name_of(predicate)
|
86
60
|
# consider doing this in bud
|
87
|
-
# PAA
|
88
61
|
if @redcycle[predicate] and @collapse
|
89
|
-
puts "collapse #{predicate}, redcycle #{@redcycle[predicate].inspect}"
|
90
62
|
via = @redcycle[predicate]
|
91
63
|
bag = name_bag(predicate, {})
|
92
|
-
#str = bag.key_cols.sort.join(", ")
|
93
64
|
str = bag.keys.sort.join(", ")
|
94
65
|
return str
|
95
66
|
else
|
@@ -98,14 +69,11 @@ class GraphGen #:nodoc: all
|
|
98
69
|
end
|
99
70
|
|
100
71
|
def process(depends)
|
101
|
-
|
102
72
|
# collapsing NEG/+ cycles.
|
103
73
|
# we want to create a function from any predicate to (cycle_name or bottom)
|
104
74
|
# bottom if the predicate is not in a NEG/+ cycle. otherwise,
|
105
75
|
# its name is "CYC" + concat(sort(predicate names))
|
106
|
-
|
107
76
|
depends.each do |d|
|
108
|
-
#puts "DEP: #{d.inspect}"
|
109
77
|
head = d[1]
|
110
78
|
body = d[3]
|
111
79
|
|
@@ -116,32 +84,30 @@ class GraphGen #:nodoc: all
|
|
116
84
|
|
117
85
|
head = name_of(head)
|
118
86
|
body = name_of(body)
|
119
|
-
addonce(head, (head != d[1]))
|
87
|
+
addonce(head, (head != d[1]), true)
|
120
88
|
addonce(body, (body != d[3]))
|
121
89
|
addedge(body, head, d[2], d[4], (head != d[1]), d[0])
|
122
90
|
end
|
123
91
|
end
|
124
92
|
|
125
|
-
def addonce(node, negcluster)
|
126
|
-
#puts "ADD NODE #{node}"
|
93
|
+
def addonce(node, negcluster, inhead=false)
|
127
94
|
if !@nodes[node]
|
128
95
|
@nodes[node] = @graph.add_node(node)
|
129
96
|
if @cards and @cards[node]
|
130
97
|
@nodes[node].label = node +"\n (#{@cards[node].to_s})"
|
131
|
-
puts "IMAGE IS #{@cards[node]}"
|
132
|
-
#@nodes[node].image = @cards[node]
|
133
|
-
end
|
134
|
-
|
135
|
-
if @vizlevel >= 3
|
136
|
-
@nodes[node].URL = "javascript:openWin(\"#{node}\", #{@budtime})"
|
137
|
-
else
|
138
|
-
@nodes[node].URL = "#{node}.html"
|
139
98
|
end
|
99
|
+
end
|
100
|
+
|
101
|
+
if @budtime == -1
|
102
|
+
@nodes[node].URL = "#{node}.html" if inhead
|
103
|
+
else
|
104
|
+
@nodes[node].URL = "javascript:openWin(\"#{node}\", #{@budtime})"
|
140
105
|
end
|
141
106
|
|
142
107
|
if negcluster
|
143
108
|
# cleaning
|
144
109
|
res = node
|
110
|
+
# pretty-printing issues
|
145
111
|
node.split(", ").each_with_index do |p, i|
|
146
112
|
if i == 0
|
147
113
|
res = p
|
@@ -151,12 +117,11 @@ class GraphGen #:nodoc: all
|
|
151
117
|
res = res + ", " + p
|
152
118
|
end
|
153
119
|
end
|
154
|
-
#@nodes[node].label = "<b>" + res + "</b>"
|
155
120
|
@nodes[node].label = res
|
156
121
|
@nodes[node].color = "red"
|
157
122
|
@nodes[node].shape = "octagon"
|
158
123
|
@nodes[node].penwidth = 3
|
159
|
-
@nodes[node].URL = "#{File.basename(@name)}
|
124
|
+
@nodes[node].URL = "#{File.basename(@name).gsub(".staging", "").gsub("collapsed", "expanded")}.svg"
|
160
125
|
elsif @tabinf[node] and (@tabinf[node] == "Bud::BudTable")
|
161
126
|
@nodes[node].shape = "rect"
|
162
127
|
end
|
@@ -180,11 +145,8 @@ class GraphGen #:nodoc: all
|
|
180
145
|
@edges[ekey].minlen = 1.5
|
181
146
|
end
|
182
147
|
@labels[ekey] = {}
|
183
|
-
|
184
148
|
end
|
185
149
|
|
186
|
-
#@edges[ekey].minlen = 5 if negcluster and body == head
|
187
|
-
|
188
150
|
if op == '<+'
|
189
151
|
@labels[ekey][' +/-'] = true
|
190
152
|
elsif op == "<~"
|
@@ -200,9 +162,8 @@ class GraphGen #:nodoc: all
|
|
200
162
|
end
|
201
163
|
end
|
202
164
|
|
203
|
-
def finish
|
165
|
+
def finish(depanalysis=nil, output=nil)
|
204
166
|
@labels.each_key do |k|
|
205
|
-
#@edges[k].label = @labels[k].key_cols.join(" ")
|
206
167
|
@edges[k].label = @labels[k].keys.join(" ")
|
207
168
|
end
|
208
169
|
|
@@ -221,28 +182,26 @@ class GraphGen #:nodoc: all
|
|
221
182
|
@nodes["T"].penwidth = 3
|
222
183
|
|
223
184
|
@tabinf.each_pair do |k, v|
|
224
|
-
|
225
185
|
unless @nodes[name_of(k.to_s)] or k.to_s =~ /_tbl/ or @internals[k.to_s] or (k.to_s =~ /^t_/ and @budtime != 0)
|
226
186
|
addonce(k.to_s, false)
|
227
187
|
end
|
228
188
|
if v == "Bud::BudPeriodic"
|
229
|
-
puts "adding edge S -> #{@nodes[k.to_s]}"
|
230
189
|
addedge("S", k.to_s, false, false, false)
|
231
190
|
end
|
232
191
|
end
|
233
192
|
|
234
|
-
unless
|
235
|
-
|
236
|
-
|
193
|
+
unless depanalysis.nil?
|
194
|
+
depanalysis.source.each {|s| addedge("S", s.pred, false, false, false)}
|
195
|
+
depanalysis.sink.each {|s| addedge(s.pred, "T", false, false, false)}
|
237
196
|
|
238
|
-
unless
|
197
|
+
unless depanalysis.underspecified.empty?
|
239
198
|
addonce("??", false)
|
240
199
|
@nodes["??"].color = "red"
|
241
200
|
@nodes["??"].shape = "diamond"
|
242
201
|
@nodes["??"].penwidth = 2
|
243
202
|
end
|
244
203
|
|
245
|
-
|
204
|
+
depanalysis.underspecified.each do |u|
|
246
205
|
if u.input
|
247
206
|
addedge(u.pred, "??", false, false, false)
|
248
207
|
else
|
@@ -251,155 +210,100 @@ class GraphGen #:nodoc: all
|
|
251
210
|
end
|
252
211
|
end
|
253
212
|
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
@graph.output(:svg => staging)
|
259
|
-
@graph.output(:dot => "#{fn}.dot")
|
260
|
-
@graph.output(:png => "#{fn}.png")
|
261
|
-
fin = File.open(staging, "r")
|
262
|
-
fout = File.open(fn, "w")
|
263
|
-
while line = fin.gets
|
264
|
-
fout.puts line.gsub("<title>G</title>", svg_javascript())
|
213
|
+
if output.nil?
|
214
|
+
@graph.output(:svg => @name)
|
215
|
+
else
|
216
|
+
@graph.output(output => @name)
|
265
217
|
end
|
266
|
-
fin.close
|
267
|
-
fout.close
|
268
|
-
File.delete(staging)
|
269
218
|
end
|
219
|
+
end
|
270
220
|
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
221
|
+
class SpaceTime
|
222
|
+
def initialize(input, links = false)
|
223
|
+
@input = input
|
224
|
+
@links = links
|
225
|
+
processes = input.map {|i| i[1]}
|
226
|
+
input.map{|i| processes << i[2]}
|
227
|
+
processes.uniq!
|
228
|
+
|
229
|
+
@queues = {}
|
230
|
+
|
231
|
+
@g = GraphViz.new(:G, :type => :digraph, :rankdir => "LR", :outputorder => "nodesfirst", :splines => "line")#, :clusterrank => "none")
|
232
|
+
@hdr = @g.subgraph("cluster_0")
|
233
|
+
|
234
|
+
@subs = {}
|
235
|
+
@head = {}
|
236
|
+
last = nil
|
237
|
+
processes.each_with_index do |p, i|
|
238
|
+
#@head[p] = @hdr.add_node("process #{p}(#{i})")#, :color => "white", :label => "")
|
239
|
+
@subs[p] = @g.subgraph("buster_#{i+1}")
|
240
|
+
@head[p] = @hdr.add_node("process #{p}(#{i})", :group => p)#, :color => "white", :label => "")
|
241
|
+
|
242
|
+
end
|
277
243
|
end
|
278
244
|
|
279
|
-
def
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
fout.puts c
|
298
|
-
rules[s[0]] = [s[1], s[3]]
|
299
|
-
fout.close
|
245
|
+
def msg_edge(f, t, l)
|
246
|
+
lbl = "#{f}#{t}#{l}"
|
247
|
+
if @edges[lbl]
|
248
|
+
prev = @edges[lbl]
|
249
|
+
@edges[lbl] = [prev[0], prev[1], prev[2], prev[3] + 1]
|
250
|
+
else
|
251
|
+
@edges[lbl] = [f, t, l, 1]
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
def process
|
256
|
+
@edges = {}
|
257
|
+
queues = {}
|
258
|
+
@input.each do |i|
|
259
|
+
queues[i[1]] = [] unless queues[i[1]]
|
260
|
+
queues[i[2]] = [] unless queues[i[2]]
|
261
|
+
queues[i[1]] << i[3]
|
262
|
+
queues[i[2]] << i[4]
|
300
263
|
end
|
301
264
|
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
end
|
306
|
-
#code[v[0]] = "<br># RULE #{k}<br> " + code[v[0]] + "<br>" + v[1]
|
307
|
-
code[v[0]] = "\n# RULE #{k}\n " + code[v[0]] + "\n" + v[1]
|
265
|
+
squeues = {}
|
266
|
+
queues.each_pair do |k, v|
|
267
|
+
squeues[k] = v.sort{|a, b| a <=> b}
|
308
268
|
end
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
269
|
+
|
270
|
+
# create the nodes and the timeline edges first.
|
271
|
+
squeues.each do |k, v|
|
272
|
+
v.each_with_index do |item, i|
|
273
|
+
label = "#{k}-#{item}"
|
274
|
+
if @links
|
275
|
+
url = "DBM_#{k}_/tm_#{item}.svg"
|
276
|
+
#puts "URL is #{url}"
|
277
|
+
end
|
278
|
+
snd = @subs[k].add_node(label, {:label => item.to_s, :width => 0.1, :height => 0.1, :fontsize => 6, :pos => [1, i], :group => k, :URL => url})
|
279
|
+
|
280
|
+
unless @head[k].id == snd.id
|
281
|
+
@subs[k].add_edge(@head[k], snd, :weight => 2)
|
282
|
+
@head[k] = snd
|
317
283
|
end
|
318
284
|
end
|
319
|
-
fout.puts("</body></html>")
|
320
|
-
fout.close
|
321
285
|
end
|
322
|
-
end
|
323
|
-
|
324
286
|
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
}
|
335
|
-
|
336
|
-
pre.code span.attribute { color: #009900; }
|
337
|
-
pre.code span.char { color: #F00; }
|
338
|
-
pre.code span.class { color: #A020F0; font-weight: bold; }
|
339
|
-
pre.code span.comment { color: #0000FF; }
|
340
|
-
pre.code span.constant { color: #008B8B; }
|
341
|
-
pre.code span.escape { color: #6A5ACD; }
|
342
|
-
pre.code span.expr { color: #2222CC; }
|
343
|
-
pre.code span.global { color: #11AA44; }
|
344
|
-
pre.code span.ident { color: #000000; }
|
345
|
-
pre.code span.keyword { color: #A52A2A; font-weight: bold; }
|
346
|
-
pre.code span.method { color: #008B8B; }
|
347
|
-
pre.code span.module { color: #A020F0; font-weight: bold; }
|
348
|
-
pre.code span.number { color: #DD00DD; }
|
349
|
-
pre.code span.punct { color: #6A5ACD; }
|
350
|
-
pre.code span.regex { color: #DD00DD; }
|
351
|
-
pre.code span.string { color: #DD00DD; }
|
352
|
-
pre.code span.symbol { color: #008B8B; }
|
353
|
-
"
|
287
|
+
#@input.sort{|a, b| a[3] <=> b[3]}.each do |i|
|
288
|
+
@input.each do |i|
|
289
|
+
snd_loc = i[1]
|
290
|
+
rcv_loc = i[2]
|
291
|
+
snd_label = "#{snd_loc}-#{i[3]}"
|
292
|
+
rcv_label = "#{rcv_loc}-#{i[4]}"
|
293
|
+
#@g.add_edge(snd_label, rcv_label, :color => "red", :weight => 1, :label => i[5])
|
294
|
+
msg_edge(snd_label, rcv_label, i[5])
|
295
|
+
end
|
354
296
|
end
|
355
|
-
|
356
297
|
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
function openWin(target, time) {
|
368
|
-
win = window.open(target + \"_\" + time + \".html\", target, \"location=no,width=400,height=180,left=0,status=no\");
|
369
|
-
// hm, an associative array, how strange.
|
370
|
-
info[target] = 1
|
371
|
-
}
|
372
|
-
|
373
|
-
function advanceTo(time) {
|
374
|
-
arr = gup(\"wins\").split(\",\");
|
375
|
-
for (i=0; i < arr.length; i++) {
|
376
|
-
if (arr[i] != \"\") {
|
377
|
-
openWin(arr[i], time);
|
378
|
-
}
|
379
|
-
}
|
380
|
-
str = '';
|
381
|
-
// getting 'key_cols'
|
382
|
-
for (var i in info) {
|
383
|
-
str = str + ',' + i;
|
384
|
-
}
|
385
|
-
self.window.location.href = 'tm_' + time + '_expanded.svg?wins=' + str;
|
386
|
-
}
|
387
|
-
|
388
|
-
// off the netz
|
389
|
-
function gup( name )
|
390
|
-
{
|
391
|
-
name = name.replace(/[\[]/,\"\\\[\").replace(/[\]]/,\"\\\]\");
|
392
|
-
var regexS = \"[\\?&]\"+name+\"=([^&#]*)\";
|
393
|
-
var regex = new RegExp( regexS );
|
394
|
-
var results = regex.exec( window.location.href );
|
395
|
-
if( results == null )
|
396
|
-
return \"\";
|
397
|
-
else
|
398
|
-
return results[1];
|
399
|
-
}
|
400
|
-
|
401
|
-
]]>
|
402
|
-
</script>
|
403
|
-
"
|
298
|
+
def finish(file, fmt=nil)
|
299
|
+
@edges.each_pair do |k, v|
|
300
|
+
lbl = v[3] > 1 ? "#{v[2]}(#{v[3]})" : v[2]
|
301
|
+
@g.add_edge(v[0], v[1], :label => lbl, :color => "red", :weight => 1)
|
302
|
+
end
|
303
|
+
if fmt.nil?
|
304
|
+
@g.output(:svg => "#{file}.svg")
|
305
|
+
else
|
306
|
+
eval("@g.output(:#{fmt} => \"\#{file}.#{fmt}\")")
|
307
|
+
end
|
404
308
|
end
|
405
|
-
|
309
|
+
end
|