cloudi 1.3.2
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.tar.gz.sig +1 -0
- data/README.markdown +7 -0
- data/lib/cloudi.rb +668 -0
- metadata +117 -0
- metadata.gz.sig +0 -0
data.tar.gz.sig
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1LȅsH����?/�"E1�3#������{v������]x=���[��|�N��[��YI�9c���s��`9)O�� kc���5p>����W*�g6����i��1C�1�90-�/����e�1�dk28�"b2�o"��&g9�:�u$�@$��I�U��exW4�����=�F���s��<�=f�=%�����>��Ct�'�@һ4}�:�V_��B�A���ll�B8��_��_��:��c�:�Q
|
data/README.markdown
ADDED
data/lib/cloudi.rb
ADDED
@@ -0,0 +1,668 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#-*-Mode:ruby;coding:utf-8;tab-width:4;c-basic-offset:4;indent-tabs-mode:()-*-
|
3
|
+
# ex: set ft=ruby fenc=utf-8 sts=4 ts=4 sw=4 et:
|
4
|
+
#
|
5
|
+
# BSD LICENSE
|
6
|
+
#
|
7
|
+
# Copyright (c) 2011-2014, Michael Truog <mjtruog at gmail dot com>
|
8
|
+
# All rights reserved.
|
9
|
+
#
|
10
|
+
# Redistribution and use in source and binary forms, with or without
|
11
|
+
# modification, are permitted provided that the following conditions are met:
|
12
|
+
#
|
13
|
+
# * Redistributions of source code must retain the above copyright
|
14
|
+
# notice, this list of conditions and the following disclaimer.
|
15
|
+
# * Redistributions in binary form must reproduce the above copyright
|
16
|
+
# notice, this list of conditions and the following disclaimer in
|
17
|
+
# the documentation and/or other materials provided with the
|
18
|
+
# distribution.
|
19
|
+
# * All advertising materials mentioning features or use of this
|
20
|
+
# software must display the following acknowledgment:
|
21
|
+
# This product includes software developed by Michael Truog
|
22
|
+
# * The name of the author may not be used to endorse or promote
|
23
|
+
# products derived from this software without specific prior
|
24
|
+
# written permission
|
25
|
+
#
|
26
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
27
|
+
# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
28
|
+
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
29
|
+
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
30
|
+
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
31
|
+
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
32
|
+
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
33
|
+
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
34
|
+
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
35
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
36
|
+
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
37
|
+
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
38
|
+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
39
|
+
# DAMAGE.
|
40
|
+
#
|
41
|
+
|
42
|
+
$:.unshift File.dirname(__FILE__)
|
43
|
+
|
44
|
+
$stdout.sync = true
|
45
|
+
$stderr.sync = true
|
46
|
+
|
47
|
+
require 'erlang'
|
48
|
+
|
49
|
+
module CloudI
|
50
|
+
class API
|
51
|
+
include Erlang
|
52
|
+
# unbuffered output is with $stderr.puts '...'
|
53
|
+
|
54
|
+
ASYNC = 1
|
55
|
+
SYNC = -1
|
56
|
+
|
57
|
+
def initialize(thread_index)
|
58
|
+
protocol = API.getenv('CLOUDI_API_INIT_PROTOCOL')
|
59
|
+
buffer_size_str = API.getenv('CLOUDI_API_INIT_BUFFER_SIZE')
|
60
|
+
if protocol == 'tcp'
|
61
|
+
@s = IO.for_fd(thread_index + 3, File::RDWR, autoclose: false)
|
62
|
+
@s.sync = true
|
63
|
+
@use_header = true
|
64
|
+
elsif protocol == 'udp'
|
65
|
+
@s = IO.for_fd(thread_index + 3, File::RDWR, autoclose: false)
|
66
|
+
@s.sync = true
|
67
|
+
@use_header = false
|
68
|
+
elsif protocol == 'local'
|
69
|
+
@s = IO.for_fd(thread_index + 3, File::RDWR, autoclose: false)
|
70
|
+
@s.sync = true
|
71
|
+
@use_header = true
|
72
|
+
else
|
73
|
+
raise InvalidInputException
|
74
|
+
end
|
75
|
+
@initialization_complete = false
|
76
|
+
@size = buffer_size_str.to_i
|
77
|
+
@callbacks = Hash.new
|
78
|
+
send(term_to_binary(:init))
|
79
|
+
poll_request(false)
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.thread_count
|
83
|
+
s = getenv('CLOUDI_API_INIT_THREAD_COUNT')
|
84
|
+
s.to_i
|
85
|
+
end
|
86
|
+
|
87
|
+
def subscribe(pattern, function)
|
88
|
+
key = @prefix + pattern
|
89
|
+
value = @callbacks.fetch(key, nil)
|
90
|
+
if value.nil?
|
91
|
+
@callbacks[key] = [function]
|
92
|
+
else
|
93
|
+
value.push(function)
|
94
|
+
end
|
95
|
+
send(term_to_binary([:subscribe, pattern]))
|
96
|
+
end
|
97
|
+
|
98
|
+
def unsubscribe(pattern)
|
99
|
+
key = @prefix + pattern
|
100
|
+
value = @callbacks.fetch(key, nil)
|
101
|
+
API.assert{value != nil}
|
102
|
+
value.shift
|
103
|
+
if value.empty?
|
104
|
+
@callbacks.delete(key)
|
105
|
+
end
|
106
|
+
send(term_to_binary([:unsubscribe, pattern]))
|
107
|
+
end
|
108
|
+
|
109
|
+
def send_async(name, request,
|
110
|
+
timeout=nil, request_info=nil, priority=nil)
|
111
|
+
if timeout.nil?
|
112
|
+
timeout = @timeoutAsync
|
113
|
+
end
|
114
|
+
if request_info.nil?
|
115
|
+
request_info = ''
|
116
|
+
end
|
117
|
+
if priority.nil?
|
118
|
+
priority = @priorityDefault
|
119
|
+
end
|
120
|
+
send(term_to_binary([:send_async, name,
|
121
|
+
OtpErlangBinary.new(request_info),
|
122
|
+
OtpErlangBinary.new(request),
|
123
|
+
timeout, priority]))
|
124
|
+
return poll_request(false)
|
125
|
+
end
|
126
|
+
|
127
|
+
def send_sync(name, request,
|
128
|
+
timeout=nil, request_info=nil, priority=nil)
|
129
|
+
if timeout.nil?
|
130
|
+
timeout = @timeoutSync
|
131
|
+
end
|
132
|
+
if request_info.nil?
|
133
|
+
request_info = ''
|
134
|
+
end
|
135
|
+
if priority.nil?
|
136
|
+
priority = @priorityDefault
|
137
|
+
end
|
138
|
+
send(term_to_binary([:send_sync, name,
|
139
|
+
OtpErlangBinary.new(request_info),
|
140
|
+
OtpErlangBinary.new(request),
|
141
|
+
timeout, priority]))
|
142
|
+
return poll_request(false)
|
143
|
+
end
|
144
|
+
|
145
|
+
def mcast_async(name, request,
|
146
|
+
timeout=nil, request_info=nil, priority=nil)
|
147
|
+
if timeout.nil?
|
148
|
+
timeout = @timeoutAsync
|
149
|
+
end
|
150
|
+
if request_info.nil?
|
151
|
+
request_info = ''
|
152
|
+
end
|
153
|
+
if priority.nil?
|
154
|
+
priority = @priorityDefault
|
155
|
+
end
|
156
|
+
send(term_to_binary([:mcast_async, name,
|
157
|
+
OtpErlangBinary.new(request_info),
|
158
|
+
OtpErlangBinary.new(request),
|
159
|
+
timeout, priority]))
|
160
|
+
return poll_request(false)
|
161
|
+
end
|
162
|
+
|
163
|
+
def forward_(command, name, request_info, request,
|
164
|
+
timeout, priority, trans_id, pid)
|
165
|
+
case command
|
166
|
+
when ASYNC
|
167
|
+
forward_async(name, request_info, request,
|
168
|
+
timeout, priority, trans_id, pid)
|
169
|
+
when SYNC
|
170
|
+
forward_sync(name, request_info, request,
|
171
|
+
timeout, priority, trans_id, pid)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def forward_async(name, request_info, request,
|
176
|
+
timeout, priority, trans_id, pid)
|
177
|
+
if @requestTimeoutAdjustment
|
178
|
+
if timeout == @request_timeout
|
179
|
+
elapsed = [0,
|
180
|
+
((Time.now - @request_timer) * 1000.0).floor].max
|
181
|
+
if elapsed > timeout
|
182
|
+
timeout = 0
|
183
|
+
else
|
184
|
+
timeout -= elapsed
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
send(term_to_binary([:forward_async, name,
|
189
|
+
OtpErlangBinary.new(request_info),
|
190
|
+
OtpErlangBinary.new(request),
|
191
|
+
timeout, priority,
|
192
|
+
OtpErlangBinary.new(trans_id), pid]))
|
193
|
+
raise ForwardAsyncException.new()
|
194
|
+
end
|
195
|
+
|
196
|
+
def forward_sync(name, request_info, request,
|
197
|
+
timeout, priority, trans_id, pid)
|
198
|
+
if @requestTimeoutAdjustment
|
199
|
+
if timeout == @request_timeout
|
200
|
+
elapsed = [0,
|
201
|
+
((Time.now - @request_timer) * 1000.0).floor].max
|
202
|
+
if elapsed > timeout
|
203
|
+
timeout = 0
|
204
|
+
else
|
205
|
+
timeout -= elapsed
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
send(term_to_binary([:forward_sync, name,
|
210
|
+
OtpErlangBinary.new(request_info),
|
211
|
+
OtpErlangBinary.new(request),
|
212
|
+
timeout, priority,
|
213
|
+
OtpErlangBinary.new(trans_id), pid]))
|
214
|
+
raise ForwardSyncException.new()
|
215
|
+
end
|
216
|
+
|
217
|
+
def return_(command, name, pattern, response_info, response,
|
218
|
+
timeout, trans_id, pid)
|
219
|
+
case command
|
220
|
+
when ASYNC
|
221
|
+
return_async(name, pattern, response_info, response,
|
222
|
+
timeout, trans_id, pid)
|
223
|
+
when SYNC
|
224
|
+
return_sync(name, pattern, response_info, response,
|
225
|
+
timeout, trans_id, pid)
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
def return_async(name, pattern, response_info, response,
|
230
|
+
timeout, trans_id, pid)
|
231
|
+
if @requestTimeoutAdjustment
|
232
|
+
if timeout == @request_timeout
|
233
|
+
elapsed = [0,
|
234
|
+
((Time.now - @request_timer) * 1000.0).floor].max
|
235
|
+
if elapsed > timeout
|
236
|
+
response_info = ''
|
237
|
+
response = ''
|
238
|
+
timeout = 0
|
239
|
+
else
|
240
|
+
timeout -= elapsed
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
244
|
+
send(term_to_binary([:return_async, name, pattern,
|
245
|
+
OtpErlangBinary.new(response_info),
|
246
|
+
OtpErlangBinary.new(response),
|
247
|
+
timeout,
|
248
|
+
OtpErlangBinary.new(trans_id), pid]))
|
249
|
+
raise ReturnAsyncException.new()
|
250
|
+
end
|
251
|
+
|
252
|
+
def return_sync(name, pattern, response_info, response,
|
253
|
+
timeout, trans_id, pid)
|
254
|
+
if @requestTimeoutAdjustment
|
255
|
+
if timeout == @request_timeout
|
256
|
+
elapsed = [0,
|
257
|
+
((Time.now - @request_timer) * 1000.0).floor].max
|
258
|
+
if elapsed > timeout
|
259
|
+
response_info = ''
|
260
|
+
response = ''
|
261
|
+
timeout = 0
|
262
|
+
else
|
263
|
+
timeout -= elapsed
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|
267
|
+
send(term_to_binary([:return_sync, name, pattern,
|
268
|
+
OtpErlangBinary.new(response_info),
|
269
|
+
OtpErlangBinary.new(response),
|
270
|
+
timeout,
|
271
|
+
OtpErlangBinary.new(trans_id), pid]))
|
272
|
+
raise ReturnSyncException.new()
|
273
|
+
end
|
274
|
+
|
275
|
+
def recv_async(timeout=nil, trans_id=nil, consume=true)
|
276
|
+
if timeout.nil?
|
277
|
+
timeout = @timeoutSync
|
278
|
+
end
|
279
|
+
if trans_id.nil?
|
280
|
+
trans_id = 0.chr * 16
|
281
|
+
end
|
282
|
+
send(term_to_binary([:recv_async, timeout,
|
283
|
+
OtpErlangBinary.new(trans_id), consume]))
|
284
|
+
return poll_request(false)
|
285
|
+
end
|
286
|
+
|
287
|
+
def process_index
|
288
|
+
return @processIndex
|
289
|
+
end
|
290
|
+
|
291
|
+
def process_count
|
292
|
+
return @processCount
|
293
|
+
end
|
294
|
+
|
295
|
+
def process_count_max
|
296
|
+
return @processCountMax
|
297
|
+
end
|
298
|
+
|
299
|
+
def process_count_min
|
300
|
+
return @processCountMin
|
301
|
+
end
|
302
|
+
|
303
|
+
def prefix
|
304
|
+
return @prefix
|
305
|
+
end
|
306
|
+
|
307
|
+
def timeout_async
|
308
|
+
return @timeoutAsync
|
309
|
+
end
|
310
|
+
|
311
|
+
def timeout_sync
|
312
|
+
return @timeoutSync
|
313
|
+
end
|
314
|
+
|
315
|
+
def callback(command, name, pattern, request_info, request,
|
316
|
+
timeout, priority, trans_id, pid)
|
317
|
+
request_time_start = nil
|
318
|
+
if @requestTimeoutAdjustment
|
319
|
+
@request_timer = Time.now
|
320
|
+
@request_timeout = timeout
|
321
|
+
end
|
322
|
+
function_queue = @callbacks.fetch(pattern, nil)
|
323
|
+
API.assert{function_queue != nil}
|
324
|
+
function = function_queue.shift
|
325
|
+
function_queue.push(function)
|
326
|
+
case command
|
327
|
+
when MESSAGE_SEND_ASYNC
|
328
|
+
begin
|
329
|
+
response = function.call(ASYNC, name, pattern,
|
330
|
+
request_info, request,
|
331
|
+
timeout, priority, trans_id, pid)
|
332
|
+
if response.kind_of?(Array)
|
333
|
+
API.assert{response.length == 2}
|
334
|
+
response_info = response[0]
|
335
|
+
response = response[1]
|
336
|
+
if not response_info.kind_of?(String)
|
337
|
+
response_info = ''
|
338
|
+
end
|
339
|
+
else
|
340
|
+
response_info = ''
|
341
|
+
end
|
342
|
+
if not response.kind_of?(String)
|
343
|
+
response = ''
|
344
|
+
end
|
345
|
+
rescue ReturnAsyncException
|
346
|
+
return
|
347
|
+
rescue ForwardAsyncException
|
348
|
+
return
|
349
|
+
rescue ReturnSyncException => e
|
350
|
+
$stderr.puts e.message
|
351
|
+
$stderr.puts e.backtrace
|
352
|
+
API.assert{false}
|
353
|
+
return
|
354
|
+
rescue ForwardSyncException => e
|
355
|
+
$stderr.puts e.message
|
356
|
+
$stderr.puts e.backtrace
|
357
|
+
API.assert{false}
|
358
|
+
return
|
359
|
+
rescue
|
360
|
+
$stderr.puts $!.message
|
361
|
+
$stderr.puts $!.backtrace
|
362
|
+
response_info = ''
|
363
|
+
response = ''
|
364
|
+
end
|
365
|
+
begin
|
366
|
+
return_async(name, pattern, response_info, response,
|
367
|
+
timeout, trans_id, pid)
|
368
|
+
rescue ReturnAsyncException
|
369
|
+
end
|
370
|
+
when MESSAGE_SEND_SYNC
|
371
|
+
begin
|
372
|
+
response = function.call(SYNC, name, pattern,
|
373
|
+
request_info, request,
|
374
|
+
timeout, priority, trans_id, pid)
|
375
|
+
if response.kind_of?(Array)
|
376
|
+
API.assert{response.length == 2}
|
377
|
+
response_info = response[0]
|
378
|
+
response = response[1]
|
379
|
+
if not response_info.kind_of?(String)
|
380
|
+
response_info = ''
|
381
|
+
end
|
382
|
+
else
|
383
|
+
response_info = ''
|
384
|
+
end
|
385
|
+
if not response.kind_of?(String)
|
386
|
+
response = ''
|
387
|
+
end
|
388
|
+
rescue ReturnSyncException
|
389
|
+
return
|
390
|
+
rescue ForwardSyncException
|
391
|
+
return
|
392
|
+
rescue ReturnAsyncException => e
|
393
|
+
$stderr.puts e.message
|
394
|
+
$stderr.puts e.backtrace
|
395
|
+
API.assert{false}
|
396
|
+
return
|
397
|
+
rescue ForwardAsyncException => e
|
398
|
+
$stderr.puts e.message
|
399
|
+
$stderr.puts e.backtrace
|
400
|
+
API.assert{false}
|
401
|
+
return
|
402
|
+
rescue
|
403
|
+
$stderr.puts $!.message
|
404
|
+
$stderr.puts $!.backtrace
|
405
|
+
response_info = ''
|
406
|
+
response = ''
|
407
|
+
end
|
408
|
+
begin
|
409
|
+
return_sync(name, pattern, response_info, response,
|
410
|
+
timeout, trans_id, pid)
|
411
|
+
rescue ReturnSyncException
|
412
|
+
end
|
413
|
+
else
|
414
|
+
raise MessageDecodingException
|
415
|
+
end
|
416
|
+
end
|
417
|
+
|
418
|
+
def poll_request(external)
|
419
|
+
if external and not @initialization_complete
|
420
|
+
send(term_to_binary(:polling))
|
421
|
+
@initialization_complete = true
|
422
|
+
end
|
423
|
+
|
424
|
+
ready = false
|
425
|
+
while ready == false
|
426
|
+
result = IO.select([@s], nil, [@s])
|
427
|
+
if result[2].length > 0
|
428
|
+
return nil
|
429
|
+
end
|
430
|
+
if result[0].length > 0
|
431
|
+
ready = true
|
432
|
+
end
|
433
|
+
end
|
434
|
+
|
435
|
+
data = recv('')
|
436
|
+
if data.bytesize == 0
|
437
|
+
return nil
|
438
|
+
end
|
439
|
+
|
440
|
+
loop do
|
441
|
+
i = 0; j = 4
|
442
|
+
command = data[i, j].unpack('L')[0]
|
443
|
+
case command
|
444
|
+
when MESSAGE_INIT
|
445
|
+
i += j; j = 4 + 4 + 4 + 4 + 4
|
446
|
+
tmp = data[i, j].unpack('LLLLL')
|
447
|
+
@processIndex = tmp[0]
|
448
|
+
@processCount = tmp[1]
|
449
|
+
@processCountMax = tmp[2]
|
450
|
+
@processCountMin = tmp[3]
|
451
|
+
prefixSize = tmp[4]
|
452
|
+
i += j; j = prefixSize + 4 + 4 + 1 + 1
|
453
|
+
tmp = data[i, j].unpack("Z#{prefixSize}LLcC")
|
454
|
+
@prefix = tmp[0]
|
455
|
+
@timeoutAsync = tmp[1]
|
456
|
+
@timeoutSync = tmp[2]
|
457
|
+
@priorityDefault = tmp[3]
|
458
|
+
@requestTimeoutAdjustment = (tmp[4] != 0)
|
459
|
+
i += j
|
460
|
+
if i != data.length
|
461
|
+
raise MessageDecodingException
|
462
|
+
end
|
463
|
+
return
|
464
|
+
when MESSAGE_SEND_ASYNC, MESSAGE_SEND_SYNC
|
465
|
+
i += j; j = 4
|
466
|
+
nameSize = data[i, j].unpack('L')[0]
|
467
|
+
i += j; j = nameSize + 4
|
468
|
+
tmp = data[i, j].unpack("Z#{nameSize}L")
|
469
|
+
name = tmp[0]
|
470
|
+
patternSize = tmp[1]
|
471
|
+
i += j; j = patternSize + 4
|
472
|
+
tmp = data[i, j].unpack("Z#{patternSize}L")
|
473
|
+
pattern = tmp[0]
|
474
|
+
requestInfoSize = tmp[1]
|
475
|
+
i += j; j = requestInfoSize + 1 + 4
|
476
|
+
tmp = data[i, j].unpack("a#{requestInfoSize}xL")
|
477
|
+
request_info = tmp[0]
|
478
|
+
requestSize = tmp[1]
|
479
|
+
i += j; j = requestSize + 1 + 4 + 1 + 16 + 4
|
480
|
+
tmp = data[i, j].unpack("a#{requestSize}xLca16L")
|
481
|
+
request = tmp[0]
|
482
|
+
timeout = tmp[1]
|
483
|
+
priority = tmp[2]
|
484
|
+
trans_id = tmp[3]
|
485
|
+
pidSize = tmp[4]
|
486
|
+
i += j; j = pidSize
|
487
|
+
pid = data[i, j].unpack("a#{pidSize}")[0]
|
488
|
+
i += j
|
489
|
+
if i != data.length
|
490
|
+
raise MessageDecodingException
|
491
|
+
end
|
492
|
+
data.clear()
|
493
|
+
callback(command, name, pattern, request_info, request,
|
494
|
+
timeout, priority, trans_id, binary_to_term(pid))
|
495
|
+
when MESSAGE_RECV_ASYNC, MESSAGE_RETURN_SYNC
|
496
|
+
i += j; j = 4
|
497
|
+
responseInfoSize = data[i, j].unpack('L')[0]
|
498
|
+
i += j; j = responseInfoSize + 1 + 4
|
499
|
+
tmp = data[i, j].unpack("a#{responseInfoSize}xL")
|
500
|
+
response_info = tmp[0]
|
501
|
+
responseSize = tmp[1]
|
502
|
+
i += j; j = responseSize + 1 + 16
|
503
|
+
tmp = data[i, j].unpack("a#{responseSize}xa16")
|
504
|
+
response = tmp[0]
|
505
|
+
trans_id = tmp[1]
|
506
|
+
i += j
|
507
|
+
if i != data.length
|
508
|
+
raise MessageDecodingException
|
509
|
+
end
|
510
|
+
return [response_info, response, trans_id]
|
511
|
+
when MESSAGE_RETURN_ASYNC
|
512
|
+
i += j; j = 16
|
513
|
+
trans_id = data[i, j].unpack('a16')[0]
|
514
|
+
i += j
|
515
|
+
if i != data.length
|
516
|
+
raise MessageDecodingException
|
517
|
+
end
|
518
|
+
return trans_id
|
519
|
+
when MESSAGE_RETURNS_ASYNC
|
520
|
+
i += j; j = 4
|
521
|
+
transIdCount = data[i, j].unpack('L')[0]
|
522
|
+
i += j; j = 16 * transIdCount
|
523
|
+
transIdList = data[i, j].unpack('a16' * transIdCount)
|
524
|
+
i += j
|
525
|
+
if i != data.length
|
526
|
+
raise MessageDecodingException
|
527
|
+
end
|
528
|
+
return transIdList
|
529
|
+
when MESSAGE_KEEPALIVE
|
530
|
+
send(term_to_binary(:keepalive))
|
531
|
+
i += j
|
532
|
+
if i < data.length
|
533
|
+
raise MessageDecodingException
|
534
|
+
end
|
535
|
+
data.slice!(0, i)
|
536
|
+
if data.length > 0
|
537
|
+
if IO.select([@s], nil, nil, 0).nil?
|
538
|
+
next
|
539
|
+
end
|
540
|
+
end
|
541
|
+
else
|
542
|
+
raise MessageDecodingException
|
543
|
+
end
|
544
|
+
|
545
|
+
ready = false
|
546
|
+
while ready == false
|
547
|
+
result = IO.select([@s], nil, [@s])
|
548
|
+
if result[2].length > 0
|
549
|
+
return nil
|
550
|
+
end
|
551
|
+
if result[0].length > 0
|
552
|
+
ready = true
|
553
|
+
end
|
554
|
+
end
|
555
|
+
|
556
|
+
data = recv(data)
|
557
|
+
if data.bytesize == 0
|
558
|
+
return nil
|
559
|
+
end
|
560
|
+
end
|
561
|
+
end
|
562
|
+
|
563
|
+
def poll
|
564
|
+
poll_request(true)
|
565
|
+
end
|
566
|
+
|
567
|
+
def binary_key_value_parse(binary)
|
568
|
+
result = {}
|
569
|
+
data = binary.split(NULL.chr)
|
570
|
+
(0...(data.length)).step(2).each do |i|
|
571
|
+
value = result[data[i]]
|
572
|
+
if value == nil
|
573
|
+
result[data[i]] = data[i + 1]
|
574
|
+
elsif value.kind_of?(Array)
|
575
|
+
value << data[i + 1]
|
576
|
+
else
|
577
|
+
result[data[i]] = [value, data[i + 1]]
|
578
|
+
end
|
579
|
+
end
|
580
|
+
result
|
581
|
+
end
|
582
|
+
|
583
|
+
def request_http_qs_parse(request)
|
584
|
+
binary_key_value_parse(request)
|
585
|
+
end
|
586
|
+
|
587
|
+
def info_key_value_parse(message_info)
|
588
|
+
binary_key_value_parse(message_info)
|
589
|
+
end
|
590
|
+
|
591
|
+
def self.assert
|
592
|
+
raise 'Assertion failed !' unless yield # if $DEBUG
|
593
|
+
end
|
594
|
+
|
595
|
+
private :callback
|
596
|
+
private :poll_request
|
597
|
+
private :binary_key_value_parse
|
598
|
+
private
|
599
|
+
|
600
|
+
def send(data)
|
601
|
+
if @use_header
|
602
|
+
data = [data.length].pack('N') + data
|
603
|
+
end
|
604
|
+
@s.write(data)
|
605
|
+
end
|
606
|
+
|
607
|
+
def recv(data)
|
608
|
+
if @use_header
|
609
|
+
while data.length < 4
|
610
|
+
fragment = @s.readpartial(@size)
|
611
|
+
data += fragment
|
612
|
+
end
|
613
|
+
total = data[0,4].unpack('N')[0]
|
614
|
+
data.slice!(0..3)
|
615
|
+
while data.length < total
|
616
|
+
fragment = @s.readpartial(@size)
|
617
|
+
data += fragment
|
618
|
+
end
|
619
|
+
else
|
620
|
+
ready = true
|
621
|
+
while ready == true
|
622
|
+
fragment = @s.readpartial(@size)
|
623
|
+
data += fragment
|
624
|
+
ready = (fragment.bytesize == @size)
|
625
|
+
|
626
|
+
if ready
|
627
|
+
ready = ! IO.select([@s], nil, nil, 0).nil?
|
628
|
+
end
|
629
|
+
end
|
630
|
+
end
|
631
|
+
data
|
632
|
+
end
|
633
|
+
|
634
|
+
MESSAGE_INIT = 1
|
635
|
+
MESSAGE_SEND_ASYNC = 2
|
636
|
+
MESSAGE_SEND_SYNC = 3
|
637
|
+
MESSAGE_RECV_ASYNC = 4
|
638
|
+
MESSAGE_RETURN_ASYNC = 5
|
639
|
+
MESSAGE_RETURN_SYNC = 6
|
640
|
+
MESSAGE_RETURNS_ASYNC = 7
|
641
|
+
MESSAGE_KEEPALIVE = 8
|
642
|
+
|
643
|
+
NULL = 0
|
644
|
+
|
645
|
+
def self.getenv(key)
|
646
|
+
ENV[key] or raise InvalidInputException
|
647
|
+
end
|
648
|
+
end
|
649
|
+
|
650
|
+
class InvalidInputException < Exception
|
651
|
+
end
|
652
|
+
|
653
|
+
class ReturnSyncException < Exception
|
654
|
+
end
|
655
|
+
|
656
|
+
class ReturnAsyncException < Exception
|
657
|
+
end
|
658
|
+
|
659
|
+
class ForwardSyncException < Exception
|
660
|
+
end
|
661
|
+
|
662
|
+
class ForwardAsyncException < Exception
|
663
|
+
end
|
664
|
+
|
665
|
+
class MessageDecodingException < Exception
|
666
|
+
end
|
667
|
+
end
|
668
|
+
|
metadata
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cloudi
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.3.2
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Michael Truog
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain:
|
12
|
+
- ! '-----BEGIN CERTIFICATE-----
|
13
|
+
|
14
|
+
MIIDMDCCAhigAwIBAgIBADANBgkqhkiG9w0BAQUFADA+MRAwDgYDVQQDDAdtanRy
|
15
|
+
|
16
|
+
dW9nMRUwEwYKCZImiZPyLGQBGRYFZ21haWwxEzARBgoJkiaJk/IsZAEZFgNjb20w
|
17
|
+
|
18
|
+
HhcNMTQwNjI0MjAzMDQ2WhcNMTUwNjI0MjAzMDQ2WjA+MRAwDgYDVQQDDAdtanRy
|
19
|
+
|
20
|
+
dW9nMRUwEwYKCZImiZPyLGQBGRYFZ21haWwxEzARBgoJkiaJk/IsZAEZFgNjb20w
|
21
|
+
|
22
|
+
ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDBOoI/CUuwOhXjks02cT58
|
23
|
+
|
24
|
+
jLxgsOQ412Xzu4eEKqzNsWMoj/3+qYdb5CR4+51EHtuJHZ8hndL5DTYIO8ylcG11
|
25
|
+
|
26
|
+
EvyxqOzU+gqC53gCEBhJLivlyMXvGqL8qHPuSKGEMc1Vpzh0WicwNnaT7z3X6aQP
|
27
|
+
|
28
|
+
UE6qWd1yE9jT7TX+GKcKayBJTufxcBMjtwvzMH4IiVaNjUBHBq2LbeNO1yDPYVzV
|
29
|
+
|
30
|
+
HWnZCv75vIXdUruFrSZcJgNRYRwzMfHEbf+BcvqqGVV6p3PJgJMrjI8FZ7roIJNf
|
31
|
+
|
32
|
+
D7ZO96x4ItjGazoTntAZe3EM9QB5Wjsd1cv2IEOISQ6jyvVX5E84Al+MEKhhhFuL
|
33
|
+
|
34
|
+
AgMBAAGjOTA3MAkGA1UdEwQCMAAwHQYDVR0OBBYEFACw0UcBaNl2dQWwgg/Qzeyf
|
35
|
+
|
36
|
+
cKG7MAsGA1UdDwQEAwIEsDANBgkqhkiG9w0BAQUFAAOCAQEAHjLn+8F8yeOFcKst
|
37
|
+
|
38
|
+
mKA3m28OIoICMefZOiJfTC9UkVkW+554IXNBu3vVxLc0nlCqmuf/aQGaFBUm9MLA
|
39
|
+
|
40
|
+
oD5CmlrU9OrEl2fPxqTHAwFgLNre8e2EWtm2OhBg73JTHRVVyBLpSK5GRUDzhJtZ
|
41
|
+
|
42
|
+
7a2ocAE2AgFKpISNxIUe4Zz9O2thg3iryLh9prjETJTUfxDjBmHdx+YkNAblRa2w
|
43
|
+
|
44
|
+
k9A+nCZzZECcR5ZZYSeaK6MCugGmXUhAkDbuWumCzu/RAghlVC9RFFQt7o1SwGQp
|
45
|
+
|
46
|
+
LdvYOeJbviyiH1q1rC3NAJNC4P7Q41zx1OYa8S9M5qn+JpE0ZsomnZyGunWaya9Q
|
47
|
+
|
48
|
+
bTD/aw==
|
49
|
+
|
50
|
+
-----END CERTIFICATE-----
|
51
|
+
|
52
|
+
'
|
53
|
+
date: 2014-06-24 00:00:00.000000000 Z
|
54
|
+
dependencies:
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: erlang_rb
|
57
|
+
requirement: &11610740 !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ~>
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '1.3'
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: 1.3.2
|
66
|
+
type: :runtime
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *11610740
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: erlang_rb
|
71
|
+
requirement: &11608600 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ~>
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '1.3'
|
77
|
+
- - ! '>='
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: 1.3.2
|
80
|
+
type: :development
|
81
|
+
prerelease: false
|
82
|
+
version_requirements: *11608600
|
83
|
+
description: Ruby CloudI API
|
84
|
+
email: mjtruog@gmail.com
|
85
|
+
executables: []
|
86
|
+
extensions: []
|
87
|
+
extra_rdoc_files:
|
88
|
+
- README.markdown
|
89
|
+
files:
|
90
|
+
- lib/cloudi.rb
|
91
|
+
- README.markdown
|
92
|
+
homepage: http://cloudi.org
|
93
|
+
licenses:
|
94
|
+
- BSD
|
95
|
+
post_install_message:
|
96
|
+
rdoc_options: []
|
97
|
+
require_paths:
|
98
|
+
- lib
|
99
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
100
|
+
none: false
|
101
|
+
requirements:
|
102
|
+
- - ! '>='
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0'
|
105
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
106
|
+
none: false
|
107
|
+
requirements:
|
108
|
+
- - ! '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
requirements: []
|
112
|
+
rubyforge_project:
|
113
|
+
rubygems_version: 1.8.11
|
114
|
+
signing_key:
|
115
|
+
specification_version: 3
|
116
|
+
summary: CloudI API
|
117
|
+
test_files: []
|
metadata.gz.sig
ADDED
Binary file
|