class SingleMindedProxy(object): MAX_CALL_LENGTH = 600.0 # The maximum amount of seconds to wait for a remote call to finish. """A proxy handling a connection to an instance of SingleMindedRPC""" def __init__(self, address=('localhost', 3344)): super(SingleMindedProxy, self).__init__() # Store member variables. self.__address = address # Create a socket and connect to the server. self.__sock = TimedSocket() self.__connected = False self.__connect() self.__lock = allocate_lock() def __nonzero__(self): return True def __getattr__(self, attrname): """ Forwards any unknown attribute requests to the function that makes RPC calls to the server. @type attrname: str @param attrname: The attribute to search for. In this case it must be the name of a remote method on the RPC server. """ if attrname == '': return self else: return partial(self.make_rpc_call, attrname) def set_address(self, address): """ Set the address of the RPC server. @type address: tuple @param address: The address where the SingleMindedRPC server is listening. """ self.__address = address def __connect(self): """Connects to an instance of SingleMindedRPC.""" try: self.__sock.connect(self.__address) except Exception, excep: raise CommunicationError('Error connecting to RPC server.', excep) self.__connected = True
def __init__(self, address=('localhost', 3344)): super(SingleMindedProxy, self).__init__() # Store member variables. self.__address = address # Create a socket and connect to the server. self.__sock = TimedSocket() self.__connected = False self.__connect() self.__lock = allocate_lock()
def __init__(self, address=('', 0)): """ Constructor. @type address: tuple @param address: The address that the RPC server should listen on for incoming connection requests. """ # Initialize super class. super(SingleMindedRPC, self).__init__() # Create server socket listening for incoming requests. self.__server_sock = TimedSocket() self.__server_sock.bind(address) self.__server_sock.listen(5) # Set member variables. self.__functions = {} self.__shutdown = False self.__shutdown_signal = allocate_lock()
class SingleMindedRPC(Thread): """The single-minded RPC server.""" def __init__(self, address=('', 0)): """ Constructor. @type address: tuple @param address: The address that the RPC server should listen on for incoming connection requests. """ # Initialize super class. super(SingleMindedRPC, self).__init__() # Create server socket listening for incoming requests. self.__server_sock = TimedSocket() self.__server_sock.bind(address) self.__server_sock.listen(5) # Set member variables. self.__functions = {} self.__shutdown = False self.__shutdown_signal = allocate_lock() def shutdown(self): return self.__shutdown def get_function(self, function_name): if self.__functions.has_key(function_name): return self.__functions[function_name] else: return None def remove_connection(self, connection): with self.__connections_lock: self.__connections.remove(connection) def add_connection(self, connection): with self.__connections_lock: self.__connections.append(connection) def get_address(self): return self.__server_sock.addr def debug_print(self): print 'Registered functions:', self.__functions def register_function(self, rpc_function, rpc_name=''): """ Registers a new function with the RPC server. This function may afterwards be called by remote clients. @type rpc_function: function @param rpc_function: The function to register. @type rpc_name: str @param rpc_name: An (optional) name to use for the function. If this is not given the functions original name is used. """ # Do simple type-checking. if not type(rpc_function) in (FunctionType, MethodType) or type(rpc_name) != StringType: raise TypeError('Arguments of invalid type given.') # Check that the name is not already taken. if rpc_name == '': rpc_name = rpc_function.__name__ if self.__functions.has_key(rpc_name): raise SMRPCError('The function name %s is already taken.'%rpc_name) # Add the function to the list. self.__functions[rpc_name] = rpc_function def stop(self, block=False): """Stop the RPC server thread. @type block: bool @param block: Whether or not the call should block until the service is closed down properly. """ self.__shutdown = True if block: self.__shutdown_signal.acquire() self.__shutdown_signal.release() def teardown(self): """ Close down the RPC server completely. This closes the server socket making the SingleMindedRPC object unusable. """ self.__server_sock.close() def run(self): """ Main thread function. """ self.__shutdown_signal.acquire() self.__shutdown = False while not self.__shutdown: # Wait for an incoming connection attempt. try: # Accept an incoming connection attempt. new_sock = self.__server_sock.accept() # Create a new worker thread and start it. connection = SingleMindedWorker(new_sock, self) connection.start() except Timeout: continue # Reset the shutdown indicator. self.__shutdown_signal.release() def __wait_for_connection(self): """Waits for a connection to arrive on the server socket.""" # Wait for an incoming connection attempt. try: connection = self.__server_sock.accept() except Timeout: return # A connection has been established. self.__connected = True self.__client_sock = connection