[Core] Stopped using libtorrent deprecated functions
As part of the process of adding support to LT 2.0, we should stop using all deprecated function, as some (if not all) were removed. For this process, we should use the LT 1.2 upgrade (guide)[1]. The change includes: * stop using file entries directly * start using the torrent handle's set/unset flags * stop using url key in add_torrent_params (for magnet) * stop accessing resume_data from save_resume_data_alert * stop using deprecated session status keys in UI [1] https://libtorrent.org/upgrade_to_1.2-ref.html Closes: https://dev.deluge-torrent.org/ticket/3499 Closes: https://github.com/deluge-torrent/deluge/pull/342
This commit is contained in:
parent
513d5f06e5
commit
2bd095e5bf
|
@ -41,7 +41,7 @@ All modules will require the [common](#common) section dependencies.
|
|||
|
||||
## Core (deluged daemon)
|
||||
|
||||
- [libtorrent] _>= 1.1.1_
|
||||
- [libtorrent] _>= 1.2.0_
|
||||
- [GeoIP] or [pygeoip] - Optional: IP address country lookup. (_Debian: `python-geoip`_)
|
||||
|
||||
## GTK UI
|
||||
|
|
|
@ -80,7 +80,7 @@ def convert_lt_files(files):
|
|||
"""Indexes and decodes files from libtorrent get_files().
|
||||
|
||||
Args:
|
||||
files (list): The libtorrent torrent files.
|
||||
files (file_storage): The libtorrent torrent files.
|
||||
|
||||
Returns:
|
||||
list of dict: The files.
|
||||
|
@ -95,18 +95,18 @@ def convert_lt_files(files):
|
|||
}
|
||||
"""
|
||||
filelist = []
|
||||
for index, _file in enumerate(files):
|
||||
for index in range(files.num_files()):
|
||||
try:
|
||||
file_path = _file.path.decode('utf8')
|
||||
file_path = files.file_path(index).decode('utf8')
|
||||
except AttributeError:
|
||||
file_path = _file.path
|
||||
file_path = files.file_path(index)
|
||||
|
||||
filelist.append(
|
||||
{
|
||||
'index': index,
|
||||
'path': file_path.replace('\\', '/'),
|
||||
'size': _file.size,
|
||||
'offset': _file.offset,
|
||||
'size': files.file_size(index),
|
||||
'offset': files.file_offset(index),
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -236,7 +236,7 @@ class Torrent:
|
|||
self.magnet = magnet
|
||||
self.status = self.handle.status()
|
||||
|
||||
self.torrent_info = self.handle.get_torrent_info()
|
||||
self.torrent_info = self.handle.torrent_file()
|
||||
self.has_metadata = self.status.has_metadata
|
||||
|
||||
self.options = TorrentOptions()
|
||||
|
@ -275,6 +275,18 @@ class Torrent:
|
|||
if log.isEnabledFor(logging.DEBUG):
|
||||
log.debug('Torrent object created.')
|
||||
|
||||
def _set_handle_flags(self, flag: lt.torrent_flags, set_flag: bool):
|
||||
"""set or unset a flag to the lt handle
|
||||
|
||||
Args:
|
||||
flag (lt.torrent_flags): the flag to set/unset
|
||||
set_flag (bool): True for setting the flag, False for unsetting it
|
||||
"""
|
||||
if set_flag:
|
||||
self.handle.set_flags(flag)
|
||||
else:
|
||||
self.handle.unset_flags(flag)
|
||||
|
||||
def on_metadata_received(self):
|
||||
"""Process the metadata received alert for this torrent"""
|
||||
self.has_metadata = True
|
||||
|
@ -359,7 +371,7 @@ class Torrent:
|
|||
"""Sets maximum download speed for this torrent.
|
||||
|
||||
Args:
|
||||
m_up_speed (float): Maximum download speed in KiB/s.
|
||||
m_down_speed (float): Maximum download speed in KiB/s.
|
||||
"""
|
||||
self.options['max_download_speed'] = m_down_speed
|
||||
if m_down_speed < 0:
|
||||
|
@ -391,7 +403,7 @@ class Torrent:
|
|||
return
|
||||
|
||||
# A list of priorities for each piece in the torrent
|
||||
priorities = self.handle.piece_priorities()
|
||||
priorities = self.handle.get_piece_priorities()
|
||||
|
||||
def get_file_piece(idx, byte_offset):
|
||||
return self.torrent_info.map_file(idx, byte_offset, 0).piece
|
||||
|
@ -424,7 +436,10 @@ class Torrent:
|
|||
sequential (bool): Enable sequential downloading.
|
||||
"""
|
||||
self.options['sequential_download'] = sequential
|
||||
self.handle.set_sequential_download(sequential)
|
||||
self._set_handle_flags(
|
||||
flag=lt.torrent_flags.sequential_download,
|
||||
set_flag=sequential,
|
||||
)
|
||||
|
||||
def set_auto_managed(self, auto_managed):
|
||||
"""Set auto managed mode, i.e. will be started or queued automatically.
|
||||
|
@ -434,7 +449,10 @@ class Torrent:
|
|||
"""
|
||||
self.options['auto_managed'] = auto_managed
|
||||
if not (self.status.paused and not self.status.auto_managed):
|
||||
self.handle.auto_managed(auto_managed)
|
||||
self._set_handle_flags(
|
||||
flag=lt.torrent_flags.auto_managed,
|
||||
set_flag=auto_managed,
|
||||
)
|
||||
self.update_state()
|
||||
|
||||
def set_super_seeding(self, super_seeding):
|
||||
|
@ -444,7 +462,10 @@ class Torrent:
|
|||
super_seeding (bool): Enable super seeding.
|
||||
"""
|
||||
self.options['super_seeding'] = super_seeding
|
||||
self.handle.super_seeding(super_seeding)
|
||||
self._set_handle_flags(
|
||||
flag=lt.torrent_flags.super_seeding,
|
||||
set_flag=super_seeding,
|
||||
)
|
||||
|
||||
def set_stop_ratio(self, stop_ratio):
|
||||
"""The seeding ratio to stop (or remove) the torrent at.
|
||||
|
@ -505,7 +526,7 @@ class Torrent:
|
|||
self.handle.prioritize_files(file_priorities)
|
||||
else:
|
||||
log.debug('Unable to set new file priorities.')
|
||||
file_priorities = self.handle.file_priorities()
|
||||
file_priorities = self.handle.get_file_priorities()
|
||||
|
||||
if 0 in self.options['file_priorities']:
|
||||
# Previously marked a file 'skip' so check for any 0's now >0.
|
||||
|
@ -632,7 +653,10 @@ class Torrent:
|
|||
elif status_error:
|
||||
self.state = 'Error'
|
||||
# auto-manage status will be reverted upon resuming.
|
||||
self.handle.auto_managed(False)
|
||||
self._set_handle_flags(
|
||||
flag=lt.torrent_flags.auto_managed,
|
||||
set_flag=False,
|
||||
)
|
||||
self.set_status_message(decode_bytes(status_error))
|
||||
elif status.moving_storage:
|
||||
self.state = 'Moving'
|
||||
|
@ -686,7 +710,10 @@ class Torrent:
|
|||
session can resume.
|
||||
"""
|
||||
status = self.handle.status()
|
||||
self.handle.auto_managed(False)
|
||||
self._set_handle_flags(
|
||||
flag=lt.torrent_flags.auto_managed,
|
||||
set_flag=False,
|
||||
)
|
||||
self.forced_error = TorrentError(message, status.paused, restart_to_resume)
|
||||
if not status.paused:
|
||||
self.handle.pause()
|
||||
|
@ -700,7 +727,10 @@ class Torrent:
|
|||
log.error('Restart deluge to clear this torrent error')
|
||||
|
||||
if not self.forced_error.was_paused and self.options['auto_managed']:
|
||||
self.handle.auto_managed(True)
|
||||
self._set_handle_flags(
|
||||
flag=lt.torrent_flags.auto_managed,
|
||||
set_flag=True,
|
||||
)
|
||||
self.forced_error = None
|
||||
self.set_status_message('OK')
|
||||
if update_state:
|
||||
|
@ -843,7 +873,7 @@ class Torrent:
|
|||
|
||||
def get_file_priorities(self):
|
||||
"""Return the file priorities"""
|
||||
if not self.handle.has_metadata():
|
||||
if not self.handle.status().has_metadata:
|
||||
return []
|
||||
|
||||
if not self.options['file_priorities']:
|
||||
|
@ -932,10 +962,10 @@ class Torrent:
|
|||
|
||||
if self.has_metadata:
|
||||
# Use the top-level folder as torrent name.
|
||||
filename = decode_bytes(self.torrent_info.file_at(0).path)
|
||||
filename = decode_bytes(self.torrent_info.files().file_path(0))
|
||||
name = filename.replace('\\', '/', 1).split('/', 1)[0]
|
||||
else:
|
||||
name = decode_bytes(self.handle.name())
|
||||
name = decode_bytes(self.handle.status().name)
|
||||
|
||||
if not name:
|
||||
name = self.torrent_id
|
||||
|
@ -1152,7 +1182,10 @@ class Torrent:
|
|||
|
||||
"""
|
||||
# Turn off auto-management so the torrent will not be unpaused by lt queueing
|
||||
self.handle.auto_managed(False)
|
||||
self._set_handle_flags(
|
||||
flag=lt.torrent_flags.auto_managed,
|
||||
set_flag=False,
|
||||
)
|
||||
if self.state == 'Error':
|
||||
log.debug('Unable to pause torrent while in Error state')
|
||||
elif self.status.paused:
|
||||
|
@ -1187,7 +1220,10 @@ class Torrent:
|
|||
else:
|
||||
# Check if torrent was originally being auto-managed.
|
||||
if self.options['auto_managed']:
|
||||
self.handle.auto_managed(True)
|
||||
self._set_handle_flags(
|
||||
flag=lt.torrent_flags.auto_managed,
|
||||
set_flag=True,
|
||||
)
|
||||
try:
|
||||
self.handle.resume()
|
||||
except RuntimeError as ex:
|
||||
|
|
|
@ -360,10 +360,9 @@ class TorrentManager(component.Component):
|
|||
if torrent_id in self.prefetching_metadata:
|
||||
return self.prefetching_metadata[torrent_id].defer
|
||||
|
||||
add_torrent_params = {}
|
||||
add_torrent_params['save_path'] = gettempdir()
|
||||
add_torrent_params['url'] = magnet.strip().encode('utf8')
|
||||
add_torrent_params['flags'] = (
|
||||
add_torrent_params = lt.parse_magnet_uri(magnet)
|
||||
add_torrent_params.save_path = gettempdir()
|
||||
add_torrent_params.flags = (
|
||||
(
|
||||
LT_DEFAULT_ADD_TORRENT_FLAGS
|
||||
| lt.add_torrent_params_flags_t.flag_duplicate_is_error
|
||||
|
@ -401,7 +400,10 @@ class TorrentManager(component.Component):
|
|||
metadata = b''
|
||||
if isinstance(torrent_info, lt.torrent_info):
|
||||
log.debug('prefetch metadata received')
|
||||
metadata = torrent_info.metadata()
|
||||
if VersionSplit(LT_VERSION) < VersionSplit('2.0.0.0'):
|
||||
metadata = torrent_info.metadata()
|
||||
else:
|
||||
metadata = torrent_info.info_section()
|
||||
|
||||
return torrent_id, b64encode(metadata)
|
||||
|
||||
|
@ -436,14 +438,10 @@ class TorrentManager(component.Component):
|
|||
elif magnet:
|
||||
magnet_info = get_magnet_info(magnet)
|
||||
if magnet_info:
|
||||
add_torrent_params['url'] = magnet.strip().encode('utf8')
|
||||
add_torrent_params['name'] = magnet_info['name']
|
||||
torrent_id = magnet_info['info_hash']
|
||||
# Workaround lt 1.2 bug for magnet resume data with no metadata
|
||||
if resume_data and VersionSplit(LT_VERSION) >= VersionSplit('1.2.10.0'):
|
||||
add_torrent_params['info_hash'] = bytes(
|
||||
bytearray.fromhex(torrent_id)
|
||||
)
|
||||
add_torrent_params['info_hash'] = bytes(bytearray.fromhex(torrent_id))
|
||||
else:
|
||||
raise AddTorrentError(
|
||||
'Unable to add magnet, invalid magnet info: %s' % magnet
|
||||
|
@ -1399,22 +1397,18 @@ class TorrentManager(component.Component):
|
|||
log.debug(
|
||||
'Tracker Error Alert: %s [%s]', decode_bytes(alert.message()), error_message
|
||||
)
|
||||
if VersionSplit(LT_VERSION) >= VersionSplit('1.2.0.0'):
|
||||
# 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
|
||||
for tracker in torrent.handle.trackers():
|
||||
if tracker['url'] == alert.url:
|
||||
if any(
|
||||
endpoint['last_error']['value'] == 0
|
||||
for endpoint in tracker['endpoints']
|
||||
):
|
||||
torrent.set_tracker_status('Announce OK')
|
||||
else:
|
||||
torrent.set_tracker_status('Error: ' + error_message)
|
||||
break
|
||||
else:
|
||||
# preserve old functionality for libtorrent < 1.2
|
||||
torrent.set_tracker_status('Error: ' + 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
|
||||
for tracker in torrent.handle.trackers():
|
||||
if tracker['url'] == alert.url:
|
||||
if any(
|
||||
endpoint['last_error']['value'] == 0
|
||||
for endpoint in tracker['endpoints']
|
||||
):
|
||||
torrent.set_tracker_status('Announce OK')
|
||||
else:
|
||||
torrent.set_tracker_status('Error: ' + error_message)
|
||||
break
|
||||
|
||||
def on_alert_storage_moved(self, alert):
|
||||
"""Alert handler for libtorrent storage_moved_alert"""
|
||||
|
@ -1488,7 +1482,9 @@ class TorrentManager(component.Component):
|
|||
return
|
||||
if torrent_id in self.torrents:
|
||||
# libtorrent add_torrent expects bencoded resume_data.
|
||||
self.resume_data[torrent_id] = lt.bencode(alert.resume_data)
|
||||
self.resume_data[torrent_id] = lt.bencode(
|
||||
lt.write_resume_data(alert.params)
|
||||
)
|
||||
|
||||
if torrent_id in self.waiting_on_resume_data:
|
||||
self.waiting_on_resume_data[torrent_id].callback(None)
|
||||
|
|
|
@ -109,7 +109,7 @@ class TestTorrent(BaseTestCase):
|
|||
# updates and will return old value. Also need to remove a priority
|
||||
# value as one file is much smaller than piece size so doesn't show.
|
||||
await prios_set # Delay to wait for alert from lt
|
||||
piece_prio = handle.piece_priorities()
|
||||
piece_prio = handle.get_piece_priorities()
|
||||
result = all(p in piece_prio for p in [3, 2, 0, 5, 6, 7])
|
||||
assert result
|
||||
|
||||
|
@ -151,9 +151,9 @@ class TestTorrent(BaseTestCase):
|
|||
handle = self.session.add_torrent(atp)
|
||||
|
||||
self.torrent = Torrent(handle, {})
|
||||
priorities_original = handle.piece_priorities()
|
||||
priorities_original = handle.get_piece_priorities()
|
||||
self.torrent.set_prioritize_first_last_pieces(True)
|
||||
priorities = handle.piece_priorities()
|
||||
priorities = handle.get_piece_priorities()
|
||||
|
||||
# The length of the list of new priorites is the same as the original
|
||||
assert len(priorities_original) == len(priorities)
|
||||
|
@ -175,7 +175,7 @@ class TestTorrent(BaseTestCase):
|
|||
self.torrent.set_prioritize_first_last_pieces(True)
|
||||
# Reset pirorities
|
||||
self.torrent.set_prioritize_first_last_pieces(False)
|
||||
priorities = handle.piece_priorities()
|
||||
priorities = handle.get_piece_priorities()
|
||||
|
||||
# Test the priority of the prioritized pieces
|
||||
for i in priorities:
|
||||
|
|
|
@ -62,7 +62,12 @@ class Command(BaseCommand):
|
|||
deferreds = []
|
||||
|
||||
ds = client.core.get_session_status(
|
||||
['num_peers', 'payload_upload_rate', 'payload_download_rate', 'dht_nodes']
|
||||
[
|
||||
'peer.num_peers_connected',
|
||||
'payload_upload_rate',
|
||||
'payload_download_rate',
|
||||
'dht.dht_nodes',
|
||||
]
|
||||
)
|
||||
ds.addCallback(on_session_status)
|
||||
deferreds.append(ds)
|
||||
|
@ -92,7 +97,7 @@ class Command(BaseCommand):
|
|||
'{!info!}Total download: %s'
|
||||
% fspeed(self.status['payload_download_rate'])
|
||||
)
|
||||
self.console.write('{!info!}DHT Nodes: %i' % self.status['dht_nodes'])
|
||||
self.console.write('{!info!}DHT Nodes: %i' % self.status['dht.dht_nodes'])
|
||||
|
||||
if isinstance(self.torrents, int):
|
||||
if self.torrents == -2:
|
||||
|
|
|
@ -541,13 +541,13 @@ class TorrentDetail(BaseMode, PopupsHandler):
|
|||
# Seed/peer info
|
||||
s = '{{!info!}}{}:{{!green!}} {} {{!input!}}({})'.format(
|
||||
torrent_data_fields['seeds']['name'],
|
||||
status['num_seeds'],
|
||||
status['peer.num_peers_connected'],
|
||||
status['total_seeds'],
|
||||
)
|
||||
row = self.add_string(row, s)
|
||||
s = '{{!info!}}{}:{{!red!}} {} {{!input!}}({})'.format(
|
||||
torrent_data_fields['peers']['name'],
|
||||
status['num_peers'],
|
||||
status['peer.num_peers_connected'],
|
||||
status['total_peers'],
|
||||
)
|
||||
row = self.add_string(row, s)
|
||||
|
|
|
@ -36,19 +36,23 @@ class StatusBars(component.Component):
|
|||
def on_get_session_status(status):
|
||||
self.upload = deluge.common.fsize(status['payload_upload_rate'])
|
||||
self.download = deluge.common.fsize(status['payload_download_rate'])
|
||||
self.connections = status['num_peers']
|
||||
self.connections = status['peer.num_peers_connected']
|
||||
if 'dht_nodes' in status:
|
||||
self.dht = status['dht_nodes']
|
||||
self.dht = status['dht.dht_nodes']
|
||||
|
||||
self.update_statusbars()
|
||||
|
||||
def on_get_external_ip(external_ip):
|
||||
self.external_ip = external_ip
|
||||
|
||||
keys = ['num_peers', 'payload_upload_rate', 'payload_download_rate']
|
||||
keys = [
|
||||
'peer.num_peers_connected',
|
||||
'payload_upload_rate',
|
||||
'payload_download_rate',
|
||||
]
|
||||
|
||||
if self.config['dht']:
|
||||
keys.append('dht_nodes')
|
||||
keys.append('dht.dht_nodes')
|
||||
|
||||
client.core.get_session_status(keys).addCallback(on_get_session_status)
|
||||
client.core.get_external_ip().addCallback(on_get_external_ip)
|
||||
|
|
|
@ -317,18 +317,22 @@ class StatusBar(component.Component):
|
|||
def send_status_request(self):
|
||||
# Sends an async request for data from the core
|
||||
keys = [
|
||||
'num_peers',
|
||||
'peer.num_peers_connected',
|
||||
'upload_rate',
|
||||
'download_rate',
|
||||
'payload_upload_rate',
|
||||
'payload_download_rate',
|
||||
'net.sent_bytes',
|
||||
'net.recv_bytes',
|
||||
'net.sent_payload_bytes',
|
||||
'net.recv_payload_bytes',
|
||||
]
|
||||
|
||||
if self.dht_status:
|
||||
keys.append('dht_nodes')
|
||||
keys.append('dht.dht_nodes')
|
||||
|
||||
if not self.health:
|
||||
keys.append('has_incoming_connections')
|
||||
keys.append('net.has_incoming_connections')
|
||||
|
||||
client.core.get_session_status(keys).addCallback(self._on_get_session_status)
|
||||
client.core.get_free_space().addCallback(self._on_get_free_space)
|
||||
|
@ -367,18 +371,18 @@ class StatusBar(component.Component):
|
|||
self.upload_protocol_rate = (
|
||||
status['upload_rate'] - status['payload_upload_rate']
|
||||
) // 1024
|
||||
self.num_connections = status['num_peers']
|
||||
self.num_connections = status['peer.num_peers_connected']
|
||||
self.update_download_label()
|
||||
self.update_upload_label()
|
||||
self.update_traffic_label()
|
||||
self.update_connections_label()
|
||||
|
||||
if 'dht_nodes' in status:
|
||||
self.dht_nodes = status['dht_nodes']
|
||||
if 'dht.dht_nodes' in status:
|
||||
self.dht_nodes = status['dht.dht_nodes']
|
||||
self.update_dht_label()
|
||||
|
||||
if 'has_incoming_connections' in status:
|
||||
self.health = status['has_incoming_connections']
|
||||
if 'net.has_incoming_connections' in status:
|
||||
self.health = status['net.has_incoming_connections']
|
||||
if self.health:
|
||||
self.remove_item(self.health_item)
|
||||
|
||||
|
|
|
@ -515,7 +515,7 @@ class WebApi(JSONComponent):
|
|||
return d
|
||||
|
||||
def got_stats(stats):
|
||||
ui_info['stats']['num_connections'] = stats['num_peers']
|
||||
ui_info['stats']['num_connections'] = stats['peer.num_peers_connected']
|
||||
ui_info['stats']['upload_rate'] = stats['payload_upload_rate']
|
||||
ui_info['stats']['download_rate'] = stats['payload_download_rate']
|
||||
ui_info['stats']['download_protocol_rate'] = (
|
||||
|
@ -524,9 +524,9 @@ class WebApi(JSONComponent):
|
|||
ui_info['stats']['upload_protocol_rate'] = (
|
||||
stats['upload_rate'] - stats['payload_upload_rate']
|
||||
)
|
||||
ui_info['stats']['dht_nodes'] = stats['dht_nodes']
|
||||
ui_info['stats']['dht_nodes'] = stats['dht.dht_nodes']
|
||||
ui_info['stats']['has_incoming_connections'] = stats[
|
||||
'has_incoming_connections'
|
||||
'net.has_incoming_connections'
|
||||
]
|
||||
|
||||
def got_filters(filters):
|
||||
|
@ -552,13 +552,13 @@ class WebApi(JSONComponent):
|
|||
|
||||
d3 = client.core.get_session_status(
|
||||
[
|
||||
'num_peers',
|
||||
'peer.num_peers_connected',
|
||||
'payload_download_rate',
|
||||
'payload_upload_rate',
|
||||
'download_rate',
|
||||
'upload_rate',
|
||||
'dht_nodes',
|
||||
'has_incoming_connections',
|
||||
'dht.dht_nodes',
|
||||
'net.has_incoming_connections',
|
||||
]
|
||||
)
|
||||
d3.addCallback(got_stats)
|
||||
|
|
Loading…
Reference in New Issue