From bdf7d8c0256fd4c3c5b8a6025bd58331b8f43ef1 Mon Sep 17 00:00:00 2001 From: Iustin Pop <iustin@google.com> Date: Mon, 20 Oct 2008 14:46:52 +0000 Subject: [PATCH] Add infrastructure for using addresses in rpc.py The patch adds support for passing node addresses to NodeController objects, which should speed up the connect sequence. The patch also adds another very small optimization of computing the content-length header value in the parent Client class instead of each NodeController. Reviewed-by: imsnah --- lib/rpc.py | 53 +++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 10 deletions(-) diff --git a/lib/rpc.py b/lib/rpc.py index 310bfdd78..284469734 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. -- GitLab