emdrb 0.4.0 → 0.4.1

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 CHANGED
@@ -1,3 +1,6 @@
1
+ == 0.4.1 / 2009-04-21
2
+ * Bug in calling deferrable methods from a local object now fixed
3
+
1
4
  == 0.4.0 / 2009-03-18
2
5
  * Mechanism for deferrable methods using blocks cleaned up further
3
6
  * Asynchronous method call API cleaned up
data/README.txt CHANGED
@@ -33,8 +33,6 @@ It is, however, not yet a complete replacement for the standard DRb:
33
33
  * No SSL support. To support this fully, EventMachine needs to have
34
34
  more comprehensive SSL/TLS support.
35
35
  * RSpec tests are very basic, and need a lot more comprehensive work.
36
- They also don't work for some reason when run under Rake, but work
37
- just fine when run manually.
38
36
  * Many standard configuration options for DRb still unsupported
39
37
 
40
38
  These and many other problems are scheduled to be addressed in the
@@ -108,5 +106,5 @@ Copyright © 2008, 2009 Rafael R. Sevilla. You can redistribute it
108
106
  and/or modify it under the same terms as Ruby. Please see the file
109
107
  COPYING for more details.
110
108
 
111
- $Id: README.txt 104 2009-03-18 04:45:56Z dido $
109
+ $Id: README.txt 125 2009-03-19 07:39:16Z dido $
112
110
 
data/Rakefile CHANGED
@@ -5,7 +5,7 @@
5
5
  # Homepage:: http://emdrb.rubyforge.org/
6
6
  # License:: GNU General Public License / Ruby License
7
7
  #
8
- # $Id: Rakefile 94 2009-03-14 07:17:37Z dido $
8
+ # $Id: Rakefile 126 2009-03-19 08:19:17Z dido $
9
9
  #
10
10
  #----------------------------------------------------------------------------
11
11
  #
@@ -46,4 +46,18 @@ depend_on "eventmachine"
46
46
 
47
47
  PROJ.spec.opts << '--color'
48
48
 
49
+ namespace :spec do
50
+ task :run do
51
+ type = ENV["TYPE"]
52
+ unless type == "drb"
53
+ type = "emdrb"
54
+ end
55
+ trap("SIGCHLD", "IGNORE")
56
+ pid = fork
57
+ if pid.nil?
58
+ exec("ruby -Ilib examples/drbserver.rb #{type}")
59
+ end
60
+ end
61
+ end
62
+
49
63
  # EOF
@@ -5,7 +5,7 @@
5
5
  # Homepage:: http://emdrb.rubyforge.org/
6
6
  # License:: GNU General Public License / Ruby License
7
7
  #
8
- # $Id: drbserver.rb 106 2009-03-18 05:48:53Z dido $
8
+ # $Id: drbserver.rb 132 2009-04-21 03:25:00Z dido $
9
9
  #
10
10
  #----------------------------------------------------------------------------
11
11
  #
@@ -52,22 +52,29 @@ class TestServer
52
52
  yield x
53
53
  end
54
54
  end
55
+
56
+ def raise_exception
57
+ raise "This error should be expected"
58
+ end
55
59
  end
56
60
 
57
61
  if ARGV[0] == "emdrb"
58
62
  class TestServer
59
63
  include DRb::DRbEMSafe
60
- include EventMachine::Deferrable
61
64
 
62
65
  deferrable_method :block_df
63
66
 
64
67
  ##
65
68
  # Simple example of a deferrable method structured as a state
66
- # machine.
67
- def block_df(data, state={:index => 0, :retval => 0 }, &block)
69
+ # machine. This method sums values of the data array as they
70
+ # are returned by the caller. The similarity of this function
71
+ # to a tail-recursive, continuation-passing style version of
72
+ # the same should be obvious...
73
+ def block_df(data, state={:index => 0, :retval => 0, :df => nil}, &block)
74
+ state[:df] ||= EventMachine::DefaultDeferrable.new
68
75
  if state[:index] >= data.length
69
- self.set_deferred_status(:succeeded, state[:retval])
70
- return(self)
76
+ state[:df].set_deferred_status(:succeeded, state[:retval])
77
+ return(state[:df])
71
78
  end
72
79
 
73
80
  df = yield data[state[:index]]
