bud 0.9.0 → 0.9.1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +10 -1
- data/docs/cheat.md +3 -3
- data/examples/{README → README.md} +0 -0
- data/lib/bud/bud_meta.rb +21 -13
- data/lib/bud/collections.rb +123 -130
- data/lib/bud/executor/elements.rb +27 -52
- data/lib/bud/executor/group.rb +1 -1
- data/lib/bud/executor/join.rb +7 -12
- data/lib/bud/rewrite.rb +83 -53
- data/lib/bud/storage/dbm.rb +2 -2
- data/lib/bud/viz_util.rb +4 -2
- data/lib/bud.rb +21 -7
- metadata +27 -68
- data/docs/bust.md +0 -83
- data/examples/bust/README.md +0 -9
- data/examples/bust/bustclient-example.rb +0 -23
- data/examples/bust/bustinspector.html +0 -135
- data/examples/bust/bustserver-example.rb +0 -18
- data/lib/bud/bust/bust.rb +0 -137
- data/lib/bud/bust/client/idempotence.rb +0 -10
- data/lib/bud/bust/client/restclient.rb +0 -49
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bud
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -13,11 +13,11 @@ authors:
|
|
13
13
|
autorequire:
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
|
-
date: 2012-
|
16
|
+
date: 2012-04-10 00:00:00.000000000 Z
|
17
17
|
dependencies:
|
18
18
|
- !ruby/object:Gem::Dependency
|
19
19
|
name: eventmachine
|
20
|
-
requirement: &
|
20
|
+
requirement: &70136220748940 !ruby/object:Gem::Requirement
|
21
21
|
none: false
|
22
22
|
requirements:
|
23
23
|
- - ! '>='
|
@@ -25,10 +25,10 @@ dependencies:
|
|
25
25
|
version: '0'
|
26
26
|
type: :runtime
|
27
27
|
prerelease: false
|
28
|
-
version_requirements: *
|
28
|
+
version_requirements: *70136220748940
|
29
29
|
- !ruby/object:Gem::Dependency
|
30
30
|
name: fastercsv
|
31
|
-
requirement: &
|
31
|
+
requirement: &70136220747220 !ruby/object:Gem::Requirement
|
32
32
|
none: false
|
33
33
|
requirements:
|
34
34
|
- - ! '>='
|
@@ -36,10 +36,10 @@ dependencies:
|
|
36
36
|
version: '0'
|
37
37
|
type: :runtime
|
38
38
|
prerelease: false
|
39
|
-
version_requirements: *
|
39
|
+
version_requirements: *70136220747220
|
40
40
|
- !ruby/object:Gem::Dependency
|
41
41
|
name: gchart
|
42
|
-
requirement: &
|
42
|
+
requirement: &70136220763100 !ruby/object:Gem::Requirement
|
43
43
|
none: false
|
44
44
|
requirements:
|
45
45
|
- - ! '>='
|
@@ -47,10 +47,10 @@ dependencies:
|
|
47
47
|
version: '0'
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
|
-
version_requirements: *
|
50
|
+
version_requirements: *70136220763100
|
51
51
|
- !ruby/object:Gem::Dependency
|
52
52
|
name: getopt
|
53
|
-
requirement: &
|
53
|
+
requirement: &70136220762540 !ruby/object:Gem::Requirement
|
54
54
|
none: false
|
55
55
|
requirements:
|
56
56
|
- - ! '>='
|
@@ -58,43 +58,10 @@ dependencies:
|
|
58
58
|
version: '0'
|
59
59
|
type: :runtime
|
60
60
|
prerelease: false
|
61
|
-
version_requirements: *
|
62
|
-
- !ruby/object:Gem::Dependency
|
63
|
-
name: i18n
|
64
|
-
requirement: &70208102943580 !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
|
-
requirements:
|
67
|
-
- - ! '>='
|
68
|
-
- !ruby/object:Gem::Version
|
69
|
-
version: '0'
|
70
|
-
type: :runtime
|
71
|
-
prerelease: false
|
72
|
-
version_requirements: *70208102943580
|
73
|
-
- !ruby/object:Gem::Dependency
|
74
|
-
name: json
|
75
|
-
requirement: &70208102943100 !ruby/object:Gem::Requirement
|
76
|
-
none: false
|
77
|
-
requirements:
|
78
|
-
- - ! '>='
|
79
|
-
- !ruby/object:Gem::Version
|
80
|
-
version: '0'
|
81
|
-
type: :runtime
|
82
|
-
prerelease: false
|
83
|
-
version_requirements: *70208102943100
|
61
|
+
version_requirements: *70136220762540
|
84
62
|
- !ruby/object:Gem::Dependency
|
85
63
|
name: msgpack
|
86
|
-
requirement: &
|
87
|
-
none: false
|
88
|
-
requirements:
|
89
|
-
- - ! '>='
|
90
|
-
- !ruby/object:Gem::Version
|
91
|
-
version: '0'
|
92
|
-
type: :runtime
|
93
|
-
prerelease: false
|
94
|
-
version_requirements: *70208102942640
|
95
|
-
- !ruby/object:Gem::Dependency
|
96
|
-
name: nestful
|
97
|
-
requirement: &70208102942180 !ruby/object:Gem::Requirement
|
64
|
+
requirement: &70136220761500 !ruby/object:Gem::Requirement
|
98
65
|
none: false
|
99
66
|
requirements:
|
100
67
|
- - ! '>='
|
@@ -102,10 +69,10 @@ dependencies:
|
|
102
69
|
version: '0'
|
103
70
|
type: :runtime
|
104
71
|
prerelease: false
|
105
|
-
version_requirements: *
|
72
|
+
version_requirements: *70136220761500
|
106
73
|
- !ruby/object:Gem::Dependency
|
107
74
|
name: ruby-graphviz
|
108
|
-
requirement: &
|
75
|
+
requirement: &70136220760140 !ruby/object:Gem::Requirement
|
109
76
|
none: false
|
110
77
|
requirements:
|
111
78
|
- - ! '>='
|
@@ -113,10 +80,10 @@ dependencies:
|
|
113
80
|
version: '0'
|
114
81
|
type: :runtime
|
115
82
|
prerelease: false
|
116
|
-
version_requirements: *
|
83
|
+
version_requirements: *70136220760140
|
117
84
|
- !ruby/object:Gem::Dependency
|
118
85
|
name: ruby2ruby
|
119
|
-
requirement: &
|
86
|
+
requirement: &70136220759200 !ruby/object:Gem::Requirement
|
120
87
|
none: false
|
121
88
|
requirements:
|
122
89
|
- - <
|
@@ -124,10 +91,10 @@ dependencies:
|
|
124
91
|
version: 1.3.1
|
125
92
|
type: :runtime
|
126
93
|
prerelease: false
|
127
|
-
version_requirements: *
|
94
|
+
version_requirements: *70136220759200
|
128
95
|
- !ruby/object:Gem::Dependency
|
129
96
|
name: ruby_parser
|
130
|
-
requirement: &
|
97
|
+
requirement: &70136220758700 !ruby/object:Gem::Requirement
|
131
98
|
none: false
|
132
99
|
requirements:
|
133
100
|
- - ! '>='
|
@@ -135,10 +102,10 @@ dependencies:
|
|
135
102
|
version: '0'
|
136
103
|
type: :runtime
|
137
104
|
prerelease: false
|
138
|
-
version_requirements: *
|
105
|
+
version_requirements: *70136220758700
|
139
106
|
- !ruby/object:Gem::Dependency
|
140
107
|
name: superators19
|
141
|
-
requirement: &
|
108
|
+
requirement: &70136220758040 !ruby/object:Gem::Requirement
|
142
109
|
none: false
|
143
110
|
requirements:
|
144
111
|
- - ! '>='
|
@@ -146,10 +113,10 @@ dependencies:
|
|
146
113
|
version: '0'
|
147
114
|
type: :runtime
|
148
115
|
prerelease: false
|
149
|
-
version_requirements: *
|
116
|
+
version_requirements: *70136220758040
|
150
117
|
- !ruby/object:Gem::Dependency
|
151
118
|
name: syntax
|
152
|
-
requirement: &
|
119
|
+
requirement: &70136220757320 !ruby/object:Gem::Requirement
|
153
120
|
none: false
|
154
121
|
requirements:
|
155
122
|
- - ! '>='
|
@@ -157,10 +124,10 @@ dependencies:
|
|
157
124
|
version: '0'
|
158
125
|
type: :runtime
|
159
126
|
prerelease: false
|
160
|
-
version_requirements: *
|
127
|
+
version_requirements: *70136220757320
|
161
128
|
- !ruby/object:Gem::Dependency
|
162
129
|
name: uuid
|
163
|
-
requirement: &
|
130
|
+
requirement: &70136220756700 !ruby/object:Gem::Requirement
|
164
131
|
none: false
|
165
132
|
requirements:
|
166
133
|
- - ! '>='
|
@@ -168,10 +135,10 @@ dependencies:
|
|
168
135
|
version: '0'
|
169
136
|
type: :runtime
|
170
137
|
prerelease: false
|
171
|
-
version_requirements: *
|
138
|
+
version_requirements: *70136220756700
|
172
139
|
- !ruby/object:Gem::Dependency
|
173
140
|
name: minitest
|
174
|
-
requirement: &
|
141
|
+
requirement: &70136220756180 !ruby/object:Gem::Requirement
|
175
142
|
none: false
|
176
143
|
requirements:
|
177
144
|
- - ! '>='
|
@@ -179,7 +146,7 @@ dependencies:
|
|
179
146
|
version: '0'
|
180
147
|
type: :development
|
181
148
|
prerelease: false
|
182
|
-
version_requirements: *
|
149
|
+
version_requirements: *70136220756180
|
183
150
|
description: A prototype of the Bloom distributed programming language as a Ruby DSL.
|
184
151
|
email:
|
185
152
|
- bloomdevs@gmail.com
|
@@ -193,9 +160,6 @@ extra_rdoc_files: []
|
|
193
160
|
files:
|
194
161
|
- lib/bud/aggs.rb
|
195
162
|
- lib/bud/bud_meta.rb
|
196
|
-
- lib/bud/bust/bust.rb
|
197
|
-
- lib/bud/bust/client/idempotence.rb
|
198
|
-
- lib/bud/bust/client/restclient.rb
|
199
163
|
- lib/bud/collections.rb
|
200
164
|
- lib/bud/depanalysis.rb
|
201
165
|
- lib/bud/errors.rb
|
@@ -224,7 +188,6 @@ files:
|
|
224
188
|
- docs/bfs.md
|
225
189
|
- docs/bfs_arch.png
|
226
190
|
- docs/bloom-loop.png
|
227
|
-
- docs/bust.md
|
228
191
|
- docs/cheat.md
|
229
192
|
- docs/getstarted.md
|
230
193
|
- docs/intro.md
|
@@ -236,15 +199,11 @@ files:
|
|
236
199
|
- docs/visualizations.md
|
237
200
|
- examples/basics/hello.rb
|
238
201
|
- examples/basics/paths.rb
|
239
|
-
- examples/bust/bustclient-example.rb
|
240
|
-
- examples/bust/bustinspector.html
|
241
|
-
- examples/bust/bustserver-example.rb
|
242
|
-
- examples/bust/README.md
|
243
202
|
- examples/chat/chat.rb
|
244
203
|
- examples/chat/chat_protocol.rb
|
245
204
|
- examples/chat/chat_server.rb
|
246
205
|
- examples/chat/README.md
|
247
|
-
- examples/README
|
206
|
+
- examples/README.md
|
248
207
|
- README.md
|
249
208
|
- LICENSE
|
250
209
|
- History.txt
|
data/docs/bust.md
DELETED
@@ -1,83 +0,0 @@
|
|
1
|
-
BUST stands for BUd State Transfer and it is a REST interface to Bud. BUST consists of a Bud implementation of a client and server. The client implements bindings to a subset of the Ruby Nestful library, and the server is a lightweight HTTP server written in Ruby. Note that the BUST server currently sets the "Access-Control-Allow-Origin: *" HTTP header to override web browsers' same-origin policy.
|
2
|
-
|
3
|
-
Right now BUST supports "GET" and "POST" requests, and may support "DELETE" and "PUT" requests in the future.
|
4
|
-
|
5
|
-
# BUST Server
|
6
|
-
|
7
|
-
For the BUST server, a "GET" request corresponds to retrieving a subset of rows of a table, and a "POST" request corresponds to inserting a row into a table. For example, the following "GET" request (assuming BUST is running on port 8080):
|
8
|
-
|
9
|
-
GET localhost:8080/foo?bar=hello&baz=world
|
10
|
-
|
11
|
-
would retrieve all rows in table "foo" where named schema attribute "bar" is equal to the string "hello", and named schema attribute "baz" is equal to the string "world". Right now, one limitation of BUST is that only strings are supported.
|
12
|
-
|
13
|
-
To use BUST in your program, ensure you have the json gem installed. Add the "require" line for BUST:
|
14
|
-
|
15
|
-
require "bud/bust/bust"
|
16
|
-
|
17
|
-
In your class, make sure to:
|
18
|
-
|
19
|
-
include Bust
|
20
|
-
|
21
|
-
That's it! Now a BUST server will be started up when your class is instantiated. This server will listen on an open port; it will print out "Bust server listening on port xxxxx" to let you know which port it has selected. But you can select a specific port by passing a port via the "bust_port" option when you instantiate your class.
|
22
|
-
|
23
|
-
You can test out the BUST server using Ruby's "net/http" library if you want, and you can also check out "BUST Inspector", a sample AJAX application that allows you to view the state of a bud instance.
|
24
|
-
|
25
|
-
## net/http Example
|
26
|
-
|
27
|
-
Try running "bustserver-example.rb" in the "examples/bust" directory:
|
28
|
-
|
29
|
-
ruby bustserver-example.rb
|
30
|
-
|
31
|
-
Now, let's interact with our example using "net/http" from within IRB. Start up an IRB instance:
|
32
|
-
|
33
|
-
irb
|
34
|
-
irb(main):001:0> require 'net/http'
|
35
|
-
=> true
|
36
|
-
|
37
|
-
bustexample.rb defines a single relation called "foo":
|
38
|
-
|
39
|
-
table :foo, [:bar, :baz, :qux]
|
40
|
-
|
41
|
-
Let's fire off some requests. First, let's put a new foo fact in:
|
42
|
-
|
43
|
-
irb(main):002:0> res = Net::HTTP.post_form(URI.parse('http://localhost:8080/foo'), {:bar => "a", :baz => "b", :qux => "c"})
|
44
|
-
=> #<Net::HTTPOK 200 /OK readbody=true>
|
45
|
-
|
46
|
-
Now, let's retrieve all foo facts where the "qux" attribute is "c", and the "baz" attribute is "b":
|
47
|
-
|
48
|
-
irb(main):003:0> res = Net::HTTP.get(URI.parse('http://localhost:8080/foo?qux=c&baz=b'))
|
49
|
-
=> "[[\"a\",\"b\",\"c\"]]"
|
50
|
-
|
51
|
-
Note that the response is a JSON array.
|
52
|
-
|
53
|
-
|
54
|
-
## BUST Inspector
|
55
|
-
|
56
|
-
BUST Inspector -- an example app that uses XMLHttpRequests to inspect state in a Bud program using BUST is included -- (bust/bustinspector.html). Right now, it assumes that the Bud instance you're trying to inspect is listening on "localhost" at port "8080". BUST Inspector is tested to work in Firefox, and may or may not work in other browsers. BUST Inspector will query your Bud instance every second for metadata describing the tables and their schema. It will display a list of the tables in a pane on the left of the screen, with a checkbox next to each table. Selecting a checkbox renders the current table contents in the right pane (these are also updated every second while the box is checked).
|
57
|
-
|
58
|
-
|
59
|
-
# BUST Client
|
60
|
-
|
61
|
-
The BUST client (located in the "bust/client" folder) allows Bud applications to access REST services (including a Bud client hosting a BUST instance). The REST client is basically a wrapper for the Ruby nestful library. You'll need to ensure you have the "nestful" gem installed before you can use the REST client. To use it in your application, you need to put the require line:
|
62
|
-
|
63
|
-
require 'bud/bust/client/restclient'
|
64
|
-
|
65
|
-
and the include line:
|
66
|
-
|
67
|
-
include RestClient
|
68
|
-
|
69
|
-
To make requests, insert into the rest_req interface, whose definition is reproduced below:
|
70
|
-
|
71
|
-
interface input, :rest_req, [:rid, :verb, :form, :url, :params]
|
72
|
-
|
73
|
-
"rid" is a unique ID for the request, "verb" is one of ":get" or ":post", "form" is the format of the request, for example, you might use ":json", or if you're doing a form post, you'd use "form". If set to nil, "form" defaults to ":form" for ":post", and is omitted from a ":get". For ":get" requests, the "form" parameter seems to be appended onto the end of "url". For example, if you do a ":get" for "http://example.com/ex" with "form" set to ":json", the library sends an HTTP GET to "http://example.com/ex.json". "params" is a hash, which comprises the query string for a ":get", and the contents of the body in a ":post" with "form" set to ":form".
|
74
|
-
|
75
|
-
The output interface is:
|
76
|
-
|
77
|
-
interface output, :rest_response, [:rid, :resp, :exception]
|
78
|
-
|
79
|
-
"rid" is the unique ID supplied when the request was made, "resp" is the parsed response from the server. For example, if you do a ":json" ":get", then "resp" will contain whatever JSON object was returned converted into a Ruby object, e.g., array, hash, etc. If there is an exception, then "resp" will contain a string describing the exception, and "exception" will be set to true; otherwise, "exception" will be set to false.
|
80
|
-
|
81
|
-
A simple example is included (bustclient-example.rb) that does an HTTP GET on Twitter's public timeline, returning the most recent statuses, and prints them to stdout. The example is in "examples/bust/client".
|
82
|
-
|
83
|
-
The BUST client does not yet support OAuth. Also unsupported so far is HTTP DELETE and PUT.
|
data/examples/bust/README.md
DELETED
@@ -1,9 +0,0 @@
|
|
1
|
-
To run the bust twitter example client, do the following:
|
2
|
-
|
3
|
-
# ruby bustclient-example.rb
|
4
|
-
|
5
|
-
To test out bust inspector, do the following:
|
6
|
-
|
7
|
-
# ruby bustserver-example.rb
|
8
|
-
|
9
|
-
Then, launch bustinspector.html in a web browser (only Firefox 4 has been tested thus far) on either the computer where you launched bustserver-example.rb, or any computer that has TCP port 8080 forwarded to the computer where you launched bustserver-example.rb.
|
@@ -1,23 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'bud'
|
3
|
-
require 'bud/bust/client/restclient'
|
4
|
-
|
5
|
-
class TwitterExample # :nodoc: all
|
6
|
-
include Bud
|
7
|
-
include RestClient
|
8
|
-
|
9
|
-
bootstrap do
|
10
|
-
# get the 20 most recent tweets from twitter
|
11
|
-
rest_req <= [[1, :get, :json,
|
12
|
-
'http://api.twitter.com/1/statuses/public_timeline']]
|
13
|
-
end
|
14
|
-
|
15
|
-
bloom :print_recent_tweets do
|
16
|
-
# print the tweets with user screen names
|
17
|
-
stdio <~ rest_response do |r|
|
18
|
-
[r.resp.map {|s| s["user"]["screen_name"] + ": " + s["text"]}] if r.rid==1
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
TwitterExample.new.run_fg
|
@@ -1,135 +0,0 @@
|
|
1
|
-
<html>
|
2
|
-
<head>
|
3
|
-
<title>BUST Inspector</title>
|
4
|
-
|
5
|
-
<script type="text/javascript">
|
6
|
-
function pollState()
|
7
|
-
{
|
8
|
-
|
9
|
-
// 1. GET the list of tables
|
10
|
-
var xmlhttp = new XMLHttpRequest();
|
11
|
-
xmlhttp.open("GET","http://localhost:8080/t_table_info",false);
|
12
|
-
xmlhttp.send();
|
13
|
-
|
14
|
-
if (xmlhttp.readyState==4) {
|
15
|
-
if (xmlhttp.status == 404){
|
16
|
-
alert("error fetching 't_table_info'");
|
17
|
-
}
|
18
|
-
if (xmlhttp.status == 200){
|
19
|
-
tableArray = JSON.parse(xmlhttp.responseText);
|
20
|
-
|
21
|
-
var tablenames = document.getElementById("tablenames");
|
22
|
-
|
23
|
-
for (var i = 0; i < tableArray.length; i++) {
|
24
|
-
var tablename = tableArray[i][0]
|
25
|
-
// if the collection is new
|
26
|
-
if (!document.getElementById("coll_" + tablename)) {
|
27
|
-
var newspan = document.createElement("span");
|
28
|
-
newspan.innerHTML = '<input type="checkbox" id="coll_' + tablename + '"/>' + tablename + '(<small><b>' + tableArray[i][1] + '</b></small>) <br/>'
|
29
|
-
while (newspan.firstChild) {
|
30
|
-
tablenames.appendChild(newspan.firstChild);
|
31
|
-
}
|
32
|
-
}
|
33
|
-
}
|
34
|
-
|
35
|
-
}
|
36
|
-
}
|
37
|
-
|
38
|
-
|
39
|
-
// 2. GET the schema table
|
40
|
-
var schemareq = new XMLHttpRequest();
|
41
|
-
schemareq.open("GET","http://localhost:8080/t_table_schema",false);
|
42
|
-
schemareq.send();
|
43
|
-
|
44
|
-
if (schemareq.status == 404) {
|
45
|
-
alert("error fetching schema info");
|
46
|
-
}
|
47
|
-
if (schemareq.status == 200) {
|
48
|
-
schemaArray = JSON.parse(schemareq.responseText)
|
49
|
-
}
|
50
|
-
|
51
|
-
|
52
|
-
// 3. GET the list of checked tables
|
53
|
-
form_elts = document.forms[0].elements
|
54
|
-
for (var i = 0; i < form_elts.length; i++) {
|
55
|
-
var tablename = form_elts[i].id.substr(5);
|
56
|
-
|
57
|
-
//look it up in the schema
|
58
|
-
var schemaIdx;
|
59
|
-
var found = false;
|
60
|
-
for (schemaIdx = 0; schemaIdx < schemaArray.length; schemaIdx++) {
|
61
|
-
if (schemaArray[schemaIdx][0] == tablename) {
|
62
|
-
found = true;
|
63
|
-
break;
|
64
|
-
}
|
65
|
-
}
|
66
|
-
if (!found) {
|
67
|
-
alert ("no schema information for table " + tablename);
|
68
|
-
}
|
69
|
-
|
70
|
-
var ourSchema = schemaArray[schemaIdx][1];
|
71
|
-
|
72
|
-
if (form_elts[i].checked) {
|
73
|
-
var tablereq = new XMLHttpRequest();
|
74
|
-
tablereq.open("GET","http://localhost:8080/"+tablename,false);
|
75
|
-
tablereq.send();
|
76
|
-
|
77
|
-
if (tablereq.status == 404){
|
78
|
-
alert("error fetching table " + tablename);
|
79
|
-
}
|
80
|
-
if (tablereq.status == 200){
|
81
|
-
responseArray = JSON.parse(tablereq.responseText)
|
82
|
-
|
83
|
-
//schema
|
84
|
-
tableText = "<table style='border-width: 1px; border-spacing: 2px; border-style: outset; border-color: gray; border-collapse: separate;'><tr>";
|
85
|
-
for (var j = 0; j < ourSchema.length; j++) {
|
86
|
-
tableText += "<td style='border-width: 1px; padding: 1px; border-style: inset; border-color: gray;'><b>" + ourSchema[j] + "</b></td>";
|
87
|
-
}
|
88
|
-
tableText += "</tr>";
|
89
|
-
|
90
|
-
//data
|
91
|
-
for (var k = 0; k < responseArray.length; k++) {
|
92
|
-
tableText += "<tr>";
|
93
|
-
for (var l = 0; l < responseArray[k].length; l++) {
|
94
|
-
tableText += "<td style='border-width: 1px; padding: 1px; border-style: inset; border-color: gray;'>" + responseArray[k][l] + "</td>";
|
95
|
-
}
|
96
|
-
tableText += "</tr>";
|
97
|
-
}
|
98
|
-
tableText += "</table>";
|
99
|
-
|
100
|
-
if (!document.getElementById("disp_" + tablename)) {
|
101
|
-
document.getElementById("tabledisplay").innerHTML += '<div style="border: 1px solid black; float:left; padding: 0px; margin:5px;" id="disp_' + tablename + '"><h4 style="margin-top:0px;">' + tablename + '</h4>' + tableText + '</div>';
|
102
|
-
} else {
|
103
|
-
document.getElementById("disp_" + tablename).innerHTML = '<h4 style="margin-top:0px;">' + tablename + '</h4>' + tableText;
|
104
|
-
}
|
105
|
-
}
|
106
|
-
} else { //if not checked
|
107
|
-
if (document.getElementById("disp_" + tablename)) {
|
108
|
-
document.getElementById("tabledisplay").removeChild(document.getElementById("disp_" + tablename))
|
109
|
-
}
|
110
|
-
}
|
111
|
-
|
112
|
-
} //end for
|
113
|
-
|
114
|
-
|
115
|
-
setTimeout('pollState()', 1000);
|
116
|
-
}
|
117
|
-
|
118
|
-
</script>
|
119
|
-
|
120
|
-
</head>
|
121
|
-
|
122
|
-
<body onLoad="setTimeout('pollState()', 1000);">
|
123
|
-
|
124
|
-
<div style="width:100%;"><h3>BUST Inspector</h3></div>
|
125
|
-
<div style="height:100%; border: 1px solid black; float:left; padding:0px; margin:5px;">
|
126
|
-
<h4 style="margin-top:0px;">Collections</h4>
|
127
|
-
<form id="tableform">
|
128
|
-
<span id="tablenames">
|
129
|
-
</span>
|
130
|
-
</form>
|
131
|
-
</div>
|
132
|
-
<span id="tabledisplay">
|
133
|
-
</span>
|
134
|
-
</body>
|
135
|
-
</html>
|
@@ -1,18 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'bud'
|
3
|
-
require 'bud/bust/bust'
|
4
|
-
|
5
|
-
class BustExample # :nodoc: all
|
6
|
-
include Bud
|
7
|
-
include Bust
|
8
|
-
|
9
|
-
state do
|
10
|
-
table :foo, [:bar, :baz, :qux]
|
11
|
-
end
|
12
|
-
|
13
|
-
bloom do
|
14
|
-
stdio <~ foo {|t| [t.inspect]}
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
BustExample.new(:bust_port => 8080).run_fg
|
data/lib/bud/bust/bust.rb
DELETED
@@ -1,137 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'bud'
|
3
|
-
require 'json'
|
4
|
-
require 'socket'
|
5
|
-
require 'uri'
|
6
|
-
require 'cgi'
|
7
|
-
|
8
|
-
HTTP_VERBS = ["GET", "POST"] #, "DELETE"]
|
9
|
-
|
10
|
-
# a RESTful interface to Bloom code
|
11
|
-
module Bust
|
12
|
-
include Bud
|
13
|
-
attr_reader :bust_port
|
14
|
-
|
15
|
-
# used this for inspiration:
|
16
|
-
# http://blogs.msdn.com/b/abhinaba/archive/2005/10/14/474841.aspx
|
17
|
-
|
18
|
-
bootstrap do
|
19
|
-
# copied from peter's code; this should probably be in the Bud runtime or in
|
20
|
-
# some meta module
|
21
|
-
@tables.each do |t|
|
22
|
-
t_table_schema << [t[0], t[1].cols.clone]
|
23
|
-
t_table_info << [t[0], t[1].class.to_s]
|
24
|
-
end
|
25
|
-
|
26
|
-
q = Queue.new
|
27
|
-
Thread.start(self) do |bud|
|
28
|
-
BustClass.new(bud, q)
|
29
|
-
end
|
30
|
-
# Wait for socket to be ready before we return from bootstrap.
|
31
|
-
r = q.pop
|
32
|
-
if r.class <= Exception
|
33
|
-
raise r
|
34
|
-
else
|
35
|
-
@bust_port = r
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
class BustClass
|
40
|
-
class BustHandler
|
41
|
-
def initialize(session, request, body, bud)
|
42
|
-
@session = session
|
43
|
-
@request = request
|
44
|
-
@body = body
|
45
|
-
@bud = bud
|
46
|
-
end
|
47
|
-
|
48
|
-
def serve()
|
49
|
-
puts "Request: " + @request
|
50
|
-
puts "Body: " + @body.inspect if @body
|
51
|
-
|
52
|
-
for type in HTTP_VERBS
|
53
|
-
if @request =~ Regexp.new(type + " .* HTTP*")
|
54
|
-
break reqstr = @request.gsub(Regexp.new(type + " "), '').gsub(/ HTTP.*/, '')
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
uri = URI.parse(reqstr)
|
59
|
-
uri_params = {}
|
60
|
-
uri_params = CGI.parse(uri.query) if uri.query
|
61
|
-
table_name = uri.path[1..-1].split(".")[0] # hack; we always return JSON
|
62
|
-
# "Access-Control-Allow-Origin: *" disables same-origin policy to allow
|
63
|
-
# XMLHttpRequests from any origin
|
64
|
-
success = "HTTP/1.1 200 OK\r\nServer: Bud\r\nContent-type: application/json\r\nAccess-Control-Allow-Origin: *\r\n\r\n"
|
65
|
-
failure = "HTTP/1.1 404 Object Not Found\r\nServer: Bud\r\nAccess-Control-Allow-Origin: *\r\n\r\n"
|
66
|
-
|
67
|
-
begin
|
68
|
-
if @request =~ /GET .* HTTP*/
|
69
|
-
puts "GET shouldn't have body" if @body
|
70
|
-
# select the appropriate elements from the table
|
71
|
-
desired_elements = @bud.send(table_name.to_sym).find_all do |t|
|
72
|
-
uri_params.all? {|k, v|
|
73
|
-
(eval "t." + k.to_s) == v[0]
|
74
|
-
}
|
75
|
-
end
|
76
|
-
@session.print success
|
77
|
-
desired_elements = desired_elements .map{|elem|
|
78
|
-
elem.class <= Struct ? elem.to_a : elem
|
79
|
-
}
|
80
|
-
@session.print desired_elements.to_json
|
81
|
-
elsif @request =~ /POST .* HTTP*/
|
82
|
-
# instantiate a new tuple
|
83
|
-
tuple_to_insert = []
|
84
|
-
@body.each do |k, v|
|
85
|
-
index = @bud.send(table_name.to_sym).cols.find_index(k.to_sym)
|
86
|
-
for i in (tuple_to_insert.size..index)
|
87
|
-
tuple_to_insert << nil
|
88
|
-
end
|
89
|
-
tuple_to_insert[index] = v[0]
|
90
|
-
end
|
91
|
-
# actually insert the puppy
|
92
|
-
@bud.async_do {
|
93
|
-
@bud.send(table_name.to_sym) <+ [tuple_to_insert]
|
94
|
-
}
|
95
|
-
@session.print success
|
96
|
-
end
|
97
|
-
rescue Exception
|
98
|
-
puts "exception: #{$!}"
|
99
|
-
@session.print failure
|
100
|
-
ensure
|
101
|
-
@session.close
|
102
|
-
end
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
def initialize(bud, q)
|
107
|
-
# allow user-configurable port
|
108
|
-
begin
|
109
|
-
server = TCPServer.new(bud.ip, (bud.options[:bust_port] or 0))
|
110
|
-
port = server.addr[1]
|
111
|
-
puts "Bust server listening on #{bud.ip}:#{port}"
|
112
|
-
# We're now ready to accept connections
|
113
|
-
q << port
|
114
|
-
rescue Exception => e
|
115
|
-
# Avoid deadlock on queue, report exception to caller
|
116
|
-
q << e
|
117
|
-
end
|
118
|
-
|
119
|
-
loop do
|
120
|
-
session = server.accept
|
121
|
-
request = session.gets
|
122
|
-
length = nil
|
123
|
-
body = nil
|
124
|
-
while req = session.gets
|
125
|
-
length = Integer(req.split(" ")[1]) if req.match(/^Content-Length:/)
|
126
|
-
if req.match(/^\r\n$/)
|
127
|
-
body = CGI.parse(session.read(length)) if length
|
128
|
-
break
|
129
|
-
end
|
130
|
-
end
|
131
|
-
Thread.start(session, request, body, bud) do |session, request, body, bud|
|
132
|
-
BustHandler.new(session, request, body, bud).serve()
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|
136
|
-
end
|
137
|
-
end
|