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, message}
`trackers_peers` - a dict of tracker_url->number of peers in the tracker

`trackers_status` will contain the status of the torrent and also the
message from the relevant alert.
  • Loading branch information
DjLegolas committed May 22, 2023
1 parent 4bf3eec commit f16678f
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 12 deletions.
44 changes: 38 additions & 6 deletions deluge/core/torrent.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import os
import socket
import time
from typing import Optional, List
from typing import List, Optional
from urllib.parse import urlparse

from twisted.internet.defer import Deferred, DeferredList
Expand Down Expand Up @@ -265,6 +265,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 @@ -648,11 +650,13 @@ def trackers(self, trackers: List['lt.announce_entry']) -> None:
self._trackers = trackers
self._trackers_last_update = time.time()

def set_tracker_status(self, status):
def set_tracker_status(self, status: str, tracker_url: str, message: str = ''):
"""Sets the tracker status.
Args:
status (str): The tracker status.
status: The tracker status.
tracker_url: The tracker url.
message: The message from tracker error/warning alerts
Emits:
TorrentTrackerStatusEvent upon tracker status change.
Expand All @@ -661,12 +665,35 @@ def set_tracker_status(self, status):

self.tracker_host = None

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

if self.trackers_status.get(tracker_url, {}).get('status') != status:
self.trackers_status[tracker_url] = {
'status': status,
'message': message,
}
self.tracker_status = f'{status}{f": {message}" if message else ""}'
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 @@ -709,6 +736,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 @@ -1201,7 +1230,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 Down
18 changes: 12 additions & 6 deletions deluge/core/torrentmanager.py
Original file line number Diff line number Diff line change
Expand Up @@ -1347,7 +1347,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 @@ -1362,7 +1364,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 @@ -1371,7 +1373,11 @@ 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',
alert.url,
decode_bytes(alert.warning_message()),
)

def on_alert_tracker_error(self, alert):
"""Alert handler for libtorrent tracker_error_alert"""
Expand All @@ -1384,7 +1390,7 @@ def on_alert_tracker_error(self, alert):
if not error_message:
error_message = decode_bytes(alert.error.message())
log.debug(
'Tracker Error Alert: %s [%s]', decode_bytes(alert.message()), error_message
f'Tracker Error Alert: {decode_bytes(alert.message())} [{error_message}]'
)
# libtorrent 1.2 added endpoint struct to each tracker. to prevent false updates
# we will need to verify that at least one endpoint to the errored tracker is working
Expand All @@ -1394,9 +1400,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', alert.url, error_message)
break

def on_alert_storage_moved(self, alert):
Expand Down

0 comments on commit f16678f

Please sign in to comment.