bud 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data/README +33 -16
  2. data/bin/budplot +42 -65
  3. data/bin/budtimelines +235 -0
  4. data/bin/budvis +24 -122
  5. data/bin/rebl +1 -0
  6. data/docs/README.md +21 -10
  7. data/docs/bfs.md +4 -6
  8. data/docs/c.html +251 -0
  9. data/docs/cheat.md +45 -30
  10. data/docs/deploy.md +26 -26
  11. data/docs/getstarted.md +6 -4
  12. data/docs/visualizations.md +43 -31
  13. data/examples/chat/chat.rb +4 -9
  14. data/examples/chat/chat_server.rb +1 -8
  15. data/examples/deploy/deploy_ip_port +1 -0
  16. data/examples/deploy/keys.rb +5 -0
  17. data/examples/deploy/tokenring-ec2.rb +9 -9
  18. data/examples/deploy/{tokenring-local.rb → tokenring-fork.rb} +3 -5
  19. data/examples/deploy/tokenring-thread.rb +15 -0
  20. data/examples/deploy/tokenring.rb +25 -17
  21. data/lib/bud/aggs.rb +87 -25
  22. data/lib/bud/bud_meta.rb +48 -31
  23. data/lib/bud/bust/bust.rb +16 -15
  24. data/lib/bud/collections.rb +207 -232
  25. data/lib/bud/depanalysis.rb +1 -0
  26. data/lib/bud/deploy/countatomicdelivery.rb +8 -20
  27. data/lib/bud/deploy/deployer.rb +16 -16
  28. data/lib/bud/deploy/ec2deploy.rb +34 -35
  29. data/lib/bud/deploy/forkdeploy.rb +90 -0
  30. data/lib/bud/deploy/threaddeploy.rb +38 -0
  31. data/lib/bud/graphs.rb +103 -199
  32. data/lib/bud/joins.rb +190 -41
  33. data/lib/bud/monkeypatch.rb +84 -0
  34. data/lib/bud/rebl.rb +8 -1
  35. data/lib/bud/rewrite.rb +152 -49
  36. data/lib/bud/server.rb +1 -0
  37. data/lib/bud/state.rb +24 -10
  38. data/lib/bud/storage/dbm.rb +170 -0
  39. data/lib/bud/storage/tokyocabinet.rb +5 -1
  40. data/lib/bud/stratify.rb +6 -7
  41. data/lib/bud/viz.rb +31 -17
  42. data/lib/bud/viz_util.rb +204 -0
  43. data/lib/bud.rb +271 -244
  44. data/lib/bud.rb.orig +806 -0
  45. metadata +43 -22
  46. data/docs/bfs.raw +0 -251
  47. data/docs/diffs +0 -181
  48. data/examples/basics/out +0 -1103
  49. data/examples/basics/out.new +0 -856
  50. 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(mapping, tableinfo, cycle, name, budtime, vizlevel, pics_dir, collapse=false, depanalysis=nil, cardinalities={})
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
- @vizlevel = vizlevel
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
- puts "CYCLE: #{c.inspect}"
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)}_expanded.svg"
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 @depanalysis.nil?
235
- @depanalysis.source.each {|s| addedge("S", s.pred, false, false, false) }
236
- @depanalysis.sink.each {|s| addedge(s.pred, "T", false, false, false) }
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 @depanalysis.underspecified.empty?
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
- @depanalysis.underspecified.each do |u|
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
- suffix = @collapse ? "collapsed" : "expanded"
255
- fn = "#{@name}_#{suffix}.svg"
256
- puts "fn is #{fn}"
257
- staging = "#{fn}_staging"
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
- def output_base
272
- if @vizlevel >= 3
273
- @pics_dir
274
- else
275
- "bud_doc"
276
- end
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 dump(shredded_rules)
280
- return if shredded_rules.nil?
281
-
282
- fout = File.new("#{output_base}/style.css", "w")
283
- fout.puts css
284
- fout.close
285
-
286
- code = {}
287
- rules = {}
288
- convertor = Syntax::Convertors::HTML.for_syntax "ruby"
289
- shredded_rules.each do |s|
290
- #fout = File.new("#{output_base}/#{s[0]}.html", "w+")
291
- fout = File.new("#{output_base}/#{s[0]}.html", "w+")
292
- fout.puts header
293
- fout.puts "<h1>Rule #{s[0]}</h1><br>"
294
-
295
- c = convertor.convert(s[3])
296
- c.sub!(/^<pre>/, "<pre class=\"code\" style='font-size:20px'>\n")
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
- rules.each_pair do |k, v|
303
- if !code[v[0]]
304
- code[v[0]] = ""
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
- @nodes.each_pair do |k, v|
310
- fout = File.new("#{output_base}/#{k}.html", "w+")
311
- fout.puts header
312
- k.split(", ").each do |i|
313
- unless code[i].nil?
314
- c = convertor.convert(code[i])
315
- c.sub!(/^<pre>/, "<pre class=\"code\">\n")
316
- fout.puts c
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
- def header
326
- return "<html><meta content='text/html; charset=UTF-8' http-equiv='Content-Type'/>\n<head><link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\" /></head><body>"
327
- end
328
-
329
- def css
330
- return "pre.code {
331
- padding: 1ex 1ex 1ex 1ex;
332
- border: 4px groove #CC0000;
333
- overflow-x: auto;
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
- end
358
-
359
- def svg_javascript
360
- return "
361
- <script type='text/javascript'>
362
- <![CDATA[
363
-
364
- var windows = new Array()
365
- var info = new Array()
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