diff --git a/lib/rpc.py b/lib/rpc.py index 310bfdd78e7ca3f7ad1f96800ec5a07e379b1c91..284469734f12f48397ed32586585e540a94bac9c 100644 --- a/lib/rpc.py +++ b/lib/rpc.py @@ -49,20 +49,36 @@ class NodeController: individual call. """ - def __init__(self, parent, node): + def __init__(self, parent, node, address=None): + """Constructor for the node controller. + + @type parent: L{Client} + @param parent: the C{Client} instance which holds global parameters for + the call + @type node: str + @param node: the name of the node we connect to; it is used for error + messages and in cases we the address paramater is not passed + @type address: str + @keyword address: the node's address, in case we know it, so that we + don't need to resolve it; testing shows that httplib has high + overhead in resolving addresses (even when speficied in /etc/hosts) + + """ self.parent = parent self.node = node + if address is None: + address = node self.failed = False - self.http_conn = hc = httplib.HTTPConnection(node, self.parent.port) + self.http_conn = hc = httplib.HTTPConnection(address, parent.port) try: hc.connect() - hc.putrequest('PUT', "/%s" % self.parent.procedure, + hc.putrequest('PUT', "/%s" % parent.procedure, skip_accept_encoding=True) - hc.putheader('Content-Length', str(len(parent.body))) + hc.putheader('Content-Length', parent.body_length) hc.endheaders() hc.send(parent.body) - except socket.error, err: + except socket.error: logging.exception("Error connecting to node %s", node) self.failed = True @@ -99,6 +115,9 @@ class Client: 'False' result, which is not good. This overloading of values can cause bugs. + @var body_length: cached string value of the length of the body (so that + individual C{NodeController} instances don't have to recompute it) + """ result_set = False result = False @@ -112,24 +131,38 @@ class Client: self.procedure = procedure self.args = args self.body = simplejson.dumps(args) + self.body_length = str(len(self.body)) #--- generic connector ------------- - def ConnectList(self, node_list): + def ConnectList(self, node_list, address_list=None): """Add a list of nodes to the target nodes. @type node_list: list @param node_list: the list of node names to connect + @type address_list: list or None + @keyword address_list: either None or a list with node addresses, + which must have the same length as the node list """ - for node in node_list: - self.ConnectNode(node) + if address_list is None: + address_list = [None for _ in node_list] + else: + assert len(node_list) == len(address_list), \ + "Name and address lists should have the same length" + for node, address in zip(node_list, address_list): + self.ConnectNode(node, address) - def ConnectNode(self, connect_node): + def ConnectNode(self, name, address=None): """Add a node to the target list. + @type name: str + @param name: the node name + @type address: str + @keyword address: the node address, if known + """ - self.nc[connect_node] = nc = NodeController(self, connect_node) + self.nc[name] = NodeController(self, name, address) def GetResults(self): """Return the results of the call.