Exemplo n.º 1
0
    def call(self, rpc, msg, timeout):
        """ Save the object that has been created and return the response.
            Will timeout after timeout ms if response has not been received
            
            Accepted Arguments:
            timeout -- (Integer) ms to wait for a response before returning
        """

        # Define local callback function to handle RPC response
        # and initialize result dict
        result = {
            "done": False,
            "success": False,
            "response": None,
            "error_msg": "timeout",
            "error_code": None
        }

        #Can't use just a simple boolean for 'done' because of the way it is
        #referenced in the callback.  The scope isn't clear and python
        #will redefine 'done' rather than change the value unless explicitly
        #defined as 'global done'
        #done = False
        def callback(request, response):
            result["response"] = response
            result["done"] = True
            result["error_msg"] = ""
            result["success"] = True

        #Setup the RPC channel
        channel = SocketRpcChannel(host=self.host, port=self.port)
        controller = channel.newController()
        service = self.service_stub_class(channel)

        #Make the RPC call and pass in a generic object with a
        #function called "run" linked to callback
        try:
            #Attempting to do something similar to a JAVA anonymous class
            #Create an instalce of a new generic type initialized with a
            #dict that has a run method pointing to the callback function
            rpc(service, controller, msg, type("", (), {"run": callback})())
        except Exception, info:
            print controller.error
Exemplo n.º 2
0
class TestRpcThread(unittest.TestCase):
    ''' Unit tests for the protobuf.service.RpcThread class.'''         

    def setUp(self):
        self.channel     = SocketRpcChannel(host=host, port=port)
        self.controller  = self.channel.newController()
        self.service     = test_pb2.TestService_Stub(self.channel)
        self.request = test_pb2.Request()
        self.request.str_data = 'I like cheese'
        self.callback = lambda request, response : response
        self.thread      = service.RpcThread(test_pb2.TestService_Stub.TestMethod,
                                             self.service, 
                                             self.controller,
                                             self.request,
                                             self.callback)
        ServerThread.start_server()
        
    def tearDown(self):
        pass
        
    def test__init__(self):
        '''Test RpcThread constructor.'''
        
        self.assertEqual(self.thread.method,
                         test_pb2.TestService_Stub.TestMethod,
                         "Attribute 'method' incorrectly initialized")
        
        self.assertEqual(self.thread.service,
                         self.service,
                         "Attribute 'service' incorrectly initialized")
        
        self.assertEqual(self.thread.controller,
                         self.controller,
                         "Attribute 'controller' incorrectly initialized")
        
        self.assertEqual(self.thread.request,
                         self.request,
                         "Attribute 'request' incorrectly initialized")
        
        self.assertEqual(self.thread.callback,
                         self.callback,
                         "Attribute 'callback' incorrectly initialized")
        
        self.assertEqual(self.thread.isDaemon(), True,
                         "Thread not set as Daemon")
    
    
    def test_run(self):
        '''Test the run method'''
        
        try:
            self.thread.run()
        except Exception, e:
            self.assert_(False, "TestRpcThread.run() threw and exception", e)
Exemplo n.º 3
0
 def setUp(self):
     self.channel     = SocketRpcChannel(host=host, port=port)
     self.controller  = self.channel.newController()
     self.service     = test_pb2.TestService_Stub(self.channel)
     self.request = test_pb2.Request()
     self.request.str_data = 'I like cheese'
     self.callback = lambda request, response : response
     self.thread      = service.RpcThread(test_pb2.TestService_Stub.TestMethod,
                                          self.service, 
                                          self.controller,
                                          self.request,
                                          self.callback)
     ServerThread.start_server()
Exemplo n.º 4
0
 def call(self, rpc, msg, timeout):
     """ Save the object that has been created and return the response.
         Will timeout after timeout ms if response has not been received
         
         Accepted Arguments:
         timeout -- (Integer) ms to wait for a response before returning
     """
             
     # Define local callback function to handle RPC response
     # and initialize result dict
     result = {"done":False, "success":False, "response":None,
                     "error_msg":"timeout", "error_code":None}
     #Can't use just a simple boolean for 'done' because of the way it is
     #referenced in the callback.  The scope isn't clear and python
     #will redefine 'done' rather than change the value unless explicitly
     #defined as 'global done'
     #done = False
     def callback(request, response):
         result["response"]  = response
         result["done"]      = True
         result["error_msg"] = ""
         result["success"]   = True
     
     #Setup the RPC channel
     channel     = SocketRpcChannel(host=self.host, port=self.port)
     controller  = channel.newController()
     service     = self.service_stub_class(channel)
     
     #Make the RPC call and pass in a generic object with a
     #function called "run" linked to callback
     try:
         #Attempting to do something similar to a JAVA anonymous class
         #Create an instalce of a new generic type initialized with a
         #dict that has a run method pointing to the callback function
         rpc(service, controller, msg, type("", (), {"run":callback})())
     except Exception, info:
         print controller.error
