Skip to content

Commit

Permalink
Pyro: memoize socket.gethost* calls
Browse files Browse the repository at this point in the history
  • Loading branch information
matthewrmshin committed Mar 10, 2016
1 parent d268eb8 commit 1ea9051
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 12 deletions.
3 changes: 2 additions & 1 deletion README
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ Acknowledgement for non-cylc Work:
Unmodified external software library released under the LGPL license.
See [metomi/isodatetime](https://github.com/metomi/isodatetime).
* lib/Pyro/:
Unmodified external software library released under the MIT license.
External software library released under the MIT license.
Minor modification based on version 3.16.
See [Pyro 3.16](https://pypi.python.org/pypi/Pyro).

Licences for non-cylc work included in this distribution can be found in the
Expand Down
7 changes: 4 additions & 3 deletions lib/Pyro/ext/remote.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import Pyro.naming
import Pyro.core
import Pyro.util
from Pyro.util import HostUtil

from Pyro.protocol import ProtocolError

Expand Down Expand Up @@ -103,7 +104,7 @@ def unregister_objects():

def host_ipaddr(interface = None):
if sys.platform == "win32":
return socket.gethostbyname(socket.gethostname())
return HostUtil.inst().gethostbyname()

cmd = "/sbin/ifconfig"
if interface:
Expand Down Expand Up @@ -135,7 +136,7 @@ def host_ipaddr(interface = None):

fd.close()

return this_host or socket.gethostbyname(socket.gethostname())
return this_host or HostUtil.inst().gethostbyname()

def find_nameserver(hostname = None, portnum = None):
if hostname and hostname.find('://') > 0:
Expand All @@ -151,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 = socket.gethostbyname('localhost')
localhost = HostUtil.inst().gethostbyname('localhost')
if verbose:
print "Error:", x
print """
Expand Down
3 changes: 2 additions & 1 deletion lib/Pyro/naming.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import sys, os, socket, time, traceback, errno
import dircache, shutil, SocketServer
import Pyro.constants, Pyro.core, Pyro.errors, Pyro.protocol, Pyro.util
from Pyro.util import HostUtil
if Pyro.util.supports_multithreading():
import threading

Expand Down Expand Up @@ -119,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:
socket.gethostbyname(bcaddr)
HostUtil.inst().gethostbyname(bcaddr)
except socket.error:
msg="invalid broadcast address '%s'" % bcaddr
if trace:
Expand Down
9 changes: 5 additions & 4 deletions lib/Pyro/protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import md5
md5=md5.md5
import Pyro.constants, Pyro.util
from Pyro.util import HostUtil

from Pyro.errors import *
from Pyro.errors import _InternalNoModuleError
Expand Down Expand Up @@ -57,17 +58,17 @@ class SSLError(Exception): pass
def getHostname(ip=None):
try:
if ip:
(hn,alias,ips) = socket.gethostbyaddr(ip)
hn,alias, ips = HostUtil.inst().gethostbyaddr(ip)
return hn
else:
return socket.gethostname()
return HostUtil.inst().gethostname()
except socket.error:
return None

#------ Get IP address (return None on error)
def getIPAddress(host=None):
try:
return socket.gethostbyname(host or getHostname())
return HostUtil.inst().gethostbyname(host or getHostname())
except socket.error:
return None

Expand Down Expand Up @@ -1041,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:
socket.gethostbyname(host) # validate hostname
HostUtil.inst().gethostbyname(host) # validate hostname
try:
if prtcol=='PYROSSL':
try:
Expand Down
41 changes: 40 additions & 1 deletion lib/Pyro/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,45 @@ def clear(self): self.flag=0
def wait(self,timeout=None):
raise RuntimeError("cannot wait in non-threaded environment")


class HostUtil(object):
"""Wrap and memoize socket.gethost* results."""

_INST = 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 __init__(self):
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]

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]

def gethostname(self):
"""Wrap and memoize socket.gethostname."""
if self.hostname is None:
self.hostname = socket.gethostname()
return self.hostname


def getEventObject():
if supports_multithreading():
from threading import Event
Expand Down Expand Up @@ -333,7 +372,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=socket.gethostbyname(socket.gethostname())
ip = HostUtil.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
5 changes: 3 additions & 2 deletions lib/Pyro/wxnsc.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
#
# Standard modules
#
import os, sys, socket
import os, sys
import traceback, cStringIO

#
Expand All @@ -42,6 +42,7 @@
from Pyro.errors import NamingError, ConnectionClosedError,\
ConnectionDeniedError
import Pyro.core
from Pyro.util import HostUtil

#----------------------------------------------------------------------#
# Module constants
Expand Down Expand Up @@ -652,7 +653,7 @@ def _setNSData(self):
Updates the display of current Name Server information.
"""
try:
ns_name, t, ns_ip = socket.gethostbyaddr(self.nsHost)
ns_name, t, ns_ip = HostUtil.inst().gethostbyaddr(self.nsHost)
ns_ip = ns_ip[0]
except:
ns_name, ns_ip = self.nsHost, ''
Expand Down

0 comments on commit 1ea9051

Please sign in to comment.