Skip to content

Commit

Permalink
[Tracker] Add a status for all trackers in a torrent
Browse files Browse the repository at this point in the history
As part of the changes needed for a more informative trackers tab in the
UIs, we need the info for each of the trackers in the torrent.
For this, new status keys were added, and `tracker_status` is now
considered deprecated.

For tracker info, the keys are:
`trackers_status` - a dict of tracker_url->status
`trackers_peers` - a dict of tracker_url->number of peers in the tracker

For DHT, PeX and LSD, the added key:
`peers_source` - a list of dicts, each contain the nameof the source,
  number of peers in that source and if it is enabled.
  • Loading branch information
DjLegolas committed Feb 26, 2022
1 parent c89a366 commit 7510710
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 9 deletions.
96 changes: 92 additions & 4 deletions deluge/core/torrent.py
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,8 @@ def __init__(self, handle, options, state=None, filename=None, magnet=None):
self.state = None
self.moving_storage_dest_path = None
self.tracker_status = ''
self.trackers_status = {}
self.trackers_peers = {}
self.tracker_host = None
self.forcing_recheck = False
self.forcing_recheck_paused = False
Expand Down Expand Up @@ -605,11 +607,12 @@ def set_trackers(self, trackers=None):
self.force_reannounce()
self.tracker_host = None

def set_tracker_status(self, status):
def set_tracker_status(self, status: str, tracker_url: str):
"""Sets the tracker status.
Args:
status (str): The tracker status.
status: The tracker status.
tracker_url: The tracker url.
Emits:
TorrentTrackerStatusEvent upon tracker status change.
Expand All @@ -618,12 +621,32 @@ def set_tracker_status(self, status):

self.tracker_host = None

if self.tracker_status != status:
if self.state == 'Paused':
return

if self.trackers_status.get(tracker_url) != status:
self.trackers_status[tracker_url] = status
self.tracker_status = status
component.get('EventManager').emit(
TorrentTrackerStatusEvent(self.torrent_id, self.tracker_status)
TorrentTrackerStatusEvent(
self.torrent_id,
self.trackers_status[tracker_url],
)
)

def set_tracker_peers(self, peers: int, tracker_url: str):
"""Sets the tracker peers amount
Args:
peers: The number of peers the tracker has.
tracker_url: The tracker url.
"""
if self.state == 'Paused':
return

if self.trackers_peers.get(tracker_url) != peers:
self.trackers_peers[tracker_url] = peers

def merge_trackers(self, torrent_info):
"""Merges new trackers in torrent_info into torrent"""
log.info(
Expand Down Expand Up @@ -666,6 +689,8 @@ def update_state(self):
self.state = 'Queued'
elif session_paused or status.paused:
self.state = 'Paused'
self.trackers_peers = {}
self.trackers_status = {}
else:
self.state = LT_TORRENT_STATE_MAP.get(str(status.state), str(status.state))

Expand Down Expand Up @@ -865,6 +890,65 @@ def get_peers(self):

return ret

def get_peers_source(self):
"""Get the peers source statistics for this torrent.
A list of peers sources and the statistics about them.
Returns:
List: The peers source statistics.
The format for the source data::
{
"name": str,
"count" int,
"enabled": bool
}
"""
ret = []
for name in ['dht', 'pex', 'lsd']:
ret.append({'name': name, 'count': 0, 'enabled': False})

peers = self.handle.get_peer_info()

private = self.torrent_info.priv()
session_config = component.get('Core').get_config()
handle_flags = self.handle.flags()

if (
not private
and not handle_flags & lt.torrent_flags.disable_dht
and session_config['dht']
):
ret[0]['enabled'] = True
if (
not private
and not handle_flags & lt.torrent_flags.disable_pex
and session_config['utpex']
):
ret[1]['enabled'] = True
if (
not private
and not handle_flags & lt.torrent_flags.disable_lsd
and session_config['lsd']
):
ret[2]['enabled'] = True

for peer in peers:
# We do not want to report peers that are half-connected
if peer.flags & peer.connecting or peer.flags & peer.handshake:
continue

if peer.source & peer.dht:
ret[0]['count'] += 1
if peer.source & peer.pex:
ret[1]['count'] += 1
if peer.source & peer.lsd:
ret[2]['count'] += 1

return ret

def get_queue_position(self):
"""Get the torrents queue position
Expand Down Expand Up @@ -1158,7 +1242,10 @@ def _create_status_funcs(self):
'tracker': lambda: self.status.current_tracker,
'tracker_host': self.get_tracker_host,
'trackers': lambda: self.trackers,
# Deprecated: Use trackers_status
'tracker_status': lambda: self.tracker_status,
'trackers_status': lambda: self.trackers_status,
'trackers_peers': lambda: self.trackers_peers,
'upload_payload_rate': lambda: self.status.upload_payload_rate,
'comment': lambda: decode_bytes(self.torrent_info.comment())
if self.has_metadata
Expand All @@ -1185,6 +1272,7 @@ def _create_status_funcs(self):
'orig_files': self.get_orig_files,
'is_seed': lambda: self.status.is_seeding,
'peers': self.get_peers,
'peers_source': self.get_peers_source,
'queue': lambda: self.status.queue_position,
'ratio': self.get_ratio,
'completed_time': lambda: self.status.completed_time,
Expand Down
15 changes: 10 additions & 5 deletions deluge/core/torrentmanager.py
Original file line number Diff line number Diff line change
Expand Up @@ -1351,7 +1351,9 @@ def on_alert_tracker_reply(self, alert):
return

# Set the tracker status for the torrent
torrent.set_tracker_status('Announce OK')
torrent.set_tracker_status('Announce OK', alert.url)
# Set the amount of peers of the tracker
torrent.set_tracker_peers(alert.num_peers, alert.url)

# Check for peer information from the tracker, if none then send a scrape request.
torrent.get_lt_status()
Expand All @@ -1366,7 +1368,7 @@ def on_alert_tracker_announce(self, alert):
return

# Set the tracker status for the torrent
torrent.set_tracker_status('Announce Sent')
torrent.set_tracker_status('Announce Sent', alert.url)

def on_alert_tracker_warning(self, alert):
"""Alert handler for libtorrent tracker_warning_alert"""
Expand All @@ -1375,7 +1377,10 @@ def on_alert_tracker_warning(self, alert):
except (RuntimeError, KeyError):
return
# Set the tracker status for the torrent
torrent.set_tracker_status('Warning: %s' % decode_bytes(alert.message()))
torrent.set_tracker_status(
'Warning: %s' % decode_bytes(alert.message()),
alert.url,
)

def on_alert_tracker_error(self, alert):
"""Alert handler for libtorrent tracker_error_alert"""
Expand All @@ -1398,9 +1403,9 @@ def on_alert_tracker_error(self, alert):
endpoint['last_error']['value'] == 0
for endpoint in tracker['endpoints']
):
torrent.set_tracker_status('Announce OK')
torrent.set_tracker_status('Announce OK', alert.url)
else:
torrent.set_tracker_status('Error: ' + error_message)
torrent.set_tracker_status('Error: ' + error_message, alert.url)
break

def on_alert_storage_moved(self, alert):
Expand Down

0 comments on commit 7510710

Please sign in to comment.