Skip to content

Commit

Permalink
Allow socket.gethost* memoize to expire
Browse files Browse the repository at this point in the history
By default, the singletons will expire after 1 hour.
  • Loading branch information
matthewrmshin committed Mar 10, 2016
1 parent 1ea9051 commit 4f1651f
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 34 deletions.
6 changes: 3 additions & 3 deletions lib/Pyro/ext/remote.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand All @@ -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 """
Expand Down
2 changes: 1 addition & 1 deletion lib/Pyro/naming.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
8 changes: 4 additions & 4 deletions lib/Pyro/protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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:
Expand Down
49 changes: 29 additions & 20 deletions lib/Pyro/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -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():
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion lib/Pyro/wxnsc.py
Original file line number Diff line number Diff line change
Expand Up @@ -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, ''
Expand Down
19 changes: 14 additions & 5 deletions lib/cylc/suite_host.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 4f1651f

Please sign in to comment.