tahoe-lafs/src/allmydata/util/connection_status.py
Itamar Turner-Trauring a08cde9a4d Port to Python 3.
2020-08-11 14:30:16 -04:00

96 lines
3.3 KiB
Python

"""
Parse connection status from Foolscap.
Ported to Python 3.
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from future.utils import PY2
if PY2:
from builtins import filter, map, zip, ascii, chr, hex, input, next, oct, open, pow, round, super, bytes, dict, list, object, range, str, max, min # noqa: F401
import time
from zope.interface import implementer
from ..interfaces import IConnectionStatus
@implementer(IConnectionStatus)
class ConnectionStatus(object):
def __init__(self, connected, summary, non_connected_statuses,
last_connection_time, last_received_time):
self.connected = connected
self.summary = summary
self.non_connected_statuses = non_connected_statuses
self.last_connection_time = last_connection_time
self.last_received_time = last_received_time
@classmethod
def unstarted(cls):
"""
Create a ``ConnectionStatus`` representing a connection for which no
attempts have yet been made.
"""
return cls(
connected=False,
summary=u"unstarted",
non_connected_statuses=[],
last_connection_time=None,
last_received_time=None,
)
def _hint_statuses(which, handlers, statuses):
non_connected_statuses = {}
for hint in which:
handler = handlers.get(hint)
handler_dsc = " via %s" % handler if handler else ""
dsc = statuses[hint]
non_connected_statuses["%s%s" % (hint, handler_dsc)] = dsc
return non_connected_statuses
def from_foolscap_reconnector(rc, last_received):
ri = rc.getReconnectionInfo()
# See foolscap/reconnector.py, ReconnectionInfo, for details about possible
# states. The returned result is a native string, it seems, so convert to
# unicode.
state = ri.state
if isinstance(state, bytes): # Python 2
state = str(state, "ascii")
if state == "unstarted":
return ConnectionStatus.unstarted()
ci = ri.connectionInfo
connected = False
last_connected = None
others = set(ci.connectorStatuses.keys())
summary = None
if state == "connected":
connected = True
if ci.winningHint:
others.remove(ci.winningHint)
summary = "Connected to %s via %s" % (
ci.winningHint, ci.connectionHandlers[ci.winningHint])
else:
summary = "Connected via listener (%s)" % ci.listenerStatus[0]
last_connected = ci.establishedAt
elif state == "connecting":
# ci describes the current in-progress attempt
summary = "Trying to connect"
elif state == "waiting":
now = time.time()
elapsed = now - ri.lastAttempt
delay = ri.nextAttempt - now
summary = "Reconnecting in %d seconds (last attempt %ds ago)" % \
(delay, elapsed)
# ci describes the previous (failed) attempt
non_connected_statuses = _hint_statuses(others,
ci.connectionHandlers,
ci.connectorStatuses)
cs = ConnectionStatus(connected, summary, non_connected_statuses,
last_connected, last_received)
return cs