mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2025-01-19 03:06:33 +00:00
add IConnectionStatus and implementation
also a function to build one from a foolscap.Reconnector
This commit is contained in:
parent
8d008967e7
commit
48fc14bd30
@ -2830,3 +2830,60 @@ class InsufficientVersionError(Exception):
|
||||
|
||||
class EmptyPathnameComponentError(Exception):
|
||||
"""The webapi disallows empty pathname components."""
|
||||
|
||||
class IConnectionStatus(Interface):
|
||||
"""
|
||||
I hold information about the 'connectedness' for some reference.
|
||||
Connections are an illusion, of course: only messages hold any meaning,
|
||||
and they are fleeting. But for status displays, it is useful to pretend
|
||||
that 'recently contacted' means a connection is established, and
|
||||
'recently failed' means it is not.
|
||||
|
||||
This object is not 'live': it is created and populated when requested
|
||||
from the connection manager, and it does not change after that point.
|
||||
"""
|
||||
|
||||
connected = Attribute(
|
||||
"""
|
||||
Returns True if we appear to be connected: we've been successful
|
||||
in communicating with our target at some point in the past, and we
|
||||
haven't experienced any errors since then.""")
|
||||
|
||||
last_connection_time = Attribute(
|
||||
"""
|
||||
If is_connected() is True, this returns a number
|
||||
(seconds-since-epoch) when we last transitioned from 'not connected'
|
||||
to 'connected', such as when a TCP connect() operation completed and
|
||||
subsequent negotiation was successful. Otherwise it returns None.
|
||||
""")
|
||||
|
||||
last_connection_summary = Attribute(
|
||||
"""
|
||||
Returns a string with a brief summary of the current status, suitable
|
||||
for display on an informational page. The more complete text from
|
||||
last_connection_description would be appropriate for a tool-tip
|
||||
popup.
|
||||
""")
|
||||
|
||||
last_connection_description = Attribute(
|
||||
"""
|
||||
Returns a string with a description of the results of the most recent
|
||||
connection attempt. For Foolscap connections, this indicates the
|
||||
winning hint and the connection handler which used it, e.g.
|
||||
'tcp:HOST:PORT via tcp' or 'tor:HOST.onion:PORT via tor':
|
||||
|
||||
* 'Connection successful: HINT via HANDLER (other hints: ..)'
|
||||
* 'Connection failed: HINT->HANDLER->FAILURE, ...'
|
||||
|
||||
Note that this describes the last *completed* connection attempt. If
|
||||
a connection attempt is currently in progress, this method will
|
||||
describe the results of the previous attempt.
|
||||
""")
|
||||
|
||||
last_received_time = Attribute(
|
||||
"""
|
||||
Returns a number (seconds-since-epoch) describing the last time we
|
||||
heard anything (including low-level keep-alives or inbound requests)
|
||||
from the other side.
|
||||
""")
|
||||
|
||||
|
81
src/allmydata/util/connection_status.py
Normal file
81
src/allmydata/util/connection_status.py
Normal file
@ -0,0 +1,81 @@
|
||||
import time
|
||||
from zope.interface import implementer
|
||||
from ..interfaces import IConnectionStatus
|
||||
|
||||
@implementer(IConnectionStatus)
|
||||
class ConnectionStatus:
|
||||
def __init__(self, connected, summary,
|
||||
last_connection_description, last_connection_time,
|
||||
last_received_time):
|
||||
self.connected = connected
|
||||
self.last_connection_summary = summary
|
||||
self.last_connection_description = last_connection_description
|
||||
self.last_connection_time = last_connection_time
|
||||
self.last_received_time = last_received_time
|
||||
|
||||
def _describe_statuses(hints, handlers, statuses):
|
||||
descriptions = []
|
||||
for hint in sorted(hints):
|
||||
handler = handlers.get(hint)
|
||||
handler_dsc = " via %s" % handler if handler else ""
|
||||
status = statuses[hint]
|
||||
descriptions.append(" %s%s: %s\n" % (hint, handler_dsc, status))
|
||||
return "".join(descriptions)
|
||||
|
||||
def from_foolscap_reconnector(rc, last_received):
|
||||
ri = rc.getReconnectionInfo()
|
||||
state = ri.state
|
||||
# the Reconnector shouldn't even be exposed until it is started, so we
|
||||
# should never see "unstarted"
|
||||
assert state in ("connected", "connecting", "waiting"), state
|
||||
ci = ri.connectionInfo
|
||||
|
||||
if state == "connected":
|
||||
connected = True
|
||||
# build a description that shows the winning hint, and the outcomes
|
||||
# of the losing ones
|
||||
statuses = ci.connectorStatuses
|
||||
handlers = ci.connectionHandlers
|
||||
others = set(statuses.keys())
|
||||
|
||||
winner = ci.winningHint
|
||||
if winner:
|
||||
others.remove(winner)
|
||||
winning_handler = ci.connectionHandlers[winner]
|
||||
winning_dsc = "to %s via %s" % (winner, winning_handler)
|
||||
else:
|
||||
winning_dsc = "via listener (%s)" % ci.listenerStatus[0]
|
||||
if others:
|
||||
other_dsc = "\nother hints:\n%s" % \
|
||||
_describe_statuses(others, handlers, statuses)
|
||||
else:
|
||||
other_dsc = ""
|
||||
details = "Connection successful " + winning_dsc + other_dsc
|
||||
summary = "Connected %s" % winning_dsc
|
||||
last_connected = ci.establishedAt
|
||||
elif state == "connecting":
|
||||
connected = False
|
||||
# ci describes the current in-progress attempt
|
||||
statuses = ci.connectorStatuses
|
||||
current = _describe_statuses(sorted(statuses.keys()),
|
||||
ci.connectionHandlers, statuses)
|
||||
details = "Trying to connect:\n%s" % current
|
||||
summary = "Trying to connect"
|
||||
last_connected = None
|
||||
elif state == "waiting":
|
||||
connected = False
|
||||
now = time.time()
|
||||
elapsed = now - ri.lastAttempt
|
||||
delay = ri.nextAttempt - now
|
||||
# ci describes the previous (failed) attempt
|
||||
statuses = ci.connectorStatuses
|
||||
last = _describe_statuses(sorted(statuses.keys()),
|
||||
ci.connectionHandlers, statuses)
|
||||
details = "Reconnecting in %d seconds\nLast attempt %ds ago:\n%s" \
|
||||
% (delay, elapsed, last)
|
||||
summary = "Reconnecting in %d seconds" % delay
|
||||
last_connected = None
|
||||
|
||||
cs = ConnectionStatus(connected, summary, details,
|
||||
last_connected, last_received)
|
||||
return cs
|
Loading…
Reference in New Issue
Block a user