Class: Cosmos::JsonDRbObject

Inherits:
Object
  • Object
show all
Defined in:
lib/cosmos/io/json_drb_object.rb

Overview

Used to forward all method calls to the remote server object. Before using this class ensure the remote service has been started in the server class:

json = JsonDrb.new
json.start_service('127.0.0.1', 7777, self)

Now the JsonDRbObject can be used to call server methods directly:

server = JsonDRbObject('127.0.0.1', 7777)
server.cmd(*args)

Instance Method Summary collapse

Constructor Details

#initialize(hostname, port) ⇒ JsonDRbObject

Returns a new instance of JsonDRbObject.

Parameters:

  • hostname (String)

    The name of the machine which has started the JSON service

  • port (Integer)

    The port number of the JSON service



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/cosmos/io/json_drb_object.rb', line 36

def initialize(hostname, port)
  hostname = '127.0.0.1' if (hostname.to_s.upcase == 'LOCALHOST')
  begin
    @addr = Socket.pack_sockaddr_in(port, hostname)
  rescue => error
    if error.message =~ /getaddrinfo/
      raise "Invalid hostname: #{hostname}"
    else
      raise error
    end
  end
  @hostname = hostname
  @port = port
  @mutex = Mutex.new
  @socket = nil
  @id = 0
  @request_in_progress = false
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_name, *method_params) ⇒ Object

Forwards all method calls to the remote service.

Parameters:

  • method_name (Symbol)

    Name of the method to call

  • method_params (Array)

    Array of parameters to pass to the method

Returns:

  • The result of the method call. If the method raises an exception the same exception is also raised. If something goes wrong with the protocol a DRb::DRbConnError exception is raised.



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/cosmos/io/json_drb_object.rb', line 67

def method_missing(method_name, *method_params)
  @mutex.synchronize do
    first_try = true
    loop do
      if !@socket or @socket.closed? or @request_in_progress
        if @request_in_progress
          @socket.close if @socket and !@socket.closed?
          @socket = nil
          @request_in_progress = false
        end
        begin
          @socket = TCPSocket.new(@hostname, @port)
          @socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
        rescue => e
          raise DRb::DRbConnError, e.message
        end
      end

      request = JsonRpcRequest.new(method_name, method_params, @id)
      @id += 1

      request_data = request.to_json(:allow_nan => true)
      begin
        @request_in_progress = true
        STDOUT.puts "Request:\n" if JsonDRb.debug?
        STDOUT.puts request_data if JsonDRb.debug?
        JsonDRb.send_data(@socket, request_data)
        response_data = JsonDRb.receive_message(@socket, '')
        STDOUT.puts "\nResponse:\n" if JsonDRb.debug?
        STDOUT.puts response_data if JsonDRb.debug?
        @request_in_progress = false
      rescue => e
        @socket.close if @socket and !@socket.closed?
        @socket = nil
        if first_try
          first_try = false
          next
        else
          raise DRb::DRbConnError, e.message, e.backtrace
        end
      end

      if response_data
        response = JsonRpcResponse.from_json(response_data)
        if JsonRpcErrorResponse === response
          if response.error.data
            raise Exception.from_hash(response.error.data)
          else
            raise "JsonDRb Error (#{response.error.code}): #{response.error.message}"
          end
        else
          return response.result
        end
      else
        # Socket was closed by server
        @socket.close if @socket and !@socket.closed?
        @socket = nil
        if first_try
          first_try = false
          next
        else
          # Socket already closed by receive_message
          raise DRb::DRbConnError, "Socket closed by server"
        end
      end
    end # loop
  end
end

Instance Method Details

#disconnectObject

Disconnects from the JSON server



56
57
58
# File 'lib/cosmos/io/json_drb_object.rb', line 56

def disconnect
  @socket.close if @socket and !@socket.closed?
end