@@ -77,13 +84,22 @@ if ARGV[0] == "emdrb"
77
84
  self.block_df(data, state, &block)
78
85
  end
79
86
  df.errback do |res|
80
- df.fail(res)
87
+ state[:df].fail(res)
81
88
  end
82
- return(self)
89
+ return(state[:df])
83
90
  end
84
91
  end
92
+ else
93
+ class TestServer
94
+ # This is a fake implementation of block_df to be used by the standard
95
+ # DRb so that the same tests will run against either.
96
+ def block_df(vals, &block)
97
+ return(vals.inject(0) { |x,y| x + block.call(y) })
98
+ end
99
+
100
+ end
85
101
  end
86
102
 
87
103
 
88
- DRb.start_service("druby://:12345", TestServer.new)
104
+ DRb.start_service("druby://127.0.0.1:12345", TestServer.new)
89
105
  DRb.thread.join
data/lib/emdrb/emdrb.rb CHANGED
@@ -5,7 +5,7 @@
5
5
  # Homepage:: http://emdrb.rubyforge.org/
6
6
  # License:: GNU General Public License / Ruby License
7
7
  #
8
- # $Id: emdrb.rb 107 2009-03-18 05:52:00Z dido $
8
+ # $Id: emdrb.rb 129 2009-04-21 03:21:07Z dido $
9
9
  #
10
10
  #----------------------------------------------------------------------------
11
11
  #
@@ -47,9 +47,9 @@ module DRb
47
47
  # 2. Exceptions must be caught and the Deferrable they return must
48
48
  # fail, with the exception object passed as a parameter to its
49
49
  # errbacks.
50
- # 3. Blocks passed to the deferrable method will always return a
51
- # Deferrable, which again will succeed
52
- #
50
+ # 3. Blocks passed to the deferrable method should always return a
51
+ # Deferrable, which again should succeed when the value of the
52
+ # block becomes available.
53
53
  #
54
54
  module DRbEMSafe
55
55
  module ClassMethods
@@ -644,10 +644,10 @@ module DRb
644
644
  end
645
645
 
646
646
  ##
647
- # Class representing a drb server instance. This subclasses DRb::DRbServer
648
- # for brevity. DRbServer instances are normally created indirectly using
649
- # either EMDRb.start service (which emulates DRb.start_service) or via
650
- # EMDRb.start_drbserver (designed to be called from within an event loop).
647
+ # Class representing a drb server instance. DRbServer instances are
648
+ # normally created indirectly using either DRb.start_service or
649
+ # EMDRb.start_drbserver (designed to be called from within an event
650
+ # loop).
651
651
  class DRbServer
652
652
  def initialize(uri=nil, front=nil, config_or_acl=nil)
653
653
  if Hash === config_or_acl
@@ -713,21 +713,33 @@ module DRb
713
713
  end
714
714
  module_function :start_drbserver
715
715
 
716
+ ##
717
+ # Stop all servers.
718
+ def stop_all_servers
719
+ @server.each do |uri,srv|
720
+ srv.stop_service
721
+ end
722
+ end
723
+ module_function :stop_all_servers
724
+
716
725
  def start_evloop
717
726
  unless EventMachine::reactor_running?
727
+ q = Queue.new
718
728
  @eventloop = Thread.new do
719
729
  begin
720
730
  EventMachine::run do
721
731
  # Start an empty event loop. The DRb server(s) will be started
722
- # by EM#next_tick calls.
732
+ # by EM#next_tick calls. Just put a dummy value into the queue
733
+ # so that the calling thread will resume execution once this
734
+ # event thread actually starts the loop.
735
+ q << 1
723
736
  end
724
737
  ensure
725
738
  # close all servers if the event loop ends for whatever reason
726
- @server.each do |uri,srv|
727
- srv.stop_service
728
- end
739
+ self.stop_all_servers
729
740
  end
730
741
  end
742
+ q.shift
731
743
  end
732
744
  end
733
745
  module_function :start_evloop
@@ -833,10 +845,17 @@ module DRb
833
845
  if DRb.here?(@uri)
834
846
  obj = DRb.to_obj(@ref)
835
847
  DRb.current_server.check_insecure_method(obj, msg_id)
