mirror of
https://git.deluge-torrent.org/deluge
synced 2025-08-12 03:18:47 +00:00
Removed LoopingCall from torrent.py
Having a LoopingCall for each torrent is expencive with a lot of torrents. The LoopingCall in torrent.py has been moved to torrentmanager.py which runs through all the torrents and calls cleanup_prev_status.
This commit is contained in:
parent
de3740fa70
commit
feaeee0379
3 changed files with 25 additions and 30 deletions
|
@ -124,8 +124,6 @@ class Torrent(object):
|
||||||
# We use this to return dicts that only contain changes from the previous
|
# We use this to return dicts that only contain changes from the previous
|
||||||
# {session_id: status_dict, ...}
|
# {session_id: status_dict, ...}
|
||||||
self.prev_status = {}
|
self.prev_status = {}
|
||||||
self.prev_status_cleanup_loop = LoopingCall(self._cleanup_prev_status)
|
|
||||||
self.prev_status_cleanup_loop.start(10)
|
|
||||||
|
|
||||||
# Set the libtorrent handle
|
# Set the libtorrent handle
|
||||||
self.handle = handle
|
self.handle = handle
|
||||||
|
@ -1017,7 +1015,7 @@ class Torrent(object):
|
||||||
except OSError as (errno, strerror):
|
except OSError as (errno, strerror):
|
||||||
log.debug("Cannot Remove Folder: %s (ErrNo %s)", strerror, errno)
|
log.debug("Cannot Remove Folder: %s (ErrNo %s)", strerror, errno)
|
||||||
|
|
||||||
def _cleanup_prev_status(self):
|
def cleanup_prev_status(self):
|
||||||
"""
|
"""
|
||||||
This method gets called to check the validity of the keys in the prev_status
|
This method gets called to check the validity of the keys in the prev_status
|
||||||
dict. If the key is no longer valid, the dict will be deleted.
|
dict. If the key is no longer valid, the dict will be deleted.
|
||||||
|
|
|
@ -199,6 +199,7 @@ class TorrentManager(component.Component):
|
||||||
self.save_state_timer = LoopingCall(self.save_state)
|
self.save_state_timer = LoopingCall(self.save_state)
|
||||||
self.save_resume_data_timer = LoopingCall(self.save_resume_data)
|
self.save_resume_data_timer = LoopingCall(self.save_resume_data)
|
||||||
self.save_all_resume_data_timer = LoopingCall(self.save_resume_data, self.torrents.keys())
|
self.save_all_resume_data_timer = LoopingCall(self.save_resume_data, self.torrents.keys())
|
||||||
|
self.prev_status_cleanup_loop = LoopingCall(self.cleanup_torrents_prev_status)
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
# Check for old temp file to verify safe shutdown
|
# Check for old temp file to verify safe shutdown
|
||||||
|
@ -237,6 +238,7 @@ class TorrentManager(component.Component):
|
||||||
self.save_resume_data_timer.start(190, False)
|
self.save_resume_data_timer.start(190, False)
|
||||||
# Force update for all resume data a bit less frequently
|
# Force update for all resume data a bit less frequently
|
||||||
self.save_all_resume_data_timer.start(900, False)
|
self.save_all_resume_data_timer.start(900, False)
|
||||||
|
self.prev_status_cleanup_loop.start(10)
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
# Stop timers
|
# Stop timers
|
||||||
|
@ -249,13 +251,13 @@ class TorrentManager(component.Component):
|
||||||
if self.save_all_resume_data_timer.running:
|
if self.save_all_resume_data_timer.running:
|
||||||
self.save_all_resume_data_timer.stop()
|
self.save_all_resume_data_timer.stop()
|
||||||
|
|
||||||
|
if self.prev_status_cleanup_loop.running:
|
||||||
|
self.prev_status_cleanup_loop.stop()
|
||||||
|
|
||||||
# Save state on shutdown
|
# Save state on shutdown
|
||||||
self.save_state()
|
self.save_state()
|
||||||
|
|
||||||
self.session.pause()
|
self.session.pause()
|
||||||
for key in self.torrents:
|
|
||||||
# Stop the status cleanup LoopingCall here
|
|
||||||
self.torrents[key].prev_status_cleanup_loop.stop()
|
|
||||||
|
|
||||||
def remove_temp_file(result):
|
def remove_temp_file(result):
|
||||||
"""Remove the temp_file to signify successfully saved state"""
|
"""Remove the temp_file to signify successfully saved state"""
|
||||||
|
@ -530,8 +532,7 @@ class TorrentManager(component.Component):
|
||||||
return filedump
|
return filedump
|
||||||
|
|
||||||
def remove(self, torrent_id, remove_data=False):
|
def remove(self, torrent_id, remove_data=False):
|
||||||
"""
|
"""Remove torrent from the session
|
||||||
Remove a torrent from the session.
|
|
||||||
|
|
||||||
:param torrent_id: the torrent to remove
|
:param torrent_id: the torrent to remove
|
||||||
:type torrent_id: string
|
:type torrent_id: string
|
||||||
|
@ -574,9 +575,6 @@ class TorrentManager(component.Component):
|
||||||
except OSError as ex:
|
except OSError as ex:
|
||||||
log.warning("Unable to remove copy torrent file: %s", ex)
|
log.warning("Unable to remove copy torrent file: %s", ex)
|
||||||
|
|
||||||
# Stop the looping call
|
|
||||||
self.torrents[torrent_id].prev_status_cleanup_loop.stop()
|
|
||||||
|
|
||||||
# Remove from set if it wasn't finished
|
# Remove from set if it wasn't finished
|
||||||
if not self.torrents[torrent_id].is_finished:
|
if not self.torrents[torrent_id].is_finished:
|
||||||
try:
|
try:
|
||||||
|
@ -726,12 +724,12 @@ class TorrentManager(component.Component):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def save_resume_data(self, torrent_ids=None):
|
def save_resume_data(self, torrent_ids=None):
|
||||||
"""
|
"""Saves resume data for list of torrent_ids or for all torrents
|
||||||
Saves resume data for list of torrent_ids or for all torrents
|
|
||||||
needing resume data updated if torrent_ids is None
|
needing resume data updated if torrent_ids is None
|
||||||
|
|
||||||
:returns: A Deferred whose callback will be invoked when save is complete
|
:returns: A Deferred whose callback will be invoked when save is complete
|
||||||
:rtype: twisted.internet.defer.Deferred
|
:rtype: twisted.internet.defer.Deferred
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if torrent_ids is None:
|
if torrent_ids is None:
|
||||||
torrent_ids = (t[0] for t in self.torrents.iteritems() if t[1].handle.need_save_resume_data())
|
torrent_ids = (t[0] for t in self.torrents.iteritems() if t[1].handle.need_save_resume_data())
|
||||||
|
@ -758,9 +756,11 @@ class TorrentManager(component.Component):
|
||||||
return DeferredList(deferreds).addBoth(on_all_resume_data_finished)
|
return DeferredList(deferreds).addBoth(on_all_resume_data_finished)
|
||||||
|
|
||||||
def load_resume_data_file(self):
|
def load_resume_data_file(self):
|
||||||
"""Loads the resume data from file for all the torrents
|
"""Load the resume data from file for all torrents
|
||||||
|
|
||||||
:returns: resume_data
|
:returns: resume_data
|
||||||
:rtype: dict
|
:rtype: dict
|
||||||
|
|
||||||
"""
|
"""
|
||||||
filename = "torrents.fastresume"
|
filename = "torrents.fastresume"
|
||||||
filepath = os.path.join(self.state_dir, filename)
|
filepath = os.path.join(self.state_dir, filename)
|
||||||
|
@ -786,9 +786,7 @@ class TorrentManager(component.Component):
|
||||||
return resume_data
|
return resume_data
|
||||||
|
|
||||||
def save_resume_data_file(self):
|
def save_resume_data_file(self):
|
||||||
"""
|
"""Saves the resume data file with the contents of self.resume_data"""
|
||||||
Saves the resume data file with the contents of self.resume_data.
|
|
||||||
"""
|
|
||||||
filename = "torrents.fastresume"
|
filename = "torrents.fastresume"
|
||||||
filepath = os.path.join(self.state_dir, filename)
|
filepath = os.path.join(self.state_dir, filename)
|
||||||
filepath_bak = filepath + ".bak"
|
filepath_bak = filepath + ".bak"
|
||||||
|
@ -850,6 +848,11 @@ class TorrentManager(component.Component):
|
||||||
self.torrents[torrent_id].handle.queue_position_bottom()
|
self.torrents[torrent_id].handle.queue_position_bottom()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def cleanup_torrents_prev_status(self):
|
||||||
|
"""Run cleanup_prev_status for each registered torrent"""
|
||||||
|
for torrent in self.torrents.iteritems():
|
||||||
|
torrent[1].cleanup_prev_status()
|
||||||
|
|
||||||
def on_set_max_connections_per_torrent(self, key, value):
|
def on_set_max_connections_per_torrent(self, key, value):
|
||||||
"""Sets the per-torrent connection limit"""
|
"""Sets the per-torrent connection limit"""
|
||||||
log.debug("max_connections_per_torrent set to %s...", value)
|
log.debug("max_connections_per_torrent set to %s...", value)
|
||||||
|
@ -863,11 +866,13 @@ class TorrentManager(component.Component):
|
||||||
self.torrents[key].set_max_upload_slots(value)
|
self.torrents[key].set_max_upload_slots(value)
|
||||||
|
|
||||||
def on_set_max_upload_speed_per_torrent(self, key, value):
|
def on_set_max_upload_speed_per_torrent(self, key, value):
|
||||||
|
"""Sets the per-torrent upload speed limit"""
|
||||||
log.debug("max_upload_speed_per_torrent set to %s...", value)
|
log.debug("max_upload_speed_per_torrent set to %s...", value)
|
||||||
for key in self.torrents.keys():
|
for key in self.torrents.keys():
|
||||||
self.torrents[key].set_max_upload_speed(value)
|
self.torrents[key].set_max_upload_speed(value)
|
||||||
|
|
||||||
def on_set_max_download_speed_per_torrent(self, key, value):
|
def on_set_max_download_speed_per_torrent(self, key, value):
|
||||||
|
"""Sets the per-torrent download speed limit"""
|
||||||
log.debug("max_download_speed_per_torrent set to %s...", value)
|
log.debug("max_download_speed_per_torrent set to %s...", value)
|
||||||
for key in self.torrents.keys():
|
for key in self.torrents.keys():
|
||||||
self.torrents[key].set_max_download_speed(value)
|
self.torrents[key].set_max_download_speed(value)
|
||||||
|
@ -1155,9 +1160,7 @@ class TorrentManager(component.Component):
|
||||||
self.handle_torrents_status_callback(self.torrents_status_requests.pop())
|
self.handle_torrents_status_callback(self.torrents_status_requests.pop())
|
||||||
|
|
||||||
def separate_keys(self, keys, torrent_ids):
|
def separate_keys(self, keys, torrent_ids):
|
||||||
"""Separates the input keys into keys for the Torrent class
|
"""Separates the input keys into torrent class keys and plugins keys"""
|
||||||
and keys for plugins.
|
|
||||||
"""
|
|
||||||
if self.torrents:
|
if self.torrents:
|
||||||
for torrent_id in torrent_ids:
|
for torrent_id in torrent_ids:
|
||||||
if torrent_id in self.torrents:
|
if torrent_id in self.torrents:
|
||||||
|
@ -1168,9 +1171,7 @@ class TorrentManager(component.Component):
|
||||||
return [], []
|
return [], []
|
||||||
|
|
||||||
def handle_torrents_status_callback(self, status_request):
|
def handle_torrents_status_callback(self, status_request):
|
||||||
"""
|
"""Build the status dictionary with torrent values"""
|
||||||
Builds the status dictionary with the values from the Torrent.
|
|
||||||
"""
|
|
||||||
d, torrent_ids, keys, diff = status_request
|
d, torrent_ids, keys, diff = status_request
|
||||||
status_dict = {}.fromkeys(torrent_ids)
|
status_dict = {}.fromkeys(torrent_ids)
|
||||||
torrent_keys, plugin_keys = self.separate_keys(keys, torrent_ids)
|
torrent_keys, plugin_keys = self.separate_keys(keys, torrent_ids)
|
||||||
|
@ -1187,10 +1188,9 @@ class TorrentManager(component.Component):
|
||||||
d.callback((status_dict, plugin_keys))
|
d.callback((status_dict, plugin_keys))
|
||||||
|
|
||||||
def torrents_status_update(self, torrent_ids, keys, diff=False):
|
def torrents_status_update(self, torrent_ids, keys, diff=False):
|
||||||
"""
|
"""Returns status dict for the supplied torrent_ids async
|
||||||
returns status dict for the supplied torrent_ids async
|
|
||||||
If the torrent states were updated recently (less than 1.5 seconds ago,
|
If torrent states updated recently post_torrent_updates is not called, cached state is used.
|
||||||
post_torrent_updates is not called. Instead the cached state is used.
|
|
||||||
|
|
||||||
:param torrent_ids: the torrent IDs to get the status on
|
:param torrent_ids: the torrent IDs to get the status on
|
||||||
:type torrent_ids: list of str
|
:type torrent_ids: list of str
|
||||||
|
|
|
@ -51,9 +51,6 @@ class TorrentTestCase(unittest.TestCase):
|
||||||
return component.start()
|
return component.start()
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
if self.torrent:
|
|
||||||
self.torrent.prev_status_cleanup_loop.stop()
|
|
||||||
|
|
||||||
deluge.core.torrent.component = self.original_component
|
deluge.core.torrent.component = self.original_component
|
||||||
|
|
||||||
def on_shutdown(result):
|
def on_shutdown(result):
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue