zillabyte 0.0.6

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.
@@ -0,0 +1,369 @@
1
+ require "rubygems"
2
+ require "json"
3
+
4
+ module Zillabyte
5
+
6
+ module Storm
7
+
8
+ module Protocol
9
+
10
+ class << self
11
+ attr_accessor :mode, :pending_commands, :pipe_name, :pipe_to_java, :pipe_from_java
12
+ end
13
+
14
+ self.pending_commands = []
15
+
16
+ def setup_pipes
17
+ pipe_name = Storm::Protocol.pipe_name
18
+ if(pipe_name and File.exist?(pipe_name+".in"))
19
+ Storm::Protocol.pipe_to_java = File.open("#{pipe_name}.in","w+")
20
+ else
21
+ Storm::Protocol.pipe_to_java = $stdout
22
+ end
23
+
24
+ if(pipe_name and File.exist?(pipe_name+".out"))
25
+ Storm::Protocol.pipe_from_java = File.open("#{pipe_name}.out","r+")
26
+ else
27
+ Storm::Protocol.pipe_from_java = $stdin
28
+ end
29
+ end
30
+
31
+ def read_message
32
+ msg = ""
33
+ loop do
34
+ line = Storm::Protocol.pipe_from_java.readline.chomp#STDIN.readline.chomp
35
+ break if line == "end"
36
+ msg << line
37
+ msg << "\n"
38
+ end
39
+
40
+ encoding_options = {
41
+ :invalid => :replace, # Replace invalid byte sequences
42
+ :undef => :replace, # Replace anything not defined in ASCII
43
+ :replace => '' # Use a blank for those replacements
44
+ }
45
+ msg.encode! Encoding.find('ASCII'), encoding_options
46
+
47
+ JSON.parse msg.chomp
48
+ end
49
+
50
+ def read_command
51
+ Storm::Protocol.pending_commands.shift ||
52
+ begin
53
+ msg = read_message
54
+ while msg.is_a? Array
55
+ Storm::Protocol.pending_taskids.push(msg)
56
+ msg = read_message
57
+ end
58
+ msg
59
+ rescue JSON::ParserError => e
60
+ fail "error: #{e}"
61
+ {}
62
+ end
63
+ end
64
+
65
+ def send_msg_to_parent(msg)
66
+ # log msg
67
+ # log msg.to_json
68
+ Storm::Protocol.pipe_to_java.write(msg.to_json+"\n")
69
+ Storm::Protocol.pipe_to_java.write("end\n")
70
+ Storm::Protocol.pipe_to_java.flush
71
+ end
72
+
73
+ def send_pid(heartbeat_dir)
74
+ pid = Process.pid
75
+ send_msg_to_parent({'pid' => pid})
76
+ File.open("#{heartbeat_dir}/#{pid}", "w").close
77
+ end
78
+
79
+ def emit(*args)
80
+
81
+ stream = nil
82
+ tuple = nil
83
+ meta = {}
84
+
85
+ if (args.size == 1)
86
+ tuple = args[0]
87
+ elsif(args.size == 2)
88
+ stream = args[0]
89
+ tuple = args[1]
90
+ else
91
+ stream = args[0]
92
+ tuple = args[1]
93
+ meta = args[2]
94
+ end
95
+
96
+ m = {:command => :emit, :tuple => tuple, :stream => stream, :meta => meta}
97
+ send_msg_to_parent m
98
+ end
99
+
100
+ def ack(tup)
101
+ send_msg_to_parent :command => :ack, :id => tup.id
102
+ end
103
+
104
+ def done()
105
+ send_msg_to_parent :command => :done #, :id => tup.id
106
+ # read_task_ids
107
+ end
108
+
109
+ def fail(msg)
110
+ send_msg_to_parent :command => :fail, :msg => msg.to_s
111
+ end
112
+
113
+ def log(msg)
114
+ send_msg_to_parent :command => :log, :msg => msg.to_s
115
+ end
116
+
117
+ def handshake
118
+ setup_info = read_message
119
+ send_pid setup_info['pidDir']
120
+ [setup_info['conf'], setup_info['context']]
121
+ end
122
+ end
123
+
124
+
125
+ class Spout
126
+ include Storm::Protocol
127
+
128
+ def open(conf, context); end
129
+
130
+ def next_batch; end
131
+
132
+ def ack(id); end
133
+
134
+ def run(pipe_name)
135
+ Storm::Protocol.mode = 'spout'
136
+ Storm::Protocol.pipe_name = pipe_name
137
+ setup_pipes
138
+ open(*handshake)
139
+
140
+ begin
141
+ while true
142
+ msg = read_command
143
+ case msg['command']
144
+ when 'next'
145
+ next_batch
146
+ done
147
+ when 'ack'
148
+ ack(msg['id'])
149
+ when 'fail'
150
+ fail(msg['id'])
151
+ end
152
+ end
153
+ rescue Exception => e
154
+ fail 'Exception in spout: ' + e.message + ' - ' + e.backtrace.join('\n')
155
+ end
156
+ end
157
+ end
158
+
159
+ class Each
160
+ include Storm::Protocol
161
+
162
+ def prepare(conf, context); end
163
+
164
+ def execute(tuple); end
165
+
166
+ def run(pipe_name)
167
+ Storm::Protocol.mode = 'each'
168
+ Storm::Protocol.pipe_name = pipe_name
169
+ setup_pipes
170
+ prepare(*handshake)
171
+
172
+ begin
173
+ while true
174
+ t = nil
175
+ begin
176
+ t = Tuple.from_hash(read_command)
177
+ if(!t)
178
+ next
179
+ end
180
+ execute t
181
+ rescue Exception => e
182
+ fail 'Exception in bolt (A): ' + e.message + ' - ' + e.backtrace.join('\n')
183
+ ensure
184
+ done()
185
+ end
186
+ end
187
+ rescue Exception => e
188
+ fail 'Exception in bolt (B): ' + e.message + ' - ' + e.backtrace.join('\n')
189
+ end
190
+ end
191
+ end
192
+
193
+ class AggregateStart
194
+ include Storm::Protocol
195
+
196
+ def start(tuple); end
197
+
198
+ def run(pipe_name)
199
+ Storm::Protocol.mode = 'agg_start'
200
+ Storm::Protocol.pipe_name = pipe_name
201
+ setup_pipes
202
+ handshake
203
+
204
+ begin
205
+ while true
206
+ t = nil
207
+ begin
208
+ t = Tuple.from_hash(read_command)
209
+ if(!t)
210
+ next
211
+ end
212
+ start t
213
+ rescue Exception => e
214
+ fail 'Exception in bolt (A): ' + e.message + ' - ' + e.backtrace.join('\n')
215
+ ensure
216
+ done()
217
+ end
218
+ end
219
+ rescue Exception => e
220
+ fail 'Exception in bolt (B): ' + e.message + ' - ' + e.backtrace.join('\n')
221
+ end
222
+ end
223
+ end
224
+
225
+ class AggregateAggregate
226
+ include Storm::Protocol
227
+
228
+ def aggregate(tuple1, tuple2); end
229
+
230
+ def run(pipe_name)
231
+ Storm::Protocol.mode = 'agg_aggregate'
232
+ Storm::Protocol.pipe_name = pipe_name
233
+ setup_pipes
234
+ handshake
235
+
236
+ begin
237
+ while true
238
+ t = nil
239
+ begin
240
+ t1 = Tuple.from_hash(read_command)
241
+ if(!t1)
242
+ next
243
+ end
244
+ t2 = Tuple.from_hash(read_command)
245
+ if(!t2)
246
+ next
247
+ end
248
+ aggregate t1, t2
249
+ rescue Exception => e
250
+ fail 'Exception in bolt (A): ' + e.message + ' - ' + e.backtrace.join('\n')
251
+ ensure
252
+ done()
253
+ end
254
+ end
255
+ rescue Exception => e
256
+ fail 'Exception in bolt (B): ' + e.message + ' - ' + e.backtrace.join('\n')
257
+ end
258
+ end
259
+ end
260
+
261
+ class AggregateComplete
262
+ include Storm::Protocol
263
+
264
+ def complete(tuple); end
265
+
266
+ def run(pipe_name)
267
+ Storm::Protocol.mode = 'agg_complete'
268
+ Storm::Protocol.pipe_name = pipe_name
269
+ setup_pipes
270
+ handshake
271
+
272
+ begin
273
+ while true
274
+ t = nil
275
+ begin
276
+ t = Tuple.from_hash(read_command)
277
+ if(!t)
278
+ next
279
+ end
280
+ complete t
281
+ rescue Exception => e
282
+ fail 'Exception in bolt (A): ' + e.message + ' - ' + e.backtrace.join('\n')
283
+ ensure
284
+ done()
285
+ end
286
+ end
287
+ rescue Exception => e
288
+ fail 'Exception in bolt (B): ' + e.message + ' - ' + e.backtrace.join('\n')
289
+ end
290
+ end
291
+ end
292
+ end
293
+
294
+ module Harness
295
+
296
+ class SpoutController < Storm::Spout
297
+
298
+ def initialize(harness, progress)
299
+ @harness = harness
300
+ @progress = progress
301
+ end
302
+
303
+ def open(*args)
304
+ @harness._prepare.call(self, *args) if @harness._prepare
305
+ end
306
+
307
+ def next_batch
308
+ @harness._next_batch.call(self)
309
+ end
310
+
311
+ end
312
+
313
+ class EachController < Storm::Each
314
+
315
+ def initialize(harness, progress)
316
+ @harness = harness
317
+ @progress = progress
318
+ end
319
+
320
+ def execute(*args)
321
+ @harness._execute.call(self, *args)
322
+ end
323
+
324
+ def prepare(*args)
325
+ @harness._prepare.call(self, *args) if @harness._prepare
326
+ end
327
+
328
+ end
329
+
330
+ class AggregateStartController < Storm::AggregateStart
331
+
332
+ def initialize(harness, progress)
333
+ @harness = harness
334
+ @progress = progress
335
+ end
336
+
337
+ def start(*args)
338
+ @harness._start.call(self, *args)
339
+ end
340
+
341
+ end
342
+
343
+ class AggregateAggregateController < Storm::AggregateAggregate
344
+
345
+ def initialize(harness, progress)
346
+ @harness = harness
347
+ @progress = progress
348
+ end
349
+
350
+ def aggregate(*args)
351
+ @harness._aggregate.call(self, *args)
352
+ end
353
+
354
+ end
355
+
356
+ class AggregateCompleteController < Storm::AggregateComplete
357
+
358
+ def initialize(harness, progress)
359
+ @harness = harness
360
+ @progress = progress
361
+ end
362
+
363
+ def complete(*args)
364
+ @harness._complete.call(self, *args)
365
+ end
366
+
367
+ end
368
+ end
369
+ end
@@ -0,0 +1,131 @@
1
+ require 'optparse'
2
+
3
+ class Zillabyte::Harness::SimpleFunction
4
+ attr_accessor :_nodes, :_relation, :_matches, :_emits, :_prepare, :_execute, :_name, :_info_file, :_options
5
+
6
+ def self.build()
7
+ h = Zillabyte::Harness::SimpleFunction.new()
8
+ yield(h)
9
+ h._name = h._name || Dir.pwd.split("/")[-1]
10
+ Zillabyte::Harness::Helper.check_name("simple_function", h._name, {})
11
+ Zillabyte::Harness::Helper.check_emits("simple_function", h._emits, {})
12
+ generic_emits = h.get_generic_emits
13
+
14
+ h._nodes = []
15
+ h._options = Zillabyte::Harness::Helper.opt_parser()
16
+
17
+ if(h._options[:command] == :info)
18
+ h._info_file = File.open(h._options[:file],"w+")
19
+ hash = {"language" => "ruby", "name" => h._name}
20
+ Zillabyte::Harness::Helper.write_hash_to_file(hash, h._info_file)
21
+ end
22
+
23
+ h.build_spout()
24
+ fn = h.build_each(generic_emits)
25
+ h.build_sink()
26
+
27
+ if(h._options[:command] == :execute and h._options[:name] == h._name)
28
+ pipe_name = h._options[:pipe]
29
+ c = Zillabyte::Harness::EachController.new(fn, progress = Zillabyte::Common::Progress.new)
30
+ c.run(pipe_name)
31
+ end
32
+
33
+ h
34
+ end
35
+
36
+ def name(v)
37
+ @_name = v
38
+ end
39
+
40
+ def matches(v, options = {})
41
+ case v
42
+ when String
43
+ @_relation = { :query => v, :options => options.is_a?(Hash) ? options : {} }
44
+ when Array
45
+ @_matches = v
46
+ end
47
+ end
48
+
49
+ def emits(v)
50
+ @_emits = v
51
+ end
52
+
53
+ def prepare(&block)
54
+ @_prepare = block
55
+ end
56
+
57
+ def execute(&block)
58
+ @_execute = block
59
+ end
60
+
61
+ def get_generic_emits()
62
+ generic_emits = []
63
+ @_emits.each do |relation|
64
+ temit = []
65
+ relation[1].each do |column|
66
+ column.each do |col, type|
67
+ temit << col
68
+ end
69
+ end
70
+ generic_emits << [relation[0], temit]
71
+ end
72
+ generic_emits
73
+ end
74
+
75
+ def build_spout()
76
+ h = Zillabyte::Harness::Spout.new(false)
77
+ h._matches = @_matches if @_matches
78
+ h._relation = @_relation if @_relation
79
+ @_nodes << h
80
+ if(@_options[:command] == :info)
81
+ info_hash = {"name" => h._name, "type" => h._type}
82
+ if(h._relation)
83
+ info_hash["relation"] = h._relation
84
+ elsif(h._matches)
85
+ info_hash["matches"] = h._matches
86
+ end
87
+ Zillabyte::Harness::Helper.write_hash_to_file(info_hash, @_info_file)
88
+ end
89
+ end
90
+
91
+ def build_each(generic_emits)
92
+ h = Zillabyte::Harness::Each.new()
93
+ h._name = @_name
94
+ h._emits = generic_emits
95
+ h._prepare = @_prepare
96
+ h._execute = @_execute
97
+ @_nodes << h
98
+ if(@_options[:command] == :info)
99
+ info_hash = {"name" => h._name, "type" => h._type, "emits" => h._emits}
100
+ Zillabyte::Harness::Helper.write_hash_to_file(info_hash, @_info_file)
101
+ end
102
+ h
103
+ end
104
+
105
+ def build_sink()
106
+ # Construct the sink...
107
+ n_sinks = @_emits.length
108
+ @_emits.each do |emit|
109
+ h = Zillabyte::Harness::Sink.new()
110
+ h._name = emit[0]
111
+ columns = emit[1]
112
+ columns.each do |col|
113
+ col.each do |cname, ctype|
114
+ h.column(cname, ctype)
115
+ end
116
+ end
117
+ if(n_sinks > 1)
118
+ h._consumes = h._name
119
+ end
120
+ @_nodes << h
121
+ if(@_options[:command] == :info)
122
+ info_hash = {"name" => h._name, "type" => h._type, "columns" => h._columns}
123
+ if(h._consumes)
124
+ info_hash["consumes"] = h._consumes
125
+ end
126
+ Zillabyte::Harness::Helper.write_hash_to_file(info_hash, @_info_file)
127
+ end
128
+ end
129
+ end
130
+
131
+ end