836
- begin
837
- df.succeed(obj.__send__(msg_id, *a, &b))
838
- rescue
839
- df.fail($!)
848
+ if obj.kind_of?(DRbEMSafe) && obj.class.deferrable_method?(msg_id)
849
+ # If the method is a deferrable, calling the method will itself
850
+ # return a deferrable by definition, and we should be using this
851
+ # deferrable to determine whether the call succeeded or failed.
852
+ df = obj.__send__(msg_id, *a, &b)
853
+ else
854
+ begin
855
+ df.succeed(obj.__send__(msg_id, *a, &b))
856
+ rescue
857
+ df.fail($!)
858
+ end
840
859
  end
841
860
  return(df)
842
861
  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 110 2009-03-18 05:55:43Z dido $
7
+ # $Id: version.rb 130 2009-04-21 03:21:53Z dido $
8
8
  #
9
9
  #----------------------------------------------------------------------------
10
10
  #
@@ -22,5 +22,5 @@
22
22
  # EMDRb version code
23
23
  #
24
24
  module EMDRb
25
- VERSION = "0.4.0"
25
+ VERSION = "0.4.1"
26
26
  end
@@ -0,0 +1,116 @@
1
+ # -*- coding: utf-8 -*-
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: emdrb_spec.rb 128 2009-04-21 03:15:04Z 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
+ #----------------------------------------------------------------------------
22
+ #
23
+
24
+ require File.join(File.dirname(__FILE__), %w[spec_helper])
25
+ require 'thread'
26
+
27
+ class LocalDeferrable
28
+ include DRb::DRbEMSafe
29
+
30
+ def df_tester(val)
31
+ df = EventMachine::DefaultDeferrable.new
32
+ df.succeed(val+1)
33
+ return(df)
34
+ end
35
+
36
+ deferrable_method :df_tester
37
+ end
38
+
39
+ describe EMDRb do
40
+ before do
41
+ DRb.start_service("druby://localhost:56789", LocalDeferrable.new)
42
+ @obj = DRbObject.new_with_uri("druby://localhost:12345")
43
+ @obj2 = DRbObject.new_with_uri("druby://localhost:56789")
44
+ end
45
+
46
+ after do
47
+ DRb.stop_service
48
+ end
49
+
50
+ it "should be able to perform simple synchronous method calls" do
51
+ @obj.identity(1).should == 1
52
+ @obj.addtwo(1, 2).should == 3
53
+ end
54
+
55
+ it "should be able to perform synchronous method calls with a block" do
56
+ val = 1
57
+ @obj.blockyield(1,2,3,4,5,6,7) { |x| val *= x }
58
+ val.should == 5040
59
+ end
60
+
61
+ it "should propagate exceptions to the client" do
62
+ lambda do
63
+ @obj.raise_exception
64
+ end.should raise_error(RuntimeError) do |error|
65
+ error.message.should == "This error should be expected"
66
+ end
67
+ end
68
+
69
+ it "should be able to perform asynchronous method calls" do
70
+ q = Queue.new
71
+ EventMachine::next_tick do
72
+ @obj.send_async(:identity, 1).callback do |data|
73
+ q << data
74
+ end
75
+ end
76
+ data = q.shift
77
+ data.should == 1
78
+ end
79
+
80
+ it "should be able to perform asynchronous method calls with a passed block" do
81
+ q = Queue.new
82
+ val = 1
83
+ EventMachine::next_tick do
84
+ df = @obj.send_async(:blockyield, 1,2,3,4,5,6,7) { |x| val *= x; val }
85
+ df.callback do |data|
86
+ q << data
87
+ end
88
+ end
89
+ data = q.shift
90
+ data[0].should be_true
91
+ val.should == 5040
92
+ end
93
+
94
+ it "should work with variadic methods" do
95
+ @obj.sum(1,2,3,4,5).should == 15
96
+ end
97
+
98
+ it "should use deferrable methods correctly" do
99
+ res = @obj.block_df([1,2,3,4,5]) { |x| x }
100
+ res.should == 15
101
+ end
102
+
103
+ it "should propagate exceptions raised by a block in a deferrable method" do
104
+ lambda do
105
+ res = @obj.block_df([1,2,3,4,5]) { |x| raise "an error" }
106
+ end.should raise_error(RuntimeError) do |error|
107
+ error.message.should == "an error"
108
+ end
109
+ end
110
+
111
+ it "should call local deferrables correctly" do
112
+ @obj2.df_tester(1).should == 2
113
+ end
114
+ end
115
+
116
+ # EOF
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.0
4
+ version: 0.4.1
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-03-18 00:00:00 +08:00
12
+ date: 2009-04-21 00:00:00 +08:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -20,7 +20,7 @@ dependencies:
20
20
  requirements:
