From 3afb542f064b87e2b024bb10cdd688a7620fbd62 Mon Sep 17 00:00:00 2001 From: Andrew Resch Date: Thu, 11 Sep 2008 09:20:29 +0000 Subject: [PATCH] Switch to torrent_handle::save_resume_data which makes resume data writing async --- deluge/core/torrent.py | 17 +++++++++--- deluge/core/torrentmanager.py | 34 +++++++++++++++++++----- libtorrent/bindings/python/src/entry.cpp | 8 ++++++ 3 files changed, 50 insertions(+), 9 deletions(-) diff --git a/deluge/core/torrent.py b/deluge/core/torrent.py index dd858b9a0..6cba44fc3 100644 --- a/deluge/core/torrent.py +++ b/deluge/core/torrent.py @@ -79,6 +79,9 @@ class Torrent: # Set the torrent_id for this torrent self.torrent_id = str(handle.info_hash()) + # Let's us know if we're waiting on a lt alert + self.waiting_on_resume_data = False + # We store the filename just in case we need to make a copy of the torrentfile if not filename: # If no filename was provided, then just use the infohash @@ -635,20 +638,28 @@ class Torrent: return True - def write_fastresume(self): + def save_resume_data(self): + """Signals libtorrent to build resume data for this torrent, it gets + returned in a libtorrent alert""" + self.handle.save_resume_data() + self.waiting_on_resume_data = True + + def write_resume_data(self, resume_data): """Writes the .fastresume file for the torrent""" - resume_data = lt.bencode(self.handle.write_resume_data()) + resume_data = lt.bencode(resume_data) path = "%s/%s.fastresume" % ( self.config["state_location"], self.torrent_id) - log.debug("Saving fastresume file: %s", path) try: self.delete_fastresume() + log.debug("Saving fastresume file: %s", path) fastresume = open(path, "wb") fastresume.write(resume_data) fastresume.close() except IOError: log.warning("Error trying to save fastresume file") + + self.waiting_on_resume_data = False def delete_fastresume(self): """Deletes the .fastresume file""" diff --git a/deluge/core/torrentmanager.py b/deluge/core/torrentmanager.py index 2cd74ffd1..31d510d2c 100644 --- a/deluge/core/torrentmanager.py +++ b/deluge/core/torrentmanager.py @@ -154,6 +154,10 @@ class TorrentManager(component.Component): self.on_alert_torrent_resumed) self.alerts.register_handler("state_changed_alert", self.on_alert_state_changed) + self.alerts.register_handler("save_resume_data_alert", + self.on_alert_save_resume_data) + self.alerts.register_handler("save_resume_data_failed_alert", + self.on_alert_save_resume_data_failed) def start(self): # Get the pluginmanager reference @@ -182,8 +186,16 @@ class TorrentManager(component.Component): self.torrents[key].handle.auto_managed(False) self.torrents[key].handle.pause() self.shutdown_torrent_pause_list.append(key) - while self.shutdown_torrent_pause_list: - time.sleep(0.1) + # We have to wait for all torrents to pause and write their resume data + wait = True + while self.shutdown_torrent_pause_list and wait: + wait = False + for torrent in self.torrents.values(): + if torrent.waiting_on_resume_data: + wait = True + break + + time.sleep(0.01) # Wait for all alerts self.alerts.handle_alerts(True) @@ -531,8 +543,8 @@ class TorrentManager(component.Component): def save_resume_data(self): """Saves resume data for all the torrents""" for torrent in self.torrents.values(): - torrent.write_fastresume() - + torrent.save_resume_data() + def queue_top(self, torrent_id): """Queue torrent to top""" if self.torrents[torrent_id].get_queue_position() == 0: @@ -607,7 +619,7 @@ class TorrentManager(component.Component): torrent.is_finished = True torrent.update_state() - torrent.write_fastresume() + torrent.save_resume_data() component.get("SignalManager").emit("torrent_finished", torrent_id) def on_alert_torrent_paused(self, alert): @@ -619,7 +631,7 @@ class TorrentManager(component.Component): component.get("SignalManager").emit("torrent_paused", torrent_id) # Write the fastresume file - self.torrents[torrent_id].write_fastresume() + self.torrents[torrent_id].save_resume_data() if torrent_id in self.shutdown_torrent_pause_list: self.shutdown_torrent_pause_list.remove(torrent_id) @@ -718,4 +730,14 @@ class TorrentManager(component.Component): torrent_id = str(alert.handle.info_hash()) self.torrents[torrent_id].update_state() component.get("SignalManager").emit("torrent_state_changed", torrent_id) + + def on_alert_save_resume_data(self, alert): + log.debug("on_alert_save_resume_data") + torrent = self.torrents[str(alert.handle.info_hash())] + torrent.write_resume_data(alert.resume_data) + + def on_alert_save_resume_data_failed(self, alert): + log.debug("on_alert_save_resume_data_failed: %s", alert.message()) + torrent = self.torrents[str(alert.handle.info_hash())] + torrent.waiting_on_resume_data = False diff --git a/libtorrent/bindings/python/src/entry.cpp b/libtorrent/bindings/python/src/entry.cpp index b24f6a2cf..861580708 100755 --- a/libtorrent/bindings/python/src/entry.cpp +++ b/libtorrent/bindings/python/src/entry.cpp @@ -49,6 +49,13 @@ struct entry_to_python } } + static PyObject* convert(boost::shared_ptr const& e) + { + if (!e) + return incref(Py_None); + return convert(*e); + } + static PyObject* convert(entry const& e) { return incref(convert0(e).ptr()); @@ -126,6 +133,7 @@ struct entry_from_python void bind_entry() { + to_python_converter, entry_to_python>(); to_python_converter(); entry_from_python(); }