rexec 1.2.6 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -4,8 +4,61 @@
4
4
  # This class is as small and independant as possible as it will get sent to clients for execution.
5
5
 
6
6
  require 'thread'
7
+ require 'monitor'
7
8
 
8
9
  module RExec
10
+
11
+ # A wrapper for sending method invocations over a Connection
12
+ class Invocation
13
+ def initialize(name, arguments)
14
+ @name = name
15
+ @arguments = arguments
16
+ end
17
+
18
+ def apply(object)
19
+ object.send(@name, *@arguments)
20
+ end
21
+
22
+ class Result
23
+ def initialize(value)
24
+ @value = value
25
+ end
26
+
27
+ attr :value
28
+ end
29
+ end
30
+
31
+ # A proxy class to create and send Invocation objects via a Connection, and receive a result.
32
+ class Proxy
33
+ def initialize(connection)
34
+ @connection = connection
35
+
36
+ @method_mutex = Mutex.new
37
+ end
38
+
39
+ def method_missing(name, *arguments)
40
+ invocation = Invocation.new(name, arguments)
41
+ result = nil
42
+
43
+ # Connection provides no transaction support. This means that
44
+ # if multiple threads are sending and receiving arbirary objects
45
+ # via the connection, the Proxy object may fail due to out of
46
+ # line objects.
47
+ @method_mutex.synchronize do
48
+ # Send the invocation.
49
+ @connection.send_object(invocation)
50
+
51
+ # Wait for the result.
52
+ result = @connection.receive_object
53
+ end
54
+
55
+ if Invocation::Result === result
56
+ return result.value
57
+ else
58
+ raise InvalidResponse.new("Invalid response received: #{result}")
59
+ end
60
+ end
61
+ end
9
62
 
10
63
  # This class represents an abstract connection to another ruby process. The interface does not impose
11
64
  # any structure on the way this communication link works, except for the fact you can send and receive
@@ -44,8 +97,17 @@ module RExec
44
97
 
45
98
  @receive_mutex = Mutex.new
46
99
  @send_mutex = Mutex.new
100
+
101
+ @proxy = Proxy.new(self)
102
+ @handler = nil
47
103
  end
48
104
 
105
+ # The object that will handle remote proxy invocations.
106
+ attr :handler, true
107
+
108
+ # The proxy object that will dispatch RPCs.
109
+ attr :proxy
110
+
49
111
  # The pipe used for reading data
50
112
  def input
51
113
  @input
@@ -89,7 +151,12 @@ module RExec
89
151
  end
90
152
 
91
153
  begin
92
- yield object
154
+ if @handler && Invocation === object
155
+ result = object.apply(@handler)
156
+ send_object(Invocation::Result.new(result))
157
+ else
158
+ yield object
159
+ end
93
160
  rescue Exception => ex
94
161
  send_object(ex)
95
162
  end
@@ -21,8 +21,8 @@
21
21
  module RExec
22
22
  module VERSION
23
23
  MAJOR = 1
24
- MINOR = 2
25
- TINY = 6
24
+ MINOR = 3
25
+ TINY = 0
26
26
 
27
27
  STRING = [MAJOR, MINOR, TINY].join('.')
28
28
  end
@@ -18,6 +18,14 @@
18
18
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
19
  # THE SOFTWARE.
20
20
 
21
+ module RemoteProxy
22
+ def self.foo
23
+ return :bar
24
+ end
25
+ end
26
+
27
+ $connection.handler = RemoteProxy
28
+
21
29
  $connection.run do |object|
22
30
  case(object[0])
23
31
  when :bounce
@@ -39,30 +39,43 @@ end
39
39
  BOUNCE = "Apples and Oranges"
40
40
 
41
41
  class RemoteServerTest < Test::Unit::TestCase
42
- def test_block_execution
43
- code = Pathname.new(__FILE__).dirname + "./client.rb"
44
-
45
- RExec::start_server(code.read, COMMAND) do |conn, pid|
46
- conn.send_object([:bounce, BOUNCE])
47
-
48
- assert_equal BOUNCE, conn.receive_object
49
-
50
- conn.dump_errors
51
-
52
- conn.stop
53
- end
54
- end
55
-
56
- def test_result_execution
57
- code = Pathname.new(__FILE__).dirname + "./client.rb"
58
-
59
- conn, pid = RExec::start_server(code.read, COMMAND, :passthrough => [])
60
-
61
- conn.send_object([:bounce, BOUNCE])
62
- assert_equal BOUNCE, conn.receive_object
63
-
64
- conn.dump_errors
65
-
66
- conn.stop
67
- end
42
+ def test_block_execution
43
+ code = Pathname.new(__FILE__).dirname + "./client.rb"
44
+
45
+ RExec::start_server(code.read, COMMAND) do |conn, pid|
46
+ conn.send_object([:bounce, BOUNCE])
47
+
48
+ assert_equal BOUNCE, conn.receive_object
49
+
50
+ conn.dump_errors
51
+
52
+ conn.stop
53
+ end
54
+ end
55
+
56
+ def test_result_execution
57
+ code = Pathname.new(__FILE__).dirname + "./client.rb"
58
+
59
+ conn, pid = RExec::start_server(code.read, COMMAND)
60
+
61
+ conn.send_object([:bounce, BOUNCE])
62
+ assert_equal BOUNCE, conn.receive_object
63
+
64
+ conn.dump_errors
65
+
66
+ conn.stop
67
+ end
68
+
69
+ def test_proxy
70
+ code = Pathname.new(__FILE__).dirname + "./client.rb"
71
+
72
+ conn, pid = RExec::start_server(code.read, COMMAND)
73
+
74
+ assert_equal conn.proxy.foo, :bar
75
+
76
+ conn.dump_errors
77
+
78
+ conn.stop
79
+ end
68
80
  end
81
+
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 1
7
- - 2
8
- - 6
9
- version: 1.2.6
7
+ - 3
8
+ - 0
9
+ version: 1.3.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Samuel Williams
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2011-07-17 00:00:00 +12:00
17
+ date: 2011-07-31 00:00:00 +12:00
18
18
  default_executable: daemon-exec
19
19
  dependencies: []
20
20