emdrb 0.1.2 → 0.2.0
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/History.txt +12 -2
- data/LEGAL +1 -1
- data/Manifest.txt +5 -1
- data/README.txt +50 -18
- data/Rakefile +21 -3
- data/lib/emdrb/emdrb.rb +176 -116
- data/lib/emdrb/version.rb +3 -3
- data/spec/client_spec.rb +61 -0
- data/spec/drbserver.rb +78 -0
- data/spec/server_spec.rb +51 -0
- data/spec/spec_common.rb +34 -0
- data/spec/spec_helper.rb +36 -0
- data/tasks/ann.rake +1 -1
- data/tasks/bones.rake +1 -1
- data/tasks/gem.rake +1 -1
- data/tasks/git.rake +1 -1
- data/tasks/manifest.rake +1 -1
- data/tasks/notes.rake +1 -1
- data/tasks/post_load.rake +1 -1
- data/tasks/rdoc.rake +1 -1
- data/tasks/setup.rb +1 -1
- data/tasks/spec.rake +1 -1
- data/tasks/svn.rake +1 -1
- data/tasks/test.rake +1 -1
- metadata +9 -5
- data/test/test_emdrb.rb +0 -96
data/History.txt
CHANGED
@@ -1,7 +1,17 @@
|
|
1
|
-
== 0.
|
1
|
+
== 0.2.0 / 2009-01-23
|
2
2
|
|
3
|
-
*
|
3
|
+
* DRb client implementation, including asynchronous calls.
|
4
|
+
* Changes so that DRb functionality is as untouched as possible.
|
5
|
+
|
6
|
+
== 0.1.2 / 2009-01-21
|
7
|
+
|
8
|
+
* Maintenance release
|
4
9
|
|
5
10
|
== 0.1.1 / 2008-12-02
|
6
11
|
|
7
12
|
* Basic unit tests
|
13
|
+
|
14
|
+
== 0.1.0 / 2008-10-23
|
15
|
+
|
16
|
+
* First public release
|
17
|
+
|
data/LEGAL
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
LEGAL NOTICE INFORMATION
|
2
2
|
------------------------
|
3
3
|
|
4
|
-
EMDRb is Copyright
|
4
|
+
EMDRb is Copyright © 2008, 2009 by Rafael Sevilla.
|
5
5
|
|
6
6
|
EMDRb is copyrighted software owned by Rafael Sevilla (dido
|
7
7
|
... imperium.ph). You may redistribute and/or modify this software as
|
data/Manifest.txt
CHANGED
@@ -7,6 +7,11 @@ Rakefile
|
|
7
7
|
lib/emdrb.rb
|
8
8
|
lib/emdrb/emdrb.rb
|
9
9
|
lib/emdrb/version.rb
|
10
|
+
spec/client_spec.rb
|
11
|
+
spec/drbserver.rb
|
12
|
+
spec/server_spec.rb
|
13
|
+
spec/spec_common.rb
|
14
|
+
spec/spec_helper.rb
|
10
15
|
tasks/ann.rake
|
11
16
|
tasks/bones.rake
|
12
17
|
tasks/gem.rake
|
@@ -20,4 +25,3 @@ tasks/setup.rb
|
|
20
25
|
tasks/spec.rake
|
21
26
|
tasks/svn.rake
|
22
27
|
tasks/test.rake
|
23
|
-
test/test_emdrb.rb
|
data/README.txt
CHANGED
@@ -10,20 +10,19 @@ available in the Ruby standard library.
|
|
10
10
|
|
11
11
|
== FEATURES/PROBLEMS:
|
12
12
|
|
13
|
-
This is a simple but working DRb server implementation that
|
14
|
-
EventMachine as its basis, rather than the default implementation
|
15
|
-
uses traditional Ruby sockets. This should at the very least
|
16
|
-
better with other programs that have an EventMachine event loop,
|
17
|
-
hopefully provide somewhat better scalability.
|
13
|
+
This is a simple but working DRb client/server implementation that
|
14
|
+
uses EventMachine as its basis, rather than the default implementation
|
15
|
+
that uses traditional Ruby sockets. This should at the very least
|
16
|
+
play better with other programs that have an EventMachine event loop,
|
17
|
+
and hopefully provide somewhat better scalability.
|
18
18
|
|
19
19
|
Obviously, this is a quick and dirty release, just to get something
|
20
|
-
out there, and of course it has a number of limitations
|
20
|
+
out there, and of course it has a number of limitations:
|
21
21
|
|
22
|
-
* We still don't have a DRb client. We use the client implementation
|
23
|
-
of the standard DRb.
|
24
22
|
* No SSL support.
|
25
23
|
* No support for ACLs.
|
26
|
-
* No
|
24
|
+
* No support for DRb over Unix domain sockets.
|
25
|
+
* RSpec tests are very basic, and need a lot more comprehensive work.
|
27
26
|
* Many standard configuration options for DRb still unsupported
|
28
27
|
|
29
28
|
These and many other problems are scheduled to be addressed in the
|
@@ -31,8 +30,11 @@ next release.
|
|
31
30
|
|
32
31
|
== SYNOPSIS:
|
33
32
|
|
34
|
-
|
35
|
-
|
33
|
+
EMDRb basically reopens several classes and adds methods and overrides
|
34
|
+
some methods in the basic distributed Ruby implementation to make it
|
35
|
+
use EventMachine's infrastructure instead of the normal networking
|
36
|
+
layer. One could do the following, which is practically identical to
|
37
|
+
one of the examples for distributed Ruby:
|
36
38
|
|
37
39
|
require 'emdrb'
|
38
40
|
|
@@ -45,10 +47,35 @@ making one with the standard library DRb:
|
|
45
47
|
end
|
46
48
|
|
47
49
|
$SAFE=1
|
48
|
-
|
49
|
-
|
50
|
+
DRb.start_service(URI, TimeServer.new)
|
51
|
+
DRb.thread.join
|
50
52
|
|
51
|
-
|
53
|
+
The corresponding client code could be made nearly identical:
|
54
|
+
|
55
|
+
require 'emdrb'
|
56
|
+
|
57
|
+
SERVER_URI="druby://localhost:8787"
|
58
|
+
|
59
|
+
DRb.start_service
|
60
|
+
|
61
|
+
timeserver = DRbObject.new_with_uri(SERVER_URI)
|
62
|
+
puts timeserver.get_current_time
|
63
|
+
|
64
|
+
Or it could be written to use of asynchronous calls:
|
65
|
+
|
66
|
+
require 'emdrb'
|
67
|
+
|
68
|
+
SERVER_URI="druby://localhost:8787"
|
69
|
+
|
70
|
+
DRb.start_service
|
71
|
+
|
72
|
+
timeserver = DRbObject.new_with_uri(SERVER_URI)
|
73
|
+
|
74
|
+
EventMachine::next_tick do
|
75
|
+
timeserver.async_call(:get_current_time).callback do |res|
|
76
|
+
puts res
|
77
|
+
end
|
78
|
+
end
|
52
79
|
|
53
80
|
== REQUIREMENTS:
|
54
81
|
|
@@ -58,11 +85,16 @@ It is also possible to create
|
|
58
85
|
|
59
86
|
* Standard gem installation: 'sudo gem install' ought to do the trick.
|
60
87
|
|
61
|
-
|
88
|
+
Note that you will need the daemons gem ('sudo gem install daemons')
|
89
|
+
if you would like to run the rspec tests that are included with
|
90
|
+
EMDRb. Daemons is not required to use EMDRb otherwise, and as such it
|
91
|
+
is not listed as a hard dependency in the gem install.
|
62
92
|
|
63
|
-
|
64
|
-
modify it under the same terms as Ruby. Please see the file COPYING for
|
65
|
-
more details.
|
93
|
+
== LICENSE:
|
66
94
|
|
95
|
+
Copyright © 2008, 2009 Rafael R. Sevilla. You can redistribute it
|
96
|
+
and/or modify it under the same terms as Ruby. Please see the file
|
97
|
+
COPYING for more details.
|
67
98
|
|
99
|
+
$Id: README.txt 63 2009-01-23 09:15:55Z dido $
|
68
100
|
|
data/Rakefile
CHANGED
@@ -1,12 +1,31 @@
|
|
1
1
|
# -*- Ruby -*-
|
2
|
-
#
|
2
|
+
#
|
3
|
+
# Author:: Rafael R. Sevilla (mailto:dido@imperium.ph)
|
4
|
+
# Copyright:: Copyright © 2008, 2009 Rafael R. Sevilla
|
5
|
+
# Homepage:: http://emdrb.rubyforge.org/
|
6
|
+
# License:: GNU General Public License / Ruby License
|
7
|
+
#
|
8
|
+
# $Id: Rakefile 61 2009-01-23 09:11:43Z dido $
|
9
|
+
#
|
10
|
+
#----------------------------------------------------------------------------
|
11
|
+
#
|
12
|
+
# Copyright © 2008, 2009 Rafael Sevilla
|
13
|
+
# This file is part of EMDRb
|
14
|
+
#
|
15
|
+
# This program is free software; you can redistribute it and/or modify
|
16
|
+
# it under the terms of either: 1) the GNU General Public License
|
17
|
+
# as published by the Free Software Foundation; either version 2 of the
|
18
|
+
# License, or (at your option) any later version; or 2) Ruby's License.
|
19
|
+
#
|
20
|
+
# See the file COPYING for complete licensing information.
|
21
|
+
#----------------------------------------------------------------------------
|
3
22
|
#
|
4
23
|
load 'tasks/setup.rb'
|
5
24
|
|
6
25
|
ensure_in_path 'lib'
|
7
26
|
require 'emdrb/version'
|
8
27
|
|
9
|
-
task :default => '
|
28
|
+
task :default => 'spec:run'
|
10
29
|
|
11
30
|
PROJ.name = 'emdrb'
|
12
31
|
PROJ.authors = 'dido@imperium.ph'
|
@@ -15,7 +34,6 @@ PROJ.url = 'http://emdrb.rubyforge.org'
|
|
15
34
|
PROJ.rubyforge.name = 'emdrb'
|
16
35
|
PROJ.version = EMDRb::Version::STRING
|
17
36
|
PROJ.dependencies = ["eventmachine"]
|
18
|
-
PROJ.rcov.opts += ["-Ilib"] # Why is this necessary?
|
19
37
|
|
20
38
|
PROJ.spec.opts << '--color'
|
21
39
|
|
data/lib/emdrb/emdrb.rb
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
#
|
2
2
|
# Author:: Rafael R. Sevilla (mailto:dido@imperium.ph)
|
3
|
-
# Copyright:: Copyright
|
3
|
+
# Copyright:: Copyright © 2008, 2009 Rafael R. Sevilla
|
4
4
|
# Homepage:: http://emdrb.rubyforge.org/
|
5
5
|
# License:: GNU General Public License / Ruby License
|
6
6
|
#
|
7
|
-
# $Id: emdrb.rb
|
7
|
+
# $Id: emdrb.rb 49 2009-01-23 08:51:47Z dido $
|
8
8
|
#
|
9
9
|
#----------------------------------------------------------------------------
|
10
10
|
#
|
11
|
-
# Copyright
|
11
|
+
# Copyright © 2008, 2009 Rafael Sevilla
|
12
12
|
# This file is part of EMDRb
|
13
13
|
#
|
14
14
|
# This program is free software; you can redistribute it and/or modify
|
@@ -20,9 +20,10 @@
|
|
20
20
|
#----------------------------------------------------------------------------
|
21
21
|
#
|
22
22
|
require 'eventmachine'
|
23
|
+
require 'thread'
|
23
24
|
require 'drb'
|
24
25
|
|
25
|
-
module
|
26
|
+
module DRb
|
26
27
|
DEFAULT_ARGC_LIMIT = 256
|
27
28
|
DEFAULT_LOAD_LIMIT = 256 * 102400
|
28
29
|
DEFAULT_SAFE_LEVEL = 0
|
@@ -40,7 +41,7 @@ module EMDRb
|
|
40
41
|
# byte order.
|
41
42
|
#
|
42
43
|
def dump(obj, error=false)
|
43
|
-
if obj.kind_of?
|
44
|
+
if obj.kind_of? DRbUndumped
|
44
45
|
obj = make_proxy(obj, error)
|
45
46
|
end
|
46
47
|
begin
|
@@ -55,22 +56,21 @@ module EMDRb
|
|
55
56
|
# Create a proxy for +obj+ that is declared to be undumpable.
|
56
57
|
#
|
57
58
|
def make_proxy(obj, error=false)
|
58
|
-
return(error ?
|
59
|
+
return(error ? DRbRemoteError.new(obj) : DRbObject.new(obj))
|
59
60
|
end
|
60
61
|
|
61
62
|
##
|
62
63
|
# Receive data from the caller. This basically receives packets
|
63
64
|
# containing objects marshalled using Ruby's Marshal::dump prefixed
|
64
65
|
# by a length. These objects are unmarshalled and processed by the
|
65
|
-
# internal object request state machine
|
66
|
-
#
|
67
|
-
|
68
|
-
def receive_data(data)
|
66
|
+
# internal object request state machine which should be represented by
|
67
|
+
# a receive_obj method from within the mixin.
|
68
|
+
def receive_data_raw(data)
|
69
69
|
@msgbuffer << data
|
70
70
|
while @msgbuffer.length > 4
|
71
71
|
length = @msgbuffer.unpack("N")[0]
|
72
72
|
if length > @load_limit
|
73
|
-
raise
|
73
|
+
raise DRbConnError, "too large packet #{length}"
|
74
74
|
end
|
75
75
|
|
76
76
|
if @msgbuffer.length < length - 4
|
@@ -89,7 +89,7 @@ module EMDRb
|
|
89
89
|
begin
|
90
90
|
return(Marshal::load(message))
|
91
91
|
rescue NameError, ArgumentError
|
92
|
-
return(
|
92
|
+
return(DRbUnknown.new($!, message))
|
93
93
|
end
|
94
94
|
end
|
95
95
|
end
|
@@ -161,79 +161,111 @@ module EMDRb
|
|
161
161
|
|
162
162
|
##
|
163
163
|
# This method will perform a method action if a block is not specified.
|
164
|
-
#
|
164
|
+
# For symmetry with perform_with_block, this method returns a deferrable
|
165
|
+
# instead of the actual value or exception as the case may be. It will
|
166
|
+
# also further execute the method call in its own independent thread
|
167
|
+
# and safe level invocations are also taken care of herein.
|
165
168
|
def perform_without_block
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
+
df = EventMachine::DefaultDeferrable.new
|
170
|
+
info = Thread.current['DRb']
|
171
|
+
req = @request
|
172
|
+
Thread.new do
|
173
|
+
Thread.current['DRb'] = info
|
174
|
+
if $SAFE < @safe_level
|
175
|
+
$SAFE = @safe_level
|
176
|
+
end
|
177
|
+
begin
|
178
|
+
if Proc == req[:ro] && req[:msg] == :__drb_yield
|
179
|
+
ary = (req[:argv].size == 1) ? req[:argv] :
|
180
|
+
[req[:argv]]
|
181
|
+
EventMachine::next_tick do
|
182
|
+
df.set_deferred_status(:succeeded, ary.collect(&@front)[0])
|
183
|
+
end
|
184
|
+
else
|
185
|
+
r = req[:ro].__send__(req[:msg], *req[:argv])
|
186
|
+
EventMachine::next_tick do
|
187
|
+
df.set_deferred_status(:succeeded, r)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
rescue
|
191
|
+
p $!
|
192
|
+
EventMachine::next_tick do
|
193
|
+
df.set_deferred_status(:failed, $!)
|
194
|
+
end
|
195
|
+
end
|
169
196
|
end
|
170
|
-
return(
|
197
|
+
return(df)
|
171
198
|
end
|
172
199
|
|
173
200
|
##
|
174
201
|
# block_yield method lifted almost verbatim from InvokeMethod18Mixin
|
175
202
|
# from the standard distributed Ruby. Obviously, since EventMachine
|
176
203
|
# doesn't work with Ruby 1.6.x, we don't care about the 1.6 version...
|
177
|
-
#
|
178
|
-
|
204
|
+
# Since this performs a synchronous DRb call, we need to execute this
|
205
|
+
# within a thread of its own.
|
206
|
+
def block_yield(req, x)
|
179
207
|
if x.size == 1 && x[0].class == Array
|
180
|
-
x[0] =
|
208
|
+
x[0] = DRbArray.new(x[0])
|
181
209
|
end
|
182
|
-
block_value =
|
210
|
+
block_value = req[:block].call(*x)
|
211
|
+
return(block_value)
|
183
212
|
end
|
184
213
|
|
185
214
|
##
|
186
|
-
# Perform with a method action with a specified block.
|
187
|
-
#
|
215
|
+
# Perform with a method action with a specified block. We have to
|
216
|
+
# do the action within a thread of its own in order to avoid deadlock
|
217
|
+
# due to the call in block_yield above, which uses synchronous calls.
|
218
|
+
# I suppose there must be a way to do it without using threads (possibly
|
219
|
+
# by using call/cc perhaps?), but I suppose this should be okay.
|
188
220
|
def perform_with_block
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
221
|
+
df = EventMachine::DefaultDeferrable.new
|
222
|
+
info = Thread.current['DRb']
|
223
|
+
req = @request
|
224
|
+
Thread.new do
|
225
|
+
Thread.current['DRb'] = info
|
226
|
+
if $SAFE < @safe_level
|
227
|
+
$SAFE = @safe_level
|
195
228
|
end
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
229
|
+
begin
|
230
|
+
r = req[:ro].__send__(req[:msg], *req[:argv]) { |*x|
|
231
|
+
jump_error = nil
|
232
|
+
block_value = nil
|
233
|
+
begin
|
234
|
+
block_value = block_yield(req, x)
|
235
|
+
rescue LocalJumpError
|
236
|
+
jump_error = $!
|
237
|
+
end
|
238
|
+
if jump_error
|
239
|
+
case jump_error.reason
|
240
|
+
when :retry
|
241
|
+
retry
|
242
|
+
when :break
|
243
|
+
break(jump_error.exit_value)
|
244
|
+
else
|
245
|
+
raise jump_error
|
246
|
+
end
|
247
|
+
end
|
248
|
+
block_value
|
249
|
+
}
|
250
|
+
EventMachine::next_tick { df.set_deferred_status(:succeeded, r) }
|
251
|
+
rescue Exception => e
|
252
|
+
EventMachine::next_tick do
|
253
|
+
df.set_deferred_status(:failed, e)
|
204
254
|
end
|
205
255
|
end
|
206
|
-
block_value
|
207
256
|
end
|
257
|
+
return(df)
|
208
258
|
end
|
209
259
|
|
210
260
|
##
|
211
|
-
# Perform a method action. This
|
261
|
+
# Perform a method action. This returns a deferrable that gets
|
262
|
+
# posted to succeeded or failed depending on whether the method
|
263
|
+
# call did not raise or raised an exception while it was being
|
264
|
+
# executed.
|
212
265
|
#
|
213
266
|
def perform
|
214
|
-
|
215
|
-
|
216
|
-
begin
|
217
|
-
@server.check_insecure_method(@front, @request[:msg])
|
218
|
-
if $SAFE < @safe_level
|
219
|
-
info = Thread.current['DRb']
|
220
|
-
result = Thread.new {
|
221
|
-
Thread.current['DRb'] = info
|
222
|
-
$SAFE = @safe_level
|
223
|
-
(@request[:block]) ? perform_with_block : perform_without_block
|
224
|
-
}.value
|
225
|
-
else
|
226
|
-
result = (@request[:block]) ? perform_with_block :
|
227
|
-
perform_without_block
|
228
|
-
succ = true
|
229
|
-
if @request[:msg] == :to_ary && result.class == Array
|
230
|
-
result = DRb::DRbArray.new(result)
|
231
|
-
end
|
232
|
-
end
|
233
|
-
rescue StandardError, ScriptError, Interrupt
|
234
|
-
result = $!
|
235
|
-
end
|
236
|
-
return([succ, result])
|
267
|
+
@server.check_insecure_method(@request[:ro], @request[:msg])
|
268
|
+
return((@request[:block]) ? perform_with_block : perform_without_block)
|
237
269
|
end
|
238
270
|
|
239
271
|
def to_obj(ref)
|
@@ -283,7 +315,16 @@ module EMDRb
|
|
283
315
|
when :block
|
284
316
|
@request[:argv] = @argv
|
285
317
|
@state = :ref
|
286
|
-
|
318
|
+
df = perform
|
319
|
+
df.callback do |result|
|
320
|
+
if @request[:msg] == :to_ary && result.class == Array
|
321
|
+
result = DRb::DRbArray.new(result)
|
322
|
+
end
|
323
|
+
send_reply(true, result)
|
324
|
+
end
|
325
|
+
df.errback do |error|
|
326
|
+
send_reply(false, error)
|
327
|
+
end
|
287
328
|
@request = {}
|
288
329
|
@argc = @argv = nil
|
289
330
|
else
|
@@ -291,6 +332,18 @@ module EMDRb
|
|
291
332
|
end
|
292
333
|
end
|
293
334
|
|
335
|
+
##
|
336
|
+
# This version of receive_data will propagate any exceptions thrown
|
337
|
+
# by receive_data_raw back to the caller. This includes load limit
|
338
|
+
# errors and other miscellanea.
|
339
|
+
def receive_data(data)
|
340
|
+
begin
|
341
|
+
return(receive_data_raw(data))
|
342
|
+
rescue Exception => e
|
343
|
+
return(send_reply(false, e))
|
344
|
+
end
|
345
|
+
end
|
346
|
+
|
294
347
|
end
|
295
348
|
|
296
349
|
##
|
@@ -298,7 +351,7 @@ module EMDRb
|
|
298
351
|
# for brevity. DRbServer instances are normally created indirectly using
|
299
352
|
# either EMDRb.start service (which emulates DRb.start_service) or via
|
300
353
|
# EMDRb.start_drbserver (designed to be called from within an event loop).
|
301
|
-
class DRbServer
|
354
|
+
class DRbServer
|
302
355
|
def initialize(uri=nil, front=nil, config_or_acl=nil)
|
303
356
|
if Hash === config_or_acl
|
304
357
|
config = config_or_acl.dup
|
@@ -314,6 +367,9 @@ module EMDRb
|
|
314
367
|
@front = front
|
315
368
|
@idconv = @config[:idconv]
|
316
369
|
@safe_level = @config[:safe_level]
|
370
|
+
EventMachine::next_tick do
|
371
|
+
@thread = Thread.current
|
372
|
+
end
|
317
373
|
end
|
318
374
|
|
319
375
|
private
|
@@ -348,11 +404,11 @@ module EMDRb
|
|
348
404
|
#
|
349
405
|
def start_drb_server
|
350
406
|
@thread = Thread.current
|
351
|
-
host, port, opt =
|
407
|
+
host, port, opt = DRb::parse_uri_drb(@uri)
|
352
408
|
if host.size == 0
|
353
409
|
host = self.class.host_inaddr_any
|
354
410
|
end
|
355
|
-
EventMachine::start_server(host, port, DRbServerProtocol) do |conn|
|
411
|
+
r = EventMachine::start_server(host, port, DRbServerProtocol) do |conn|
|
356
412
|
Thread.current['DRb'] = { 'client' => conn, 'server' => self }
|
357
413
|
conn.front = @front
|
358
414
|
conn.load_limit = @config[:load_limit]
|
@@ -361,11 +417,18 @@ module EMDRb
|
|
361
417
|
conn.server = self
|
362
418
|
conn.safe_level = self.safe_level
|
363
419
|
end
|
420
|
+
# NOTE: This is an undocumented method in EventMachine. Revise
|
421
|
+
# as necessary when we receive feedback from the EventMachine
|
422
|
+
# developers on the canonical way to determine the real port number
|
423
|
+
# if port 0 was specified in start_server.
|
424
|
+
addr = Socket.unpack_sockaddr_in(EventMachine.get_sockname(r))
|
425
|
+
port = addr[0] if port == 0
|
426
|
+
@uri = "druby://#{host}:#{port}"
|
364
427
|
end
|
365
428
|
|
366
429
|
end
|
367
430
|
|
368
|
-
def
|
431
|
+
def parse_uri_drb(uri)
|
369
432
|
if uri =~ /^druby:\/\/(.*?):(\d+)(\?(.*))?$/
|
370
433
|
host = $1
|
371
434
|
port = $2.to_i
|
@@ -378,9 +441,8 @@ module EMDRb
|
|
378
441
|
raise DRb::DRbBadURI.new('can\'t parse uri:' + uri)
|
379
442
|
end
|
380
443
|
end
|
381
|
-
module_function :
|
444
|
+
module_function :parse_uri_drb
|
382
445
|
|
383
|
-
@primary_server = nil
|
384
446
|
@eventloop = nil
|
385
447
|
|
386
448
|
##
|
@@ -411,52 +473,11 @@ module EMDRb
|
|
411
473
|
end
|
412
474
|
serv = queue.shift
|
413
475
|
@primary_server = serv
|
414
|
-
|
476
|
+
DRb.regist_server(serv)
|
415
477
|
return(serv)
|
416
478
|
end
|
417
479
|
module_function :start_service
|
418
480
|
|
419
|
-
attr_accessor :primary_server
|
420
|
-
module_function :primary_server=, :primary_server
|
421
|
-
|
422
|
-
@server = {}
|
423
|
-
def regist_server(server)
|
424
|
-
@server[server.uri] = server
|
425
|
-
Thread.exclusive do
|
426
|
-
@primary_server = server unless @primary_server
|
427
|
-
end
|
428
|
-
end
|
429
|
-
module_function :regist_server
|
430
|
-
|
431
|
-
##
|
432
|
-
# Get the 'current' server.
|
433
|
-
#
|
434
|
-
# In the context of execution taking place within the main
|
435
|
-
# thread of a dRuby server (typically, as a result of a remote
|
436
|
-
# call on the server or one of its objects), the current
|
437
|
-
# server is that server. Otherwise, the current server is
|
438
|
-
# the primary server.
|
439
|
-
#
|
440
|
-
# If the above rule fails to find a server, a DRbServerNotFound
|
441
|
-
# error is raised.
|
442
|
-
def current_server
|
443
|
-
drb = Thread.current['DRb']
|
444
|
-
server = (drb && drb['server']) ? drb['server'] : @primary_server
|
445
|
-
raise DRb::DRbServerNotFound unless server
|
446
|
-
return server
|
447
|
-
end
|
448
|
-
module_function :current_server
|
449
|
-
|
450
|
-
##
|
451
|
-
# Get the thread of the primary server.
|
452
|
-
#
|
453
|
-
# This returns nil if there is no primary server. See #primary_server.
|
454
|
-
def thread
|
455
|
-
@primary_server ? @primary_server.thread : nil
|
456
|
-
end
|
457
|
-
module_function :thread
|
458
|
-
|
459
|
-
|
460
481
|
##
|
461
482
|
# Client protocol module
|
462
483
|
module DRbClientProtocol
|
@@ -470,7 +491,7 @@ module EMDRb
|
|
470
491
|
|
471
492
|
def post_init
|
472
493
|
@msgbuffer = ""
|
473
|
-
@idconv =
|
494
|
+
@idconv = DRbIdConv.new
|
474
495
|
@load_limit = DEFAULT_LOAD_LIMIT
|
475
496
|
end
|
476
497
|
|
@@ -506,6 +527,10 @@ module EMDRb
|
|
506
527
|
close_connection
|
507
528
|
end
|
508
529
|
end
|
530
|
+
|
531
|
+
def receive_data(data)
|
532
|
+
return(receive_data_raw(data))
|
533
|
+
end
|
509
534
|
end
|
510
535
|
|
511
536
|
##
|
@@ -513,7 +538,7 @@ module EMDRb
|
|
513
538
|
#
|
514
539
|
# Method calls on this object are relayed to the remote object
|
515
540
|
# that this object is a stub for.
|
516
|
-
class DRbObject
|
541
|
+
class DRbObject
|
517
542
|
def initialize(obj, uri=nil)
|
518
543
|
@uri = nil
|
519
544
|
@ref = nil
|
@@ -521,18 +546,22 @@ module EMDRb
|
|
521
546
|
return if uri.nil?
|
522
547
|
@uri = uri
|
523
548
|
ref = nil
|
524
|
-
@host, @port, @opt =
|
549
|
+
@host, @port, @opt = DRb::parse_uri_drb(@uri)
|
525
550
|
else
|
526
|
-
|
551
|
+
@uri = uri ? uri : (DRb.uri rescue nil)
|
552
|
+
@ref = obj ? DRb.to_id(obj) : nil
|
527
553
|
end
|
528
554
|
end
|
529
555
|
|
530
556
|
##
|
531
557
|
# Perform an asynchronous call to the remote object. This can only
|
532
|
-
# be used from within
|
558
|
+
# be used from within the event loop. It returns a deferrable to which
|
533
559
|
# callbacks can be attached.
|
534
560
|
def send_async(msg_id, *a, &b)
|
535
561
|
df = EventMachine::DefaultDeferrable.new
|
562
|
+
if @host.nil? || @port.nil?
|
563
|
+
@host, @port, @opt = DRb::parse_uri_drb(@uri)
|
564
|
+
end
|
536
565
|
EventMachine.connect(@host, @port, DRbClientProtocol) do |c|
|
537
566
|
c.ref = self
|
538
567
|
c.msg_id = msg_id
|
@@ -543,6 +572,37 @@ module EMDRb
|
|
543
572
|
return(df)
|
544
573
|
end
|
545
574
|
|
575
|
+
##
|
576
|
+
# Route method calls to the referenced object. This synchronizes
|
577
|
+
# an asynchronous call by using a Queue to synchronize the DRb
|
578
|
+
# event thread with the calling thread, so use of this mechanism,
|
579
|
+
# to make method calls within an event loop will thus result in a
|
580
|
+
# threading deadlock! Use the send_async method if you want to
|
581
|
+
# use EMDRb from within an event loop.
|
582
|
+
def method_missing(msg_id, *a, &b)
|
583
|
+
if DRb.here?(@uri)
|
584
|
+
obj = DRb.to_obj(@ref)
|
585
|
+
DRb.current_server.check_insecure_method(obj, msg_id)
|
586
|
+
return obj.__send__(msg_id, *a, &b)
|
587
|
+
end
|
588
|
+
|
589
|
+
q = Queue.new
|
590
|
+
EventMachine::next_tick do
|
591
|
+
df = self.send_async(msg_id, *a, &b)
|
592
|
+
df.callback { |data| q << data }
|
593
|
+
end
|
594
|
+
succ, result = q.shift
|
595
|
+
if succ
|
596
|
+
return result
|
597
|
+
elsif DRbUnknown === result
|
598
|
+
raise result
|
599
|
+
else
|
600
|
+
bt = self.class.prepare_backtrace(@uri, result)
|
601
|
+
result.set_backtrace(bt + caller)
|
602
|
+
raise result
|
603
|
+
end
|
604
|
+
end
|
605
|
+
|
546
606
|
end
|
547
607
|
|
548
608
|
end
|
data/lib/emdrb/version.rb
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
# Homepage:: http://emdrb.rubyforge.org/
|
5
5
|
# License:: GNU Lesser General Public License / Ruby License
|
6
6
|
#
|
7
|
-
# $Id: version.rb
|
7
|
+
# $Id: version.rb 57 2009-01-23 09:07:54Z dido $
|
8
8
|
#
|
9
9
|
#----------------------------------------------------------------------------
|
10
10
|
#
|
@@ -25,8 +25,8 @@ module EMDRb
|
|
25
25
|
module Version
|
26
26
|
|
27
27
|
MAJOR = 0
|
28
|
-
MINOR =
|
29
|
-
TINY =
|
28
|
+
MINOR = 2
|
29
|
+
TINY = 0
|
30
30
|
|
31
31
|
# The version of EMDRb in use.
|
32
32
|
STRING = [ MAJOR, MINOR, TINY ].join(".")
|
data/spec/client_spec.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Rafael R. Sevilla (mailto:dido@imperium.ph)
|
3
|
+
# Copyright:: Copyright © 2008, 2009 Rafael R. Sevilla
|
4
|
+
# Homepage:: http://emdrb.rubyforge.org/
|
5
|
+
# License:: GNU General Public License / Ruby License
|
6
|
+
#
|
7
|
+
# $Id: client_spec.rb 50 2009-01-23 08:52:21Z dido $
|
8
|
+
#
|
9
|
+
#----------------------------------------------------------------------------
|
10
|
+
#
|
11
|
+
# Copyright © 2008, 2009 Rafael Sevilla
|
12
|
+
# This file is part of EMDRb
|
13
|
+
#
|
14
|
+
# This program is free software; you can redistribute it and/or modify
|
15
|
+
# it under the terms of either: 1) the GNU General Public License
|
16
|
+
# as published by the Free Software Foundation; either version 2 of the
|
17
|
+
# License, or (at your option) any later version; or 2) Ruby's License.
|
18
|
+
#
|
19
|
+
# See the file COPYING for complete licensing information.
|
20
|
+
#----------------------------------------------------------------------------
|
21
|
+
#
|
22
|
+
require File.join(File.dirname(__FILE__), %w[spec_helper])
|
23
|
+
require File.join(File.dirname(__FILE__), %w[spec_common])
|
24
|
+
|
25
|
+
Thread.abort_on_exception = true
|
26
|
+
|
27
|
+
describe EMDRb, "Client" do
|
28
|
+
it_should_behave_like "DRb basics"
|
29
|
+
|
30
|
+
before(:all) do
|
31
|
+
system(File.join(File.dirname(__FILE__), "drbserver.rb drb"))
|
32
|
+
DRb.start_service
|
33
|
+
@obj = DRb::DRbObject.new(nil, "druby://localhost:12345")
|
34
|
+
end
|
35
|
+
|
36
|
+
after(:all) do
|
37
|
+
pid = File.open(File.join(File.dirname(__FILE__), "drbserver.pid")) { |fp| fp.read.to_i }
|
38
|
+
Process.kill("SIGTERM", pid)
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should be able to perform asynchronous method calls" do
|
42
|
+
EventMachine::next_tick do
|
43
|
+
@obj.send_async(:identity, 1).callback do |data|
|
44
|
+
data[0].should be_true
|
45
|
+
data[1].should == 1
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should be able to perform asynchronous method calls with a passed block" do
|
51
|
+
EventMachine::next_tick do
|
52
|
+
val = 1
|
53
|
+
df = @obj.send_async(:blockyield, 1,2,3,4,5,6,7) { |x| val *= x; val }
|
54
|
+
df.callback do |data|
|
55
|
+
data[0].should be_true
|
56
|
+
val.should == 5040
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
data/spec/drbserver.rb
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Author:: Rafael R. Sevilla (mailto:dido@imperium.ph)
|
3
|
+
# Copyright:: Copyright © 2008, 2009 Rafael R. Sevilla
|
4
|
+
# Homepage:: http://emdrb.rubyforge.org/
|
5
|
+
# License:: GNU General Public License / Ruby License
|
6
|
+
#
|
7
|
+
# $Id: drbserver.rb 46 2009-01-23 08:10:42Z dido $
|
8
|
+
#
|
9
|
+
#----------------------------------------------------------------------------
|
10
|
+
#
|
11
|
+
# Copyright © 2008, 2009 Rafael Sevilla
|
12
|
+
# This file is part of EMDRb
|
13
|
+
#
|
14
|
+
# This program is free software; you can redistribute it and/or modify
|
15
|
+
# it under the terms of either: 1) the GNU General Public License
|
16
|
+
# as published by the Free Software Foundation; either version 2 of the
|
17
|
+
# License, or (at your option) any later version; or 2) Ruby's License.
|
18
|
+
#
|
19
|
+
# See the file COPYING for complete licensing information.
|
20
|
+
#----------------------------------------------------------------------------
|
21
|
+
#
|
22
|
+
# This is the DRb server that should be run by the specs, and can execute
|
23
|
+
# using either the standard DRb or EMDRb depending on what is being tested.
|
24
|
+
#
|
25
|
+
require 'daemons'
|
26
|
+
Thread.abort_on_exception = true
|
27
|
+
if ARGV[0] == "emdrb"
|
28
|
+
$LOAD_PATH << File.join(File.dirname(__FILE__), '../lib/')
|
29
|
+
require 'emdrb'
|
30
|
+
elsif ARGV[0] == "drb"
|
31
|
+
require 'drb'
|
32
|
+
else
|
33
|
+
raise "specify emdrb or drb on the command line"
|
34
|
+
end
|
35
|
+
|
36
|
+
if ARGV[1].nil?
|
37
|
+
pidfile = File.expand_path(File.join(File.dirname(__FILE__), "drbserver.pid"))
|
38
|
+
if File.exist?(pidfile)
|
39
|
+
exit(0)
|
40
|
+
end
|
41
|
+
# logfile = File.expand_path(File.join(File.dirname(__FILE__), "drbserver.log"))
|
42
|
+
Daemonize.daemonize
|
43
|
+
pid = Process.pid
|
44
|
+
File.open(pidfile, "w") { |fp| fp.write(pid.to_s) }
|
45
|
+
|
46
|
+
handler = lambda do
|
47
|
+
File.delete(pidfile)
|
48
|
+
exit(0)
|
49
|
+
end
|
50
|
+
|
51
|
+
trap("SIGTERM", handler)
|
52
|
+
trap("SIGINT", handler)
|
53
|
+
end
|
54
|
+
|
55
|
+
class TestServer
|
56
|
+
def identity(x)
|
57
|
+
return(x)
|
58
|
+
end
|
59
|
+
|
60
|
+
def addtwo(x, y)
|
61
|
+
return(x+y)
|
62
|
+
end
|
63
|
+
|
64
|
+
def sum(*vals)
|
65
|
+
return(vals.inject(0) { |x,y| x + y })
|
66
|
+
end
|
67
|
+
|
68
|
+
def blockyield(*vals)
|
69
|
+
vals.each do |x|
|
70
|
+
yield x
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
|
77
|
+
DRb.start_service("druby://:12345", TestServer.new)
|
78
|
+
DRb.thread.join
|
data/spec/server_spec.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Rafael R. Sevilla (mailto:dido@imperium.ph)
|
3
|
+
# Copyright:: Copyright © 2008, 2009 Rafael R. Sevilla
|
4
|
+
# Homepage:: http://emdrb.rubyforge.org/
|
5
|
+
# License:: GNU General Public License / Ruby License
|
6
|
+
#
|
7
|
+
# $Id: server_spec.rb 48 2009-01-23 08:48:43Z dido $
|
8
|
+
#
|
9
|
+
#----------------------------------------------------------------------------
|
10
|
+
#
|
11
|
+
# Copyright © 2008, 2009 Rafael Sevilla
|
12
|
+
# This file is part of EMDRb
|
13
|
+
#
|
14
|
+
# This program is free software; you can redistribute it and/or modify
|
15
|
+
# it under the terms of either: 1) the GNU General Public License
|
16
|
+
# as published by the Free Software Foundation; either version 2 of the
|
17
|
+
# License, or (at your option) any later version; or 2) Ruby's License.
|
18
|
+
#
|
19
|
+
# See the file COPYING for complete licensing information.
|
20
|
+
#----------------------------------------------------------------------------
|
21
|
+
#
|
22
|
+
# This tests the EMDRb server implementation against the standard DRb
|
23
|
+
# client.
|
24
|
+
#
|
25
|
+
#require File.join(File.dirname(__FILE__), %w[spec_helper])
|
26
|
+
require File.join(File.dirname(__FILE__), %w[spec_common])
|
27
|
+
require 'drb' # yes, that's right, we use the STANDARD DRb here!
|
28
|
+
require 'thread'
|
29
|
+
|
30
|
+
Thread.abort_on_exception = true
|
31
|
+
|
32
|
+
describe "EMDRb Server" do
|
33
|
+
it_should_behave_like "DRb basics"
|
34
|
+
|
35
|
+
before(:all) do
|
36
|
+
# but we start the *server* with EMDRb
|
37
|
+
system(File.join(File.dirname(__FILE__), "drbserver.rb emdrb"))
|
38
|
+
DRb.start_service
|
39
|
+
@obj = DRbObject.new_with_uri("druby://localhost:12345")
|
40
|
+
end
|
41
|
+
|
42
|
+
after(:all) do
|
43
|
+
pid = File.open(File.join(File.dirname(__FILE__), "drbserver.pid")) { |fp| fp.read.to_i }
|
44
|
+
Process.kill("SIGTERM", pid)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should work with variadic methods" do
|
48
|
+
@obj.sum(1,2,3,4,5).should == 15
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
data/spec/spec_common.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Rafael R. Sevilla (mailto:dido@imperium.ph)
|
3
|
+
# Copyright:: Copyright © 2008, 2009 Rafael R. Sevilla
|
4
|
+
# Homepage:: http://emdrb.rubyforge.org/
|
5
|
+
# License:: GNU General Public License / Ruby License
|
6
|
+
#
|
7
|
+
# $Id: spec_common.rb 44 2009-01-23 06:40:54Z dido $
|
8
|
+
#
|
9
|
+
#----------------------------------------------------------------------------
|
10
|
+
#
|
11
|
+
# Copyright © 2008, 2009 Rafael Sevilla
|
12
|
+
# This file is part of EMDRb
|
13
|
+
#
|
14
|
+
# This program is free software; you can redistribute it and/or modify
|
15
|
+
# it under the terms of either: 1) the GNU General Public License
|
16
|
+
# as published by the Free Software Foundation; either version 2 of the
|
17
|
+
# License, or (at your option) any later version; or 2) Ruby's License.
|
18
|
+
#
|
19
|
+
# See the file COPYING for complete licensing information.
|
20
|
+
#----------------------------------------------------------------------------
|
21
|
+
#
|
22
|
+
describe "DRb basics", :shared => true do
|
23
|
+
it "should be able to perform simple synchronous method calls" do
|
24
|
+
@obj.identity(1).should == 1
|
25
|
+
@obj.addtwo(1, 2).should == 3
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should be able to perform synchronous method calls with a block" do
|
29
|
+
val = 1
|
30
|
+
@obj.blockyield(1,2,3,4,5,6,7) { |x| val *= x }
|
31
|
+
val.should == 5040
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Rafael R. Sevilla (mailto:dido@imperium.ph)
|
3
|
+
# Copyright:: Copyright © 2008, 2009 Rafael R. Sevilla
|
4
|
+
# Homepage:: http://emdrb.rubyforge.org/
|
5
|
+
# License:: GNU General Public License / Ruby License
|
6
|
+
#
|
7
|
+
# $Id: spec_helper.rb 60 2009-01-23 09:11:11Z dido $
|
8
|
+
#
|
9
|
+
#----------------------------------------------------------------------------
|
10
|
+
#
|
11
|
+
# Copyright © 2008, 2009 Rafael Sevilla
|
12
|
+
# This file is part of EMDRb
|
13
|
+
#
|
14
|
+
# This program is free software; you can redistribute it and/or modify
|
15
|
+
# it under the terms of either: 1) the GNU General Public License
|
16
|
+
# as published by the Free Software Foundation; either version 2 of the
|
17
|
+
# License, or (at your option) any later version; or 2) Ruby's License.
|
18
|
+
#
|
19
|
+
# See the file COPYING for complete licensing information.
|
20
|
+
#----------------------------------------------------------------------------
|
21
|
+
#
|
22
|
+
require File.expand_path(
|
23
|
+
File.join(File.dirname(__FILE__), %w[.. lib emdrb]))
|
24
|
+
|
25
|
+
Spec::Runner.configure do |config|
|
26
|
+
# == Mock Framework
|
27
|
+
#
|
28
|
+
# RSpec uses it's own mocking framework by default. If you prefer to
|
29
|
+
# use mocha, flexmock or RR, uncomment the appropriate line:
|
30
|
+
#
|
31
|
+
# config.mock_with :mocha
|
32
|
+
# config.mock_with :flexmock
|
33
|
+
# config.mock_with :rr
|
34
|
+
end
|
35
|
+
|
36
|
+
# EOF
|
data/tasks/ann.rake
CHANGED
data/tasks/bones.rake
CHANGED
data/tasks/gem.rake
CHANGED
data/tasks/git.rake
CHANGED
data/tasks/manifest.rake
CHANGED
data/tasks/notes.rake
CHANGED
data/tasks/post_load.rake
CHANGED
data/tasks/rdoc.rake
CHANGED
data/tasks/setup.rb
CHANGED
data/tasks/spec.rake
CHANGED
data/tasks/svn.rake
CHANGED
data/tasks/test.rake
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: emdrb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- dido@imperium.ph
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-01-
|
12
|
+
date: 2009-01-23 00:00:00 +08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -32,6 +32,11 @@ files:
|
|
32
32
|
- lib/emdrb.rb
|
33
33
|
- lib/emdrb/emdrb.rb
|
34
34
|
- lib/emdrb/version.rb
|
35
|
+
- spec/client_spec.rb
|
36
|
+
- spec/drbserver.rb
|
37
|
+
- spec/server_spec.rb
|
38
|
+
- spec/spec_common.rb
|
39
|
+
- spec/spec_helper.rb
|
35
40
|
- tasks/ann.rake
|
36
41
|
- tasks/bones.rake
|
37
42
|
- tasks/gem.rake
|
@@ -45,7 +50,6 @@ files:
|
|
45
50
|
- tasks/spec.rake
|
46
51
|
- tasks/svn.rake
|
47
52
|
- tasks/test.rake
|
48
|
-
- test/test_emdrb.rb
|
49
53
|
has_rdoc: true
|
50
54
|
homepage: http://emdrb.rubyforge.org
|
51
55
|
post_install_message:
|
@@ -73,5 +77,5 @@ rubygems_version: 1.2.0
|
|
73
77
|
signing_key:
|
74
78
|
specification_version: 2
|
75
79
|
summary: This is a distributed Ruby client and server which should work as a drop-in replacement for the standard distributed Ruby implementation available in the Ruby standard library
|
76
|
-
test_files:
|
77
|
-
|
80
|
+
test_files: []
|
81
|
+
|
data/test/test_emdrb.rb
DELETED
@@ -1,96 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# Author:: Rafael R. Sevilla (mailto:dido@imperium.ph)
|
3
|
-
# Copyright:: Copyright (c) 2008 Rafael R. Sevilla
|
4
|
-
# Homepage:: http://emdrb.rubyforge.org/
|
5
|
-
# License:: GNU General Public License / Ruby License
|
6
|
-
#
|
7
|
-
# $Id: test_emdrb.rb 27 2009-01-22 05:11:56Z dido $
|
8
|
-
#
|
9
|
-
#----------------------------------------------------------------------------
|
10
|
-
#
|
11
|
-
# Copyright (C) 2008 Rafael Sevilla
|
12
|
-
# This file is part of EMDRb
|
13
|
-
#
|
14
|
-
# This program is free software; you can redistribute it and/or modify
|
15
|
-
# it under the terms of either: 1) the GNU General Public License
|
16
|
-
# as published by the Free Software Foundation; either version 2 of the
|
17
|
-
# License, or (at your option) any later version; or 2) Ruby's License.
|
18
|
-
#
|
19
|
-
# See the file COPYING for complete licensing information.
|
20
|
-
#----------------------------------------------------------------------------
|
21
|
-
#
|
22
|
-
require 'test/unit'
|
23
|
-
require 'emdrb/emdrb'
|
24
|
-
require 'drb'
|
25
|
-
|
26
|
-
Thread.abort_on_exception = true
|
27
|
-
|
28
|
-
class TestServer
|
29
|
-
def identity(x)
|
30
|
-
return(x)
|
31
|
-
end
|
32
|
-
|
33
|
-
def addtwo(x, y)
|
34
|
-
return(x+y)
|
35
|
-
end
|
36
|
-
|
37
|
-
def sum(*vals)
|
38
|
-
return(vals.inject(0) { |x,y| x + y })
|
39
|
-
end
|
40
|
-
|
41
|
-
def blockyield(*vals)
|
42
|
-
vals.each do |x|
|
43
|
-
yield x
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
class EMDRbTest < Test::Unit::TestCase
|
49
|
-
def setup
|
50
|
-
EMDRb.start_service("druby://:12345", TestServer.new)
|
51
|
-
end
|
52
|
-
|
53
|
-
def teardown
|
54
|
-
EMDRb.thread.kill
|
55
|
-
end
|
56
|
-
|
57
|
-
def test_server
|
58
|
-
o = DRbObject.new_with_uri("druby://localhost:12345")
|
59
|
-
DRb.start_service
|
60
|
-
assert_equal(1, o.identity(1))
|
61
|
-
assert_equal(3, o.addtwo(1, 2))
|
62
|
-
assert_raises(ArgumentError) do
|
63
|
-
o.addtwo(1)
|
64
|
-
end
|
65
|
-
assert_equal(15, o.sum(1,2,3,4,5))
|
66
|
-
val = 1
|
67
|
-
o.blockyield(1,2,3,4,5,6,7) { |x| val *= x }
|
68
|
-
assert_equal(5040, val)
|
69
|
-
end
|
70
|
-
|
71
|
-
def test_client
|
72
|
-
o = EMDRb::DRbObject.new(nil, "druby://localhost:12345")
|
73
|
-
q = Queue.new
|
74
|
-
EventMachine::next_tick do
|
75
|
-
o.send_async(:identity, 1).callback do |data|
|
76
|
-
assert(data[0])
|
77
|
-
assert_equal(1, data[1])
|
78
|
-
q << data
|
79
|
-
end
|
80
|
-
end
|
81
|
-
q.shift
|
82
|
-
|
83
|
-
# EventMachine::next_tick do
|
84
|
-
# val = 1
|
85
|
-
# df = o.send_async(:blockyield, 1,2,3,4,5,6,7) { |x| val *= x; val }
|
86
|
-
# df.callback do |data|
|
87
|
-
# assert(data[0])
|
88
|
-
# assert_equal(5040, data[1])
|
89
|
-
# q << data
|
90
|
-
# end
|
91
|
-
# end
|
92
|
-
# q.shift
|
93
|
-
|
94
|
-
end
|
95
|
-
|
96
|
-
end
|