21
21
  - - ">="
22
22
  - !ruby/object:Gem::Version
23
- version: 0.12.2
23
+ version: 0.12.6
24
24
  version:
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: bones
@@ -47,14 +47,12 @@ files:
47
47
  - LEGAL
48
48
  - README.txt
49
49
  - Rakefile
50
+ - examples/drbserver.rb
50
51
  - lib/emdrb.rb
51
52
  - lib/emdrb/emdrb.rb
52
53
  - lib/emdrb/unix.rb
53
54
  - lib/emdrb/version.rb
54
- - spec/client_spec.rb
55
- - spec/drbserver.rb
56
- - spec/server_spec.rb
57
- - spec/spec_common.rb
55
+ - spec/emdrb_spec.rb
58
56
  - spec/spec_helper.rb
59
57
  - tasks/ann.rake
60
58
  - tasks/bones.rake
data/spec/client_spec.rb DELETED
@@ -1,66 +0,0 @@
1
- # -*- coding: utf-8 -*-
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: client_spec.rb 105 2009-03-18 05:48:08Z 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
- #----------------------------------------------------------------------------
22
- #
23
- require File.join(File.dirname(__FILE__), %w[spec_helper])
24
- require File.join(File.dirname(__FILE__), %w[spec_common])
25
- require 'thread'
26
-
27
- Thread.abort_on_exception = true
28
-
29
- describe EMDRb, "Client" do
30
- it_should_behave_like "DRb basics"
31
-
32
- before do
33
- DRb.start_service
34
- @obj = DRb::DRbObject.new(nil, "druby://localhost:12345")
35
- end
36
-
37
- after do
38
- DRb.stop_service
39
- end
40
-
41
- it "should be able to perform asynchronous method calls" do
42
- q = Queue.new
43
- EventMachine::next_tick do
44
- @obj.send_async(:identity, 1).callback do |data|
45
- q << data
46
- end
47
- end
48
- data = q.shift
49
- data.should == 1
50
- end
51
-
52
- it "should be able to perform asynchronous method calls with a passed block" do
53
- q = Queue.new
54
- val = 1
55
- EventMachine::next_tick do
56
- df = @obj.send_async(:blockyield, 1,2,3,4,5,6,7) { |x| val *= x; val }
57
- df.callback do |data|
58
- q << data
59
- end
60
- end
61
- data = q.shift
62
- data[0].should be_true
63
- val.should == 5040
64
- end
65
-
66
- end
data/spec/server_spec.rb DELETED
@@ -1,54 +0,0 @@
1
- # -*- coding: utf-8 -*-
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: server_spec.rb 108 2009-03-18 05:53:00Z 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
- #----------------------------------------------------------------------------
22
- #
23
- # This tests the EMDRb server implementation against the standard DRb
24
- # client.
25
- #
26
- #require File.join(File.dirname(__FILE__), %w[spec_helper])
27
- require File.join(File.dirname(__FILE__), %w[spec_common])
28
- require 'drb' # yes, that's right, we use the STANDARD DRb here!
29
- require 'thread'
30
-
31
- Thread.abort_on_exception = true
32
-
33
- describe "EMDRb Server" do
34
- it_should_behave_like "DRb basics"
35
-
36
- before(:all) do
37
- DRb.start_service
38
- @obj = DRbObject.new_with_uri("druby://localhost:12345")
39
- end
40
-
41
- after(:all) do
42
- DRb.stop_service
43
- end
44
-
45
- it "should work with variadic methods" do
46
- @obj.sum(1,2,3,4,5).should == 15
47
- end
48
-
49
- it "should use deferrable methods correctly" do
50
- res = @obj.block_df([1,2,3,4,5]) { |x| x }
51
- res.should == 15
52
- end
53
-
54
- end
data/spec/spec_common.rb DELETED
@@ -1,34 +0,0 @@
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