X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/tripe/blobdiff_plain/e8ea4061c8cda115466e3520fa897caa559438ac..660564a1b1490f71cd18a4861b521396b6bdb67d:/peerdb/tripe-newpeers.in diff --git a/peerdb/tripe-newpeers.in b/peerdb/tripe-newpeers.in index 81e62f75..502492d9 100644 --- a/peerdb/tripe-newpeers.in +++ b/peerdb/tripe-newpeers.in @@ -60,6 +60,32 @@ class ResolverFailure (ExpectedError): def __str__(me): return "failed to resolve `%s': %s" % (me.host, me.msg) +class ResolvingHost (object): + """ + A host name which is being looked up by a bulk-resolver instance. + """ + + def __init__(me, name): + """Make a new resolving-host object for the host NAME.""" + me.name = name + me.addr = None + me.failure = None + + def setaddr(me, addr): + """Add the address ADDR.""" + me.addr = addr + + def failed(me, msg): + """ + Report that resolution of this host failed, with a human-readable MSG. + """ + me.failure = msg + + def get(me): + """Return the resolved address.""" + if me.failure is not None: raise ResolverFailure(me.name, me.failure) + return me.addr + class BulkResolver (object): """ Resolve a number of DNS names in parallel. @@ -78,36 +104,35 @@ class BulkResolver (object): def __init__(me): """Initialize the resolver.""" - me._resolvers = {} me._namemap = {} - - def prepare(me, host): - """Prime the resolver to resolve the name HOST.""" - if host not in me._resolvers: - me._resolvers[host] = M.SelResolveByName \ - (host, - lambda name, alias, addr: - me._resolved(host, addr[0]), - lambda: me._resolved(host, None)) + me._noutstand = 0 + + def prepare(me, name): + """Prime the resolver to resolve the given host NAME.""" + if name not in me._namemap: + me._namemap[name] = host = ResolvingHost(name) + host._resolv = M.SelResolveByName( + name, + lambda cname, alias, addr: me._resolved(host, addr[0]), + lambda: me._resolved(host, None)) + me._noutstand += 1 def run(me): """Run the background DNS resolver until it's finished.""" - while me._resolvers: - M.select() + while me._noutstand: M.select() - def lookup(me, host): - """ - Fetch the address corresponding to HOST. - """ - addr = me._namemap[host] - if addr is None: - raise ResolverFailure(host, '(unknown failure)') - return addr + def lookup(me, name): + """Fetch the address corresponding to the host NAME.""" + return me._namemap[name].get() def _resolved(me, host, addr): """Callback function: remember that ADDR is the address for HOST.""" - me._namemap[host] = addr - del me._resolvers[host] + if addr is None: + host.failed('(unknown failure)') + else: + host.setaddr(addr) + host._resolv = None + me._noutstand -= 1 ###-------------------------------------------------------------------------- ### The configuration parser.