diff --git a/lib/Pyro/ext/remote.py b/lib/Pyro/ext/remote.py index 5f7a8d6b54e..e446109bac3 100644 --- a/lib/Pyro/ext/remote.py +++ b/lib/Pyro/ext/remote.py @@ -104,7 +104,7 @@ def unregister_objects(): def host_ipaddr(interface = None): if sys.platform == "win32": - return HostUtil.inst().gethostbyname() + return HostUtil.get_inst().gethostbyname() cmd = "/sbin/ifconfig" if interface: @@ -136,7 +136,7 @@ def host_ipaddr(interface = None): fd.close() - return this_host or HostUtil.inst().gethostbyname() + return this_host or HostUtil.get_inst().gethostbyname() def find_nameserver(hostname = None, portnum = None): if hostname and hostname.find('://') > 0: @@ -152,7 +152,7 @@ def find_nameserver(hostname = None, portnum = None): ns = locator.getNS(host = hostname, port = portnum) except (Pyro.core.PyroError, socket.error), x: - localhost = HostUtil.inst().gethostbyname('localhost') + localhost = HostUtil.get_inst().gethostbyname('localhost') if verbose: print "Error:", x print """ diff --git a/lib/Pyro/naming.py b/lib/Pyro/naming.py index c52ce27cbc6..876d6430e40 100644 --- a/lib/Pyro/naming.py +++ b/lib/Pyro/naming.py @@ -120,7 +120,7 @@ def __sendSysCommand(self,request,host=None,port=None,trace=0,logerrors=1,role=P raise Pyro.errors.PyroError(msg) if bcaddr: try: - HostUtil.inst().gethostbyname(bcaddr) + HostUtil.get_inst().gethostbyname(bcaddr) except socket.error: msg="invalid broadcast address '%s'" % bcaddr if trace: diff --git a/lib/Pyro/protocol.py b/lib/Pyro/protocol.py index 727f07f4fe8..4d2e49980d0 100644 --- a/lib/Pyro/protocol.py +++ b/lib/Pyro/protocol.py @@ -58,17 +58,17 @@ class SSLError(Exception): pass def getHostname(ip=None): try: if ip: - hn,alias, ips = HostUtil.inst().gethostbyaddr(ip) + hn,alias, ips = HostUtil.get_inst().gethostbyaddr(ip) return hn else: - return HostUtil.inst().gethostname() + return HostUtil.get_inst().gethostname() except socket.error: return None #------ Get IP address (return None on error) def getIPAddress(host=None): try: - return HostUtil.inst().gethostbyname(host or getHostname()) + return HostUtil.get_inst().gethostbyname(host or getHostname()) except socket.error: return None @@ -1042,7 +1042,7 @@ def __init__(self, port, host='', threaded=_has_threading,prtcol='PYRO'): self.connections = [] # connection threads self.initTLS=lambda tls: None # default do-nothing func if host: - HostUtil.inst().gethostbyname(host) # validate hostname + HostUtil.get_inst().gethostbyname(host) # validate hostname try: if prtcol=='PYROSSL': try: diff --git a/lib/Pyro/util.py b/lib/Pyro/util.py index a7e9922c5d4..96c196c6be4 100644 --- a/lib/Pyro/util.py +++ b/lib/Pyro/util.py @@ -52,39 +52,48 @@ def wait(self,timeout=None): class HostUtil(object): """Wrap and memoize socket.gethost* results.""" - _INST = None + EXPIRE = 3600.0 # singleton expires in 1 hour by default + _instance = None @classmethod - def inst(cls, reset=False): - """Return the singleton of this class.""" - if cls._INST is None or reset: - cls._INST = cls() - return cls._INST + def get_inst(cls, new=False, expire=None): + """Return the singleton instance of this class. - def __init__(self): - self.hostname = None - self.hostbyname = {} - self.hostbyaddr = {} + If "new" is True, create a new singleton instance. + + """ + if expire is None: + expire = cls.EXPIRE + if (cls._instance is None or new or + time.time() > cls._instance.expire_time): + cls._instance = cls(expire) + return cls._instance + + def __init__(self, expire): + self.expire_time = time.time() + expire + self._hostname = None + self._hostbyname = {} + self._hostbyaddr = {} def gethostbyaddr(self, addr): """Wrap and memoize socket.gethostbyaddr.""" - if addr not in self.hostbyaddr: - self.hostbyaddr[addr] = socket.gethostbyaddr(addr) - return self.hostbyaddr[addr] + if addr not in self._hostbyaddr: + self._hostbyaddr[addr] = socket.gethostbyaddr(addr) + return self._hostbyaddr[addr] def gethostbyname(self, name=None): """Wrap and memoize socket.gethostbyname.""" if name is None: name = self.gethostname() - if name not in self.hostbyname: - self.hostbyname[name] = socket.gethostbyname(name) - return self.hostbyname[name] + if name not in self._hostbyname: + self._hostbyname[name] = socket.gethostbyname(name) + return self._hostbyname[name] def gethostname(self): """Wrap and memoize socket.gethostname.""" - if self.hostname is None: - self.hostname = socket.gethostname() - return self.hostname + if self._hostname is None: + self._hostname = socket.gethostname() + return self._hostname def getEventObject(): @@ -372,7 +381,7 @@ def getGUID(): # For A: should use the machine's MAC ethernet address, but there is no # portable way to get it... use the IP address + 2 bytes process id. try: - ip = HostUtil.inst().gethostbyname() + ip = HostUtil.get_inst().gethostbyname() networkAddrStr=binascii.hexlify(socket.inet_aton(ip))+"%04x" % os.getpid() except socket.error: # can't get IP address... use another value, like our Python id() and PID diff --git a/lib/Pyro/wxnsc.py b/lib/Pyro/wxnsc.py index 197f834a157..6012140e67d 100644 --- a/lib/Pyro/wxnsc.py +++ b/lib/Pyro/wxnsc.py @@ -653,7 +653,7 @@ def _setNSData(self): Updates the display of current Name Server information. """ try: - ns_name, t, ns_ip = HostUtil.inst().gethostbyaddr(self.nsHost) + ns_name, t, ns_ip = HostUtil.get_inst().gethostbyaddr(self.nsHost) ns_ip = ns_ip[0] except: ns_name, ns_ip = self.nsHost, '' diff --git a/lib/cylc/suite_host.py b/lib/cylc/suite_host.py index 2e48685196a..8a59183dc8a 100644 --- a/lib/cylc/suite_host.py +++ b/lib/cylc/suite_host.py @@ -48,25 +48,34 @@ import sys import socket +from time import time class SuiteHostUtil(object): """(Suite) host utility.""" + EXPIRE = 3600.0 # singleton expires in 1 hour by default _instance = None @classmethod - def get_inst(cls, new=False): + def get_inst(cls, new=False, expire=None): """Return the singleton instance of this class. - If "new" is True, create a new singleton instance. + "new": if True, create a new singleton instance. + "expire": + the expire duration in seconds. If None or not specified, the + singleton expires after 3600.0 seconds (1 hour). Once expired, the + next call to this method will create a new singleton. """ - if cls._instance is None or new: - cls._instance = cls() + if expire is None: + expire = cls.EXPIRE + if cls._instance is None or new or time() > cls._instance.expire_time: + cls._instance = cls(expire) return cls._instance - def __init__(self): + def __init__(self, expire): + self.expire_time = time() + expire self._host_name = None self._host_ip_address = None self._host_name_pref = None