From a65603e10c3ff82b1fb3a52b977780608f9a76cf Mon Sep 17 00:00:00 2001 From: Calum Lind Date: Wed, 16 Jul 2014 13:14:49 +0100 Subject: [PATCH] [#1032] Keep track of torrent errors over restarts * Add error_statusmsg to TorrentState * Adds a new set_error_statusmsg() method to force torrent error state. * Any torrent in error state will remain in that state on restart with additional message in status. * Any new libtorrent errors will override manually set ones. --- deluge/core/torrent.py | 39 ++++++++++++++++++++++++++++++----- deluge/core/torrentmanager.py | 6 ++++-- 2 files changed, 38 insertions(+), 7 deletions(-) diff --git a/deluge/core/torrent.py b/deluge/core/torrent.py index fcc22f9b2..cd6f80830 100644 --- a/deluge/core/torrent.py +++ b/deluge/core/torrent.py @@ -216,6 +216,11 @@ class Torrent(object): self.set_trackers(state.trackers) self.filename = state.filename self.is_finished = state.is_finished + last_sess_prepend = "[Error from Previous Session] " + if state.error_statusmsg and not state.error_statusmsg.startswith(last_sess_prepend): + self.error_statusmsg = last_sess_prepend + state.error_statusmsg + else: + self.error_statusmsg = state.error_statusmsg else: self.trackers = [tracker for tracker in self.handle.trackers()] self.is_finished = False @@ -224,6 +229,7 @@ class Torrent(object): self.filename = self.torrent_id else: self.filename = filename + self.error_statusmsg = None self.statusmsg = "OK" self.state = None @@ -592,16 +598,23 @@ class Torrent(object): log.debug("session.is_paused: %s", session_is_paused) # First we check for an error from libtorrent, and set the state to that if any occurred. - if status.error or self.statusmsg.startswith("Error:"): + if status.error or self.error_statusmsg: # This is an error'd torrent self.state = "Error" if status.error: - self.set_status_message(status.error) - if status.paused: - self.handle.auto_managed(False) + self.set_error_statusmsg(status.error) + self.set_status_message(self.error_statusmsg) + # This will be reverted upon resuming. + self.handle.auto_managed(False) + if not status.paused: + self.handle.pause() + if not status.error: + # As this is not a libtorrent Error we should emit a state changed event + component.get("EventManager").emit(TorrentStateChangedEvent(self.torrent_id, "Error")) return else: self.set_status_message("OK") + self.set_error_statusmsg(None) if self.moving_storage: self.state = "Moving" @@ -646,6 +659,19 @@ class Torrent(object): """ self.statusmsg = message + def set_error_statusmsg(self, message): + """Sets the torrent error status message. + + Note: + This will force a torrent into an error state. It is used for + setting those errors that are not covered by libtorrent. + + Args: + message (str): The error status message. + + """ + self.error_statusmsg = message + def get_eta(self): """Get the ETA for this torrent. @@ -853,7 +879,9 @@ class Torrent(object): files = [os.path.join(path, f) for f in files] return sum(os.stat(f).st_size for f in files if os.path.exists(f)) - if self.moving_storage: + if self.state == "Error": + progress = 100.0 + elif self.moving_storage: torrent_status = self.get_status(["files", "total_done"]) torrent_files = [f['path'] for f in torrent_status["files"]] dest_path_size = get_size(torrent_files, self.moving_storage_dest_path) @@ -1026,6 +1054,7 @@ class Torrent(object): # Reset the status message just in case of resuming an Error'd torrent self.set_status_message("OK") + self.set_error_statusmsg(None) if self.status.is_finished: # If the torrent has already reached it's 'stop_seed_ratio' then do not do anything diff --git a/deluge/core/torrentmanager.py b/deluge/core/torrentmanager.py index 8d26d8749..443898902 100644 --- a/deluge/core/torrentmanager.py +++ b/deluge/core/torrentmanager.py @@ -54,6 +54,7 @@ class TorrentState: queue=None, auto_managed=True, is_finished=False, + error_statusmsg=None, stop_ratio=2.00, stop_at_ratio=False, remove_at_ratio=False, @@ -654,7 +655,7 @@ class TorrentManager(component.Component): # Create the state for each Torrent and append to the list for torrent in self.torrents.values(): paused = False - if torrent.state == "Paused": + if torrent.state in ["Paused", "Error"]: paused = True torrent_state = TorrentState( @@ -674,6 +675,7 @@ class TorrentManager(component.Component): torrent.get_queue_position(), torrent.options["auto_managed"], torrent.is_finished, + torrent.error_statusmsg, torrent.options["stop_ratio"], torrent.options["stop_at_ratio"], torrent.options["remove_at_ratio"], @@ -1043,7 +1045,7 @@ class TorrentManager(component.Component): return # Set an Error message and pause the torrent alert_msg = decode_string(alert.message()).split(':', 1)[1].strip() - torrent.set_status_message("Error: Moving storage failed, %s" % alert_msg) + torrent.set_error_statusmsg("Failed to move storage: %s" % alert_msg) torrent.moving_storage = False torrent.pause() torrent.update_state()