Exemplo n.º 5
0
    def __init__(self, service_stub_class, port, host):
        ''' Contruct a new ProtoBufRpcRequest and return it.

            Accepted Arguments:
            service_stub_class -- (Service_Stub) The client side RPC
                                  stub class produced by protoc from
                                  the .proto file
            port -- (Integer) The port on which the service is running
                    on the RPC server.
            host -- (String) The hostname or IP address of the server
                    running the RPC service.
        '''
        self.service_stub_class = service_stub_class
        self.port               = port
        self.host               = host
        
        # Setup the RPC channel
        self.channel     = SocketRpcChannel(host=self.host, port=self.port)
        self.service     = self.service_stub_class(self.channel)
        
        # go through service_stub methods and add a wrapper function to 
        # this object that will call the method
        for method in service_stub_class.GetDescriptor().methods:
            # Add service methods to the this object
            rpc = lambda request, timeout=None, callback=None, service=self, method=method.name : service.call(
                        service_stub_class.__dict__[method], request, timeout, callback)
            rpc.__doc__ = method.name + ' method of the ' + \
                service_stub_class.DESCRIPTOR.name + ' from the ' + \
                service_stub_class.__module__ + ' module generated by the ' + \
                'protoc compiler.  This method can be called synchronously ' + \
                'by setting timeout -> ms or asynchrounously by setting ' + \
                'callback -> function(request,response)\n\n' + \
                'Synchronous Example:\n' + \
                '\trequest = ' + method.input_type.name + '()\n' + \
                '\ttry:\n' + \
                '\t#Wait 1000ms for a response\n' + \
                '\t\tresponse = ' + method.name + '(request, timeout=1000)\n' + \
                '\texcept: RpcException\n' + \
                '\t\t#Handle exception\n\n' + \
                'Asynchronous Example:\n' + \
                '\tdef callback(request,response):\n' + \
                '\t\t#Do some stuff\n' + \
                '\trequest = ' + method.input_type.name + '()\n' + \
                '\ttry:\n' + \
                '\t\t' + method.name + '(request, callback=callback)\n' + \
                '\texcept: RpcException\n' + \
                '\t\t#Handle exception\n\n' 
            self.__dict__[method.name] = rpc
Exemplo n.º 6
0
class RpcService(object):
    ''' Class abstracting the Protocol Buffer RPC calls for a supplied
        service stub.
    '''
  
    def __init__(self, service_stub_class, port, host):
        ''' Contruct a new ProtoBufRpcRequest and return it.

            Accepted Arguments:
            service_stub_class -- (Service_Stub) The client side RPC
                                  stub class produced by protoc from
                                  the .proto file
            port -- (Integer) The port on which the service is running
                    on the RPC server.
            host -- (String) The hostname or IP address of the server
                    running the RPC service.
        '''
        self.service_stub_class = service_stub_class
        self.port               = port
        self.host               = host
        
        # Setup the RPC channel
        self.channel     = SocketRpcChannel(host=self.host, port=self.port)
        self.service     = self.service_stub_class(self.channel)
        
        # go through service_stub methods and add a wrapper function to 
        # this object that will call the method
        for method in service_stub_class.GetDescriptor().methods:
            # Add service methods to the this object
            rpc = lambda request, timeout=None, callback=None, service=self, method=method.name : service.call(
                        service_stub_class.__dict__[method], request, timeout, callback)
            rpc.__doc__ = method.name + ' method of the ' + \
                service_stub_class.DESCRIPTOR.name + ' from the ' + \
                service_stub_class.__module__ + ' module generated by the ' + \
                'protoc compiler.  This method can be called synchronously ' + \
                'by setting timeout -> ms or asynchrounously by setting ' + \
                'callback -> function(request,response)\n\n' + \
                'Synchronous Example:\n' + \
                '\trequest = ' + method.input_type.name + '()\n' + \
                '\ttry:\n' + \
                '\t#Wait 1000ms for a response\n' + \
                '\t\tresponse = ' + method.name + '(request, timeout=1000)\n' + \
                '\texcept: RpcException\n' + \
                '\t\t#Handle exception\n\n' + \
                'Asynchronous Example:\n' + \
                '\tdef callback(request,response):\n' + \
                '\t\t#Do some stuff\n' + \
                '\trequest = ' + method.input_type.name + '()\n' + \
                '\ttry:\n' + \
                '\t\t' + method.name + '(request, callback=callback)\n' + \
                '\texcept: RpcException\n' + \
                '\t\t#Handle exception\n\n' 
            self.__dict__[method.name] = rpc

    
    def call(self, rpc, request, timeout=None, callback=None):
        ''' Save the object that has been created and return the response.
            Will timeout after timeout ms if response has not been received.
            The timeout arg is only used for asynch requests.
            If a callback has been supplied the timeout arg is not used.
            The response value will be returned for a synch request but nothing
            will be returned for an asynch request.
            
            Accepted Arguments:
            timeout -- (Integer) ms to wait for a response before returning
        '''
                
        # Define local callback function to handle RPC response
        # and initialize result dict
        result = {'done': False, 'response': None}
        def synch_callback(request, response):
            result['response']  = response
            result['done']      = True
            result['error_msg'] = ''
            result['success']   = True
        
        # If no callback has been passed in then this is meant to be synchronous
        if callback == None:
            rpc_callback = synch_callback
        else:
            if ((not callable(callback) and 
                 (callback.__class__.__dict__.get('run') == None or
                  callback.run.func_code.co_argcount < 2)) or
                   (callable(callback) and callback.func_code.co_argcount < 2)):
                raise Exception("callback must be a callable with signature " +
                                "callback(request, response, ...) or an " +
                                "object with a callable run function with " +
                                "the same signature")                    
            rpc_callback = callback
        
        # Create a controller for this call
        controller  = self.channel.newController()
        
        # Spawn a new thread to wait for the callback so this can return
        # immediately if an asynch callback has been requested
        rpc_thread = RpcThread(rpc, self.service, controller,
                               request, rpc_callback)
        rpc_thread.start()
        # If a callback has been passed in return 
        if rpc_callback == callback:
            return
        else:
            if timeout == None:
                timeout = 100    
        end = time() + (timeout / 1000)
        
        # Tight loop waiting for timeout or synch_callback to set done to True 
        while time() < end and not result['done']:
            if controller.failed():
                if type(controller.error) is str:
                    raise Exception(controller.error)
                else:
                    raise controller.error
        
        if time() >= end and not result['done']:
            raise RpcError('request timed out')
        
        return result['response']