mirror of
https://github.com/codex-storage/deluge.git
synced 2025-01-12 04:24:27 +00:00
Improvements and bug fixes
This commit is contained in:
parent
5cd86aa5bc
commit
0f67dc168b
@ -427,12 +427,9 @@ class Core(component.Component):
|
||||
for torrent_id in torrent_ids:
|
||||
self.torrentmanager[torrent_id].resume()
|
||||
|
||||
def create_torrent_status(self, torrent_id, torrent_keys, plugin_keys, diff=False, update=True):
|
||||
def create_torrent_status(self, torrent_id, torrent_keys, plugin_keys, diff=False, update=False):
|
||||
try:
|
||||
if update:
|
||||
status = self.torrentmanager[torrent_id].get_status(torrent_keys, diff)
|
||||
else:
|
||||
status = self.torrentmanager[torrent_id].create_status_dict(torrent_keys, diff)
|
||||
status = self.torrentmanager[torrent_id].get_status(torrent_keys, diff, update=update)
|
||||
except KeyError:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
@ -106,14 +106,14 @@ def tracker_error_filter(torrent_ids, values):
|
||||
# If this is a tracker_host, then we need to filter on it
|
||||
if values[0] != "Error":
|
||||
for torrent_id in torrent_ids:
|
||||
if values[0] == tm[torrent_id].create_status_dict(["tracker_host"])["tracker_host"]:
|
||||
if values[0] == tm[torrent_id].get_status(["tracker_host"])["tracker_host"]:
|
||||
filtered_torrent_ids.append(torrent_id)
|
||||
return filtered_torrent_ids
|
||||
|
||||
# Check all the torrent's tracker_status for 'Error:' and only return torrent_ids
|
||||
# that have this substring in their tracker_status
|
||||
for torrent_id in torrent_ids:
|
||||
if _("Error") + ":" in tm[torrent_id].create_status_dict(["tracker_host"])["tracker_host"]:
|
||||
if _("Error") + ":" in tm[torrent_id].get_status(["tracker_host"])["tracker_host"]:
|
||||
filtered_torrent_ids.append(torrent_id)
|
||||
return filtered_torrent_ids
|
||||
|
||||
@ -192,7 +192,7 @@ class FilterManager(component.Component):
|
||||
#leftover filter arguments:
|
||||
#default filter on status fields.
|
||||
for torrent_id in list(torrent_ids):
|
||||
status = self.torrents[torrent_id].create_status_dict(filter_dict.keys()) #status={key:value}
|
||||
status = self.torrents[torrent_id].get_status(filter_dict.keys()) #status={key:value}
|
||||
for field, values in filter_dict.iteritems():
|
||||
if (not status[field] in values) and torrent_id in torrent_ids:
|
||||
torrent_ids.remove(torrent_id)
|
||||
@ -213,7 +213,7 @@ class FilterManager(component.Component):
|
||||
items = dict((field, self.tree_fields[field]()) for field in tree_keys)
|
||||
|
||||
for torrent_id in list(torrent_ids):
|
||||
status = self.core.create_torrent_status(torrent_id, torrent_keys, plugin_keys, update=False) #status={key:value}
|
||||
status = self.core.create_torrent_status(torrent_id, torrent_keys, plugin_keys) #status={key:value}
|
||||
for field in tree_keys:
|
||||
value = status[field]
|
||||
items[field][value] = items[field].get(value, 0) + 1
|
||||
@ -261,7 +261,7 @@ class FilterManager(component.Component):
|
||||
|
||||
def filter_state_active(self, torrent_ids):
|
||||
for torrent_id in list(torrent_ids):
|
||||
status = self.torrents[torrent_id].create_status_dict(["download_payload_rate", "upload_payload_rate"])
|
||||
status = self.torrents[torrent_id].get_status(["download_payload_rate", "upload_payload_rate"])
|
||||
if status["download_payload_rate"] or status["upload_payload_rate"]:
|
||||
pass #ok
|
||||
else:
|
||||
|
@ -224,6 +224,9 @@ class Torrent(object):
|
||||
self.forcing_recheck = False
|
||||
self.forcing_recheck_paused = False
|
||||
|
||||
self.update_status(self.handle.status())
|
||||
self._create_status_funcs()
|
||||
|
||||
if log.isEnabledFor(logging.DEBUG):
|
||||
log.debug("Torrent object created.")
|
||||
|
||||
@ -407,10 +410,9 @@ class Torrent(object):
|
||||
self.update_state()
|
||||
break
|
||||
|
||||
# Do we really need this?
|
||||
#self.options["file_priorities"] = self.handle.file_priorities()
|
||||
#if self.options["file_priorities"] != list(file_priorities):
|
||||
# log.warning("File priorities were not set for this torrent")
|
||||
# In case values in file_priorities were faulty (old state?)
|
||||
# we make sure the stored options are in sync
|
||||
self.options["file_priorities"] = self.handle.file_priorities()
|
||||
|
||||
# Set the first/last priorities if needed
|
||||
if self.options["prioritize_first_last_pieces"]:
|
||||
@ -489,12 +491,12 @@ class Torrent(object):
|
||||
# This is an error'd torrent
|
||||
self.state = "Error"
|
||||
self.set_status_message(status.error)
|
||||
if self.handle_is_paused:
|
||||
if handle_is_paused:
|
||||
self.handle.auto_managed(False)
|
||||
return
|
||||
|
||||
if ltstate == LTSTATE["Queued"] or ltstate == LTSTATE["Checking"]:
|
||||
if self.handle_is_paused:
|
||||
if handle_is_paused:
|
||||
self.state = "Paused"
|
||||
else:
|
||||
self.state = "Checking"
|
||||
@ -668,7 +670,7 @@ class Torrent(object):
|
||||
self.calculate_last_seen_complete()
|
||||
return self._last_seen_complete
|
||||
|
||||
def get_status(self, keys, diff=False):
|
||||
def get_status(self, keys, diff=False, update=False):
|
||||
"""
|
||||
Returns the status of the torrent based on the keys provided
|
||||
|
||||
@ -677,22 +679,62 @@ class Torrent(object):
|
||||
:param diff: if True, will return a diff of the changes since the last
|
||||
call to get_status based on the session_id
|
||||
:type diff: bool
|
||||
:param update: if True, the status will be updated from libtorrent
|
||||
if False, the cached values will be returned
|
||||
:type update: bool
|
||||
|
||||
:returns: a dictionary of the status keys and their values
|
||||
:rtype: dict
|
||||
|
||||
"""
|
||||
status = self.handle.status()
|
||||
self.update_status(status)
|
||||
return self.create_status_dict(keys)
|
||||
if update:
|
||||
self.update_status(self.handle.status())
|
||||
|
||||
if not keys:
|
||||
keys = self.status_funcs.keys()
|
||||
|
||||
status_dict = {}
|
||||
|
||||
for key in keys:
|
||||
status_dict[key] = self.status_funcs[key]()
|
||||
|
||||
if diff:
|
||||
session_id = self.rpcserver.get_session_id()
|
||||
if session_id in self.prev_status:
|
||||
# We have a previous status dict, so lets make a diff
|
||||
status_diff = {}
|
||||
for key, value in status_dict.items():
|
||||
if key in self.prev_status[session_id]:
|
||||
if value != self.prev_status[session_id][key]:
|
||||
status_diff[key] = value
|
||||
else:
|
||||
status_diff[key] = value
|
||||
|
||||
self.prev_status[session_id] = status_dict
|
||||
return status_diff
|
||||
|
||||
self.prev_status[session_id] = status_dict
|
||||
return status_dict
|
||||
|
||||
return status_dict
|
||||
|
||||
def update_status(self, status):
|
||||
"""
|
||||
Updates the cached status.
|
||||
|
||||
:param status: a libtorrent status
|
||||
:type status: libtorrent.torrent_status
|
||||
|
||||
"""
|
||||
#import datetime
|
||||
#print datetime.datetime.now().strftime("%H:%M:%S.%f"),
|
||||
#print " update_status"
|
||||
self.status = status
|
||||
|
||||
if self.torrent_info is None and self.has_metadata():
|
||||
self.torrent_info = self.handle.get_torrent_info()
|
||||
|
||||
if not self.status_funcs:
|
||||
def _create_status_funcs(self):
|
||||
#if you add a key here->add it to core.py STATUS_KEYS too.
|
||||
self.status_funcs = {
|
||||
"active_time": lambda: self.status.active_time,
|
||||
@ -763,36 +805,6 @@ class Torrent(object):
|
||||
"total_size": self.ti_total_size,
|
||||
}
|
||||
|
||||
def create_status_dict(self, keys, diff=False):
|
||||
# Create the desired status dictionary and return it
|
||||
status_dict = {}
|
||||
|
||||
if not keys:
|
||||
keys = self.status_funcs.keys()
|
||||
|
||||
for key in keys:
|
||||
status_dict[key] = self.status_funcs[key]()
|
||||
|
||||
session_id = self.rpcserver.get_session_id()
|
||||
if diff:
|
||||
if session_id in self.prev_status:
|
||||
# We have a previous status dict, so lets make a diff
|
||||
status_diff = {}
|
||||
for key, value in status_dict.items():
|
||||
if key in self.prev_status[session_id]:
|
||||
if value != self.prev_status[session_id][key]:
|
||||
status_diff[key] = value
|
||||
else:
|
||||
status_diff[key] = value
|
||||
|
||||
self.prev_status[session_id] = status_dict
|
||||
return status_diff
|
||||
|
||||
self.prev_status[session_id] = status_dict
|
||||
return status_dict
|
||||
|
||||
return status_dict
|
||||
|
||||
def ti_comment(self):
|
||||
if self.has_metadata():
|
||||
try:
|
||||
|
@ -161,7 +161,7 @@ class TorrentManager(component.Component):
|
||||
|
||||
self.torrents_status_requests = []
|
||||
self.status_dict = {}
|
||||
self.state_update_alert_start = None
|
||||
self.last_state_update_alert_ts = 0
|
||||
|
||||
# Register set functions
|
||||
self.config.register_set_function("max_connections_per_torrent",
|
||||
@ -207,7 +207,7 @@ class TorrentManager(component.Component):
|
||||
self.alerts.register_handler("file_completed_alert",
|
||||
self.on_alert_file_completed)
|
||||
self.alerts.register_handler("state_update_alert",
|
||||
self.state_update_alert)
|
||||
self.on_alert_state_update)
|
||||
|
||||
def start(self):
|
||||
# Get the pluginmanager reference
|
||||
@ -666,9 +666,7 @@ class TorrentManager(component.Component):
|
||||
for s in state.torrents:
|
||||
setattr(s, attr, getattr(state_tmp, attr, None))
|
||||
except Exception, e:
|
||||
log.warning("Unable to update state file to a compatible version: %s", e)
|
||||
import traceback
|
||||
print traceback.format_exc()
|
||||
log.exception("Unable to update state file to a compatible version: %s", e)
|
||||
|
||||
# Reorder the state.torrents list to add torrents in the correct queue
|
||||
# order.
|
||||
@ -1138,9 +1136,9 @@ class TorrentManager(component.Component):
|
||||
torrent_keys = list(set(keys) - set(leftover_keys))
|
||||
return torrent_keys, leftover_keys
|
||||
|
||||
def state_update_alert(self, alert):
|
||||
self.state_update_alert_start = time.time()
|
||||
def on_alert_state_update(self, alert):
|
||||
log.debug("on_status_notification: %s", alert.message())
|
||||
self.last_state_update_alert_ts = time.time()
|
||||
|
||||
for s in alert.status:
|
||||
torrent_id = str(s.info_hash)
|
||||
@ -1150,6 +1148,9 @@ class TorrentManager(component.Component):
|
||||
self.handle_torrents_status_callback(self.torrents_status_requests.pop())
|
||||
|
||||
def handle_torrents_status_callback(self, status_request):
|
||||
"""
|
||||
Builds the status dictionary with the values from the Torrent.
|
||||
"""
|
||||
d, torrent_ids, keys, diff = status_request
|
||||
status_dict = {}.fromkeys(torrent_ids)
|
||||
torrent_keys, plugin_keys = self.separate_keys(keys, torrent_ids)
|
||||
@ -1162,21 +1163,32 @@ class TorrentManager(component.Component):
|
||||
print "Missing torrent id:", torrent_id
|
||||
del status_dict[torrent_id]
|
||||
else:
|
||||
status_dict[torrent_id] = self.torrents[torrent_id].create_status_dict(torrent_keys, diff)
|
||||
status_dict[torrent_id] = self.torrents[torrent_id].get_status(torrent_keys, diff)
|
||||
self.status_dict = status_dict
|
||||
d.callback((status_dict, plugin_keys))
|
||||
|
||||
def torrents_status_update(self, torrent_ids, keys, diff=False):
|
||||
"""
|
||||
returns all torrents , optionally filtered by filter_dict.
|
||||
If the torrent states were updated recently (less than two seconds ago,
|
||||
returns status dict for the supplied torrent_ids async
|
||||
If the torrent states were updated recently (less than 1.5 seconds ago,
|
||||
post_torrent_updates is not called. Instead the cached state is used.
|
||||
|
||||
:param torrent_ids: the torrent IDs to get the status on
|
||||
:type torrent_ids: list of str
|
||||
:param keys: the keys to get the status on
|
||||
:type keys: list of str
|
||||
:param diff: if True, will return a diff of the changes since the last
|
||||
call to get_status based on the session_id
|
||||
:type diff: bool
|
||||
|
||||
:returns: a status dictionary for the equested torrents.
|
||||
:rtype: dict
|
||||
|
||||
"""
|
||||
d = Deferred()
|
||||
now = time.time()
|
||||
# Less than two seconds since last time the torrent states were updated
|
||||
if self.state_update_alert_start and \
|
||||
(now - self.state_update_alert_start) < 2:
|
||||
# If last update was recent, use cached data instead of request updates from libtorrent
|
||||
if (now - self.last_state_update_alert_ts) < 1.5:
|
||||
reactor.callLater(0, self.handle_torrents_status_callback, (d, torrent_ids, keys, diff))
|
||||
else:
|
||||
# Ask libtorrent for status update
|
||||
|
@ -202,8 +202,6 @@ class StatusBar(component.Component):
|
||||
# Get some config values
|
||||
client.core.get_config_values(["max_connections_global", "max_download_speed",
|
||||
"max_upload_speed", "dht"]).addCallback(update_config_values)
|
||||
# Called from update a few milliseconds later
|
||||
#self.send_status_request()
|
||||
|
||||
def stop(self):
|
||||
# When stopped, we just show the not connected thingy
|
||||
|
@ -176,8 +176,6 @@ class SystemTray(component.Component):
|
||||
self._on_max_download_speed(configs["max_download_speed"])
|
||||
self._on_max_upload_speed(configs["max_upload_speed"])
|
||||
client.core.get_config_values(["max_download_speed", "max_upload_speed"]).addCallback(update_config_values)
|
||||
# This is called from update a few milliseconds later, so this line can be deleted
|
||||
#self.send_status_request()
|
||||
|
||||
def start(self):
|
||||
self.__start()
|
||||
|
@ -47,10 +47,8 @@ class SessionProxy(component.Component):
|
||||
The SessionProxy component is used to cache session information client-side
|
||||
to reduce the number of RPCs needed to provide a rich user interface.
|
||||
|
||||
On start-up it will query the Core for a full status of all the torrents in
|
||||
the session. After that point, it will query the Core for only changes in
|
||||
the status of the torrents and will try to satisfy client requests from the
|
||||
cache.
|
||||
It will query the Core for only changes in the status of the torrents
|
||||
and will try to satisfy client requests from the cache.
|
||||
|
||||
"""
|
||||
def __init__(self):
|
||||
@ -78,21 +76,6 @@ class SessionProxy(component.Component):
|
||||
# so that upcoming queries or status updates don't throw errors.
|
||||
self.torrents.setdefault(torrent_id, [time.time(), {}])
|
||||
self.cache_times.setdefault(torrent_id, {})
|
||||
# These initial keys are the ones used for the visible columns(by
|
||||
# default) on the GTK UI torrent view. If either the console-ui
|
||||
# or the web-ui needs additional keys, add them here;
|
||||
# There's NO need to fetch every bit of status information from
|
||||
# core if it's not going to be used. Additional status fields
|
||||
# will be queried later, for example, when viewing the status tab
|
||||
# of a torrent.
|
||||
#inital_keys = [
|
||||
# 'queue', 'state', 'name', 'total_wanted', 'progress', 'state',
|
||||
# 'download_payload_rate', 'upload_payload_rate', 'eta', 'owner'
|
||||
#]
|
||||
|
||||
#The the torrents status will be requested by torrentview, so this
|
||||
#only causes a second request for the same data withing a few miliseconds
|
||||
#self.get_torrents_status({'id': torrent_ids}, inital_keys)
|
||||
return client.core.get_session_state().addCallback(on_get_session_state)
|
||||
|
||||
def stop(self):
|
||||
|
Loading…
x
Reference in New Issue
